年の月を並べ替える


19

関数や文字列の入力を受け取り、プログラムを書く、タイトルケースには、英語の月名を完全に綴ら:JanuaryFebruaryMarch、など(ヌル/ CR / LFは、あなたがそう選択した場合は[OK]を、いくつかの非英字で区切ら終了)のいずれか

  • 2つの入力を比較し、2番目の入力が最初の入力よりも大きい場合(月順)にTruthy値を返します。値が等しいとFalsey値になります

  • または、それらの任意のシーケンス(リスト、区切り文字列など)を時系列に並べ替えます

(課題の核心は、正しい辞書式ソートを提供するメソッド/式を定義することです。一部の言語では、どちらか一方の回答が短くなる場合があります)

内部時間解析メソッド(などstrptime)を使用して、月名を数字に変換したり、月名の事前にマッピングされたマッピングに変換することはできません。文字列自体のプロパティ、定義した控えめなルックアップテーブル、または巧妙なものを使用します。

機能する例、最初のものは規則で禁止されていますが...

import datetime
def is_later_month(a, b):
    '''
    Example of prohibited code because it relies on language 
    features about how to parse month names
    '''
    return datetime.strptime(a, '%B') < datetime.strptime(b, '%B') 

ただし、以下のバージョンは問題ありません。

months = {
    'January':  1, 'February':  2, 'March':      3,
    'April':    4, 'May':       5, 'June':       6,
    'July':     7, 'August':    8, 'September':  9,
    'October': 10, 'November': 11, 'December':  12,
}
def is_later_month(a, b):
    """
    Returns True/False when comparing two months.
    """
    return months[a] < months[b]

または、ソート機能を実行できます

months = {'as above...'}
def sort_months(l):
    """
    Sorts list and returns it. Different input and output than the above, 
    but equally valid. Sorting versus comparing might be shorter in your
    favorite language.
    """
    return sorted(l, key=lambda x: months[x]) 

テスト例

assert is_later_month('January', 'February')
assert is_later_month('January', 'December')
assert is_later_month('November', 'December')
assert not is_later_month('July', 'July')
assert not is_later_month('October', 'September')

月の名前を数値に変換するために内部時間解析メソッド(strptimeなど)を使用することはできません。これは少し不明瞭です。月の名前を含む言語の定義済みリテラルを使用できますか?
ルイスメンドー

その答えを削除します。しかし、何が許可され、何が許可されないのかはまだ明確ではありません。
ルイスメンドー

問題は、事前定義された配列など、これらの潜在的なトリックをすべて予測できないことです。おそらく、より良いオプションは、メイクアップされた名前など、あまり一般的でない文字列のセットを使用することでした。でも今は遅すぎると思う
ルイスメンドー

私が表現していることは明確ですか?Python monthsにすべての月の名前のリストである組み込み機能がある場合months[x] < months[y]、答えとして禁止したいと思います。月の名前のリストには、ランダムに生成された文字列よりもチャレンジを簡単/難しくする、より独特な機能(可変長、共通性)があります。
ニックT

はい、それは明らかだと思います。私はあなたが明示的に除外していない他の同様のケースがあるかもしれないことを恐れています(しかし、私はどのケースを知りません)
ルイスメンドー

回答:


41

ゼリー、19 バイト

11ị“bMAanlseovc”iµÞ

これは、引数としてリストを取り、それをソートする単項リンクです。オンラインでお試しください!

バックグラウンド

Jellyは、1ベースのモジュラーインデックスを使用します。11文字を取得するのに十分な頻度で月の名前を繰り返す場合、次の配列を取得します。

J a n u a r y J a n u
F e b r u a r y F e b
M a r c h M a r c h M
A p r i l A p r i l A
M a y M a y M a y M a
J u n e J u n e J u n
J u l y J u l y J u l
A u g u s t A u g u s
S e p t e m b e r S e
O c t o b e r O c t o
N o v e m b e r N o v
D e c e m b e r D e c

11 番目(最後)の列では、すべての文字が異なるため、それらを使用して月の順序を識別できます。

使い方

11ị“bMAanlseovc”iµÞ  Monadic link. Argument: A (array of months)

                 µ   Combine the preceding chain into a link.
                  Þ  Sort A by that link.
11ị                    Select the 11th character of the month's name.
   “bMAanlseovc”       Find the index of that character in "bMAanlseovc".
                       For 'u' ("January"), this returns 0 (not found).

1
好奇心が強いのですが、「bMAanlseovc」で月をどのようにランク付けしていますか?最初の文字一致のインデックス?
ljeabmreosn

説明を追加しました。
デニス

8
うわー、それは本当に賢いです!
-ljeabmreosn

15

x86マシンコード、26 25バイト

Hexdump:

ff 32 8b 01 34 c0 68 30 5f 43 01 59 f7 e1 91 5a
80 f2 c0 f7 e2 3b c8 d6 c3

アセンブリコード:

    push dword ptr [edx];
    mov eax, [ecx];
    xor al, 0xc0;
    push 0x01435f30;
    pop ecx;
    mul ecx;
    xchg eax, ecx;
    pop edx;
    xor dl, 0xc0;
    mul edx;
    cmp ecx, eax;
    _emit 0xd6;
    ret;

次のハッシュ関数は、月の名前を適切な順序で配置します(ブルートフォースによって検出されます)。

(x ^ 0xc0) * 0x01435f30

入力文字列の最初の4バイト(32ビット)に適用され、リトルエンディアン順に並べられます。次に、結果を比較しSALC、結果レジスタを設定するために使用します(al):

  • -1(true)月が順番になっている場合
  • 2番目の月が最初の月に先行する場合(または同じ場合)、0(偽)

4
私が感銘を受けた。コードゴルフ固有の言語を使用しない非常に短いコード。
ShuberFu

13

ゼリー、15 バイト

Oḅ32 354*%991µÞ

これは1つの遅い提出であるため、ここにはオンライン通訳リンクがありません。このプログラムは、ハッシュ関数354^(input interpreted as base 32 int) % 991をソートキーとして使用します。これにより、正しい順序で出力が行われます。累乗の結果が巨大であるため、プログラムはすぐに終了しません。「9月」の場合、0.24兆桁の数字を計算する必要があります。

ゼリーの説明:

              Þ         Sort by...
             µ          Monadic link consisting of...

O                       Convert month string to code points
 ḅ32                    Take base 32
     354*               Perform 354 to the power of the result
         %991           Take modulo 991

Pythonの概念実証スクリプト- powモジュラーべき乗の使用に注意してください。これははるかに効率的です。

import random

def base_convert(string, base):
    total = 0

    for c in string:
        total = total * base + ord(c)

    return total

def month_hash(month):
    return pow(354, base_convert(month, 32), 991)

months = ["January", "February", "March", "April", "May", "June", "July",
    "August", "September", "October", "November", "December"]
random.shuffle(months)

print(months)
print(sorted(months, key=month_hash))

5
「これは1つの遅い提出であるため、ここにはオンライン通訳のリンクはありません。」その場合、手作業で月を並べ替えることもできます。;-)
owacoder

たぶん、あなたは、機能要求をPRできたの最適化POW / MOD ...
ニック・T

@NickTこれは素晴らしいアイデアですが、残念ながらインタープリターのセットアップ方法(各演算子を個別に定義する方法)には少し注意が必要です。また、Jellyは3つ以上の引数を持つ演算子ではうまく機能しないため、別の演算子を定義してもまったく機能しません
...-Sp3000

独立したオペレータなどではなく、電源操作の後にモジュラー除算が続くかどうかを確認するための、より深い内省。簡単に聞こえますか?:P
ニックT

5

Python、64 61 57バイト

lambda x,y,g='bMAanlseovc'.find:g((x*4)[10])<g((y*4)[10])

ラムダは入力として2か月かかり、それらを比較します。Ideoneでテストします。

@ljeabmreosnに3バイトのゴルフをし、さらに3バイトの道を開いてくれてありがとう!


2
最後に、ゼリーの答えで正しい月をすばやく計算するために使用した黒魔術の背後にある秘密を明らかにします!
バリューインク

1
動作するs[10%len(s)]ように変更し(4*s)[10]ますか?
ljeabmreosn

1
@ljeabmreosnそれは確かに動作します。ありがとう!
デニス

1
まだ<ストライキ> AB </ストライキ>ラムダでデフォルト引数の使用を見ていない:P
ニック・T

4

Python、81 71バイト

lambda x,y,m='anebarprayunulugepctovec':m.index(x[1:3])<m.index(y[1:3])

https://repl.it/CluN/1

m2か月の2番目と3番目の文字のインデックスを比較します。

月のリストをソートする83バイトバージョン:

lambda x:sorted(x,key=lambda i:'JanFebMarAprMayJunJulAugSepOctNovDec'.index(i[:3]))

3

ルビー、58バイト

@atlasologistの回答から月のソートトリックを使用します

->a{a.sort_by{|i|"anebarprayunulugepctovec".index i[1,2]}}

比較関数は少し長く、63バイトです

->a,b{m=->i{"anebarprayunulugepctovec".index i[1,2]};m[a]<m[b]}

3

J、66 65バイト

f(m)= 2 *(ord(m [0])+ ord(m [-1]))// len(m)が12か月の限られた領域で有効な関数であるという事実を使用します。

>/@:('7/HEäWa<+0'&i.@(3 :'u:<.(#>y)%~+:+/3&u:({.>y),({:>y)')"0)"1

使用法:

   bigger =: >/@:('7/HEäWa<+0'&i.@(3 :'u:<.(#>y)%~+:+/3&u:({.>y),({:>y)')"0)"1
   bigger ('May'; 'March')
1
   bigger ('May'; 'June')
0

(決してこれが最良のアイデアではありませんが、私は誰かのランキングトリックを盗みたくありませんでした!)

@atlasologistの方法を使用した短いバージョンを次に示します。

J、63バイト

m=:[:}.3{.]
[:>/(12 2$'anebarprayunulugepctovec')i.([:m[),:[:m]

使用法:

   bigger =: [:>/(12 2$'anebarprayunulugepctovec')i.([:m[),:[:m]
   'January' bigger 'May'
0
   'June' bigger 'May'
1

そして、@ Dennisの巧妙な方法を使用したはるかに短いバージョン:

J、34バイト

>&:('ubMAanlseov'&i.@:{.@:(10&|.))

3

Haskell、74バイト

私の最初のコードゴルフ、イェーイ!これの一般的なアイデアは、ゼリーのトップアンサーと、月の名前が繰り返されるとき、11番目のキャラクターが常に一意であるという事実に触発されています。

e s=head.drop 10$cycle s;a#b=elem(e b)$tail$dropWhile(/=e a)"ubMAanlseovc"

これがどのように機能するかを確認するための無料版です:

order :: String
order = "ubMAanlseovc"

eleventhChar :: String -> Char
eleventhChar
  = head . drop 10 $ cycle

inOrder :: String -> String -> Bool
inOrder m1 m2
  = elem (eleventhChar m2) (tail $ dropWhile (/= eleventhChar m1) order)

このe関数は11番目のChar関数を表し(単相性の制限により4バイトを取り除くことはできません)、#中置関数はそのinOrder関数に対応します。

きちんとした小さなソリューションですが、より多くのバイトを削る方法があるかもしれません(私はこれを書いている間にいくつか見つけました!)


あなたは短縮できe s=head.drop 10$cycle sますが、使用して説明で行ったように.代わりに$e=head.drop 10.cycle。ただし、リストインデックス演算子の使用!!はさらに短くなりますe=(!!10).cycle
。– Laikoni

素晴らしい提案。時々あなたはこれらのことを見落としているだけです。どうもありがとう。間もなく編集します。
バウアー

2

Java、133 123

ゴルフ:

boolean f(String a,String b){return h(a)<h(b);}int h(String s){return"anebarprayunulugepctovec".indexOf(s.substring(1,3));}

私はアセンブラーの答えのような巧妙なテクニックを探していましたが、理解するのに時間がかかりすぎていたので、他の誰もが使ったのと同じテクニックを使いました。

ゴルフをしていない:

import java.util.Random;

public class SortTheMonthsOfTheYear {

  public static void main(String[] args) {
    // @formatter:off
    String[] MONTHS = new String[] {
        "January", "February", "March",
        "April",   "May",      "June",
        "July",    "August",   "September",
        "October", "November", "December"
    };
    // @formatter:on

    Random r = new Random();
    for (int i = 0; i < 100; ++i) {
      int m1 = r.nextInt(MONTHS.length);
      int m2 = r.nextInt(MONTHS.length);
      System.out.println("Input: " + MONTHS[m1] + " < " + MONTHS[m2]);
      System.out.println("Expected: " + (m1 < m2));
      System.out.println("Actual:   " + new SortTheMonthsOfTheYear().f(MONTHS[m1], MONTHS[m2]));
      System.out.println();
    }
  }

  // Begin golf
  boolean f(String a, String b) {
    return h(a) < h(b);
  }

  int h(String s) {
    return "anebarprayunulugepctovec".indexOf(s.substring(1, 3));
  }
  // End golf

}

次のsubstring場合は代わりに使用できますcharAt
-anatolyg

@anatolygありがとう、それがどうやって私を逃れたのかわかりません。また"" +、生charのs がないため、削除することもできました。

2

Linux上のARMマシン言語44 40バイト

e28fc001     add ip, pc, #1
e12fff1c     bx ip
6803         ldr r3, [r0, #0]
6808         ldr r0, [r1, #0]
4a05         ldr r2, [pc, #20]
f08303dd     eor.w r3, r3, #221
f08000dd     eor.w r0, r0, #221
4353         muls r3, r2
4350         muls r0, r2
4283         cmp r3, r0
bfac         ite ge
2000         movge r0, #0
2001         movlt r0, #1
4770         bx lr
2f68f24c

anatolygソリューションとは異なるハッシュ関数を使用しましたとを使用し、親指の命令を使用して数バイトを節約しようとしました(ただし、親指モードに入るのに8バイトを使用しました)。

GNURootを搭載したRaspberry PiまたはAndroidデバイスでこれを試すことができます。

int main(int argc,char**argv){
return ((int(*)(char*,char*))"\
\1\xc0\x8f\xe2\
\x1c\xff\x2f\xe1\
\3\x68\x8\x68\
\5\x4a\x83\xf0\
\xdd\3\x80\xf0\
\xdd\x43\x53\x43\
\x50\x4a\x83\x42\
\xac\bf\0\x20\
\1\x20\x70\x47\
\x4c\xf2\x68\x2f\
")(argv[1],argv[2]);}

実行するには

$ ./foo January February; echo $?

現在のバージョンでは、等号(およびその他)を正しく処理するようになりました。


Thumbモードに明示的に切り替えるコードは必要ないと思います。私が覚えていることから、あなたはあなたのプロシージャがサムモードであることをリンカに伝えるだけでよく、リンカはあなたのコードの呼び出し時に自動的にThumbモードに切り替えるようにプロシージャのアドレスのLSBを1に設定します。
アナトリグ

また、何をしbfacますか?
アナトリグ

@anatolyg ite geは、次の命令(movge r0, #0)を条件付きで実行しr3 >= r0ます。そうでない場合は、それに続く命令が実行されます(movlt r0, #1)。ここには数バイトを
削る

1

Perl 6、55バイト

*.sort({index 'anebarprayunulugepctovec',.substr(1,2)})

比較バージョンではさらに数バイト必要です。

{[<] @_».&{index 'anebarprayunulugepctovec',.substr(1,2)}}
{[<] .map: {index 'anebarprayunulugepctovec',.substr(1,2)}}

テスト:

#! /usr/bin/env perl6
use v6.c;
use Test;

my @months = <
  January February March April May June July
  August September October November December
>;

my &month-sort = *.sort({index 'anebarprayunulugepctovec',.substr(1,2)});

plan 100;

for ^100 {
  # 「.pick(*)」 returns all elements in random order
  is-deeply month-sort(@months.pick(*)), @months.List;
}

1

Haskell、118文字

data M=Ju|Fr|Mc|Ai|My|Je|Jy|Au|St|Oo|Ne|De deriving(Ord,Eq,Read)
r=read.([head,last]<*>).lines.take 4
a#b=(r a::M)<r b

各月の名前の最初と4番目の文字(または5月の3番目)が一意であるという事実を使用して、言語で自動的に解析および比較できるデータ型を定義します。'r'関数は、最初の4文字(またはそれ以下)を取得し、最初と最後を選択するだけで文字列を変換します。次に、「a#b」は値を比較する演算子です。

*Main> "June" # "March"
False
*Main> "June" # "July"
True
*Main> "January" # "July"
True
*Main> "January" # "November"
True
*Main> "December" # "November"
False

おそらくより効率的な方法で行うことができますが、月を表すために有用なデータ型を使用してそれをやってみたかったです。


1

PowerShell、96 88 63バイト

$input|Sort{'anebarprayunulugepctovec'.IndexOf((-join$_[1,2]))}

例えば

PS C:\Code> 'February', 'January', 'December', 'April' | .\monthsort.ps1
January
February
April
December

次に、リストを順番に並べ替える2番目の課題を行います。以前のバージョンでは、2か月のテストを比較しました。

v2.
$l,$r=$args|%{-join$_[1,2]};($d='anebarprayunulugepctovec').indexof($l)-lt$d.IndexOf($r)

v1.
$l,$r=$args|%{-join$_[1,2]};$r-match('an|eb|ar|pr|ay|un|ul|ug|ep|ct|ov|ec'-split$l)[1].Trim('|')

e.g.

PS C:\code> .\Test-MonthsInOrder.ps1 January February
True

月名の2番目の2文字に基づきます。



0

Javascript、118バイト

u=p=>{p=p.split` `.sort();c=[];for(i=0;i<12;i++){c.push(p["4 3 7 0 8 6 5 1 11 10 9 2".split` `[i]]);}return c.join` `}

おそらく、を削除してc使用することにより、より多くのゴ​​ルフをすることができますarray.mapが、これは私が今持っているものです...


for(i=0;i<12;)c.push(p[[4,3,7,0,8,6,5,1,11,10,9,2][i++]]);
pinkfloydx33

0

バッシュ、101バイト

これはis_laterのような関数です

f(){ s=ubMAanlseovc a=$1$1$1 b=$2$2$2 c=${a:10:1} d=${b:10:1} e=${s%$c*} f=${s%$d*};((${#e}<${#f}));}

テスト

$ f January December && echo later || echo not later
not later

0

k4、29

{x@<"ubMAanlseovc"?(*|11#)'x}

@Dennisの Jelly回答ポート。

これは、コンパレータではなくソーターです。興味深いことに、コンパレータは同じアルゴリズムで簡単に実装でき、1バイトだけ長くなります。

{(<)."ubMAanlseovc"?(*|11#)'x}

0

Bash + coreutils、94バイト 93バイト

s(){ x=FMAyulgSOND;for y;{ rev<<<${y:0:3}|tr -d -C $x|tr $x C-M;echo B$y;}|sort|cut -f2 -dB;}

これは、辞書式にソートする変換を考え出す試みです。変換キーをよく見るとFMAyulgSONDを 2月から12月までの月を見ることができます(変換後1月は空になります。「B」を区切り文字として使用すると、一番上に表示されます)。キーのない文字を反転、切り捨て、削除すると、このトリックを実行できます。

Cロケールを使用した90バイト

s(){ x=FMAyulgSOND;for y;{ rev<<<${y:0:3}|tr -d -C $x|tr $x C-M;echo \␉$y;}|sort|cut -f2;}

...ここで、theはタブ文字です。

Cロケールを使用した80バイト

s(){ x=anebarprayunulugepctovec;for y;{ echo ${x%${y:1:2}*}\␉$y;}|sort|cut -f2;}

... @ atlasologのメソッドを使用します。このアプローチを使用して、より多くのロケールを操作する方法にバインドされます。

テスト/使用法

s December November October September August July June May April March February January

出力:

January
February
March
April
May
June
July
August
September
October
November
December
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.