한 달의 월을 정렬


19

함수 또는 문자열 입력을합니다 프로그램을 작성, 제목의 경우, 영어 월 이름을 완전히 철자 : January, February, March, 등 (널 / CR / LF가 그렇게 선택하는 경우 OK, 일부 비 알파 문자로 구분 종료) 및 중

  • 두 번째 입력이 첫 번째보다 큰 경우 (월 순서로) 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)을 사용하여 월 이름을 숫자로 변환 할 수 없습니다. 이것은 다소 불분명합니다. 월 이름이 포함 된 언어의 미리 정의 된 리터럴을 사용할 수 있습니까?
Luis Mendo

그러면 답변을 삭제하겠습니다. 그러나 무엇이 허용되고 무엇이 허용되지 않는지는 여전히 명확하지 않습니다.
Luis Mendo

문제는 사전 정의 된 배열과 같은 모든 잠재적 인 트릭을 예상 할 수 없다는 것입니다. 아마도 더 나은 옵션은 구성 이름과 같이 덜 일반적인 문자열 세트를 사용하는 것입니다. 그러나 지금 추측하기에는 너무 늦었습니다.
Luis Mendo

내가 표현하고있는 것이 분명합니까? 파이썬 months에 모든 월 이름 목록이 내장 months[x] < months[y]되어 있다면 대답 으로 금지하고 싶습니다 . 월 이름 목록에는 좀 더 특이한 기능 (가변 길이, 공통성)이있어 무작위로 생성 된 문자열보다 더 어렵고 어렵습니다.
Nick T

예, 분명하다고 생각합니다. 나는 당신이 명시 적으로 배제하지 않은 다른 유사한 경우가 있을지 모른다는 것을 두려워합니다 (그러나 나는 어느 것을 알지 못합니다)
Luis Mendo

답변:


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

설명을 추가했습니다.
Dennis

8
와, 정말 영리 해요!
ljeabmreosn

15

x86 기계 코드, 26 25 바이트

16 진 덤프 :

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)
  • 두 번째 달이 첫 번째 달보다 앞에 오는 경우 0 (거짓)

4
나는 감동. 코드 골프 특정 언어를 사용하지 않는 매우 짧은 코드입니다.
ShuberFu

13

젤리 , 15 바이트

Oḅ32 354*%991µÞ

제출 이 느리기 때문에 온라인 통역사 링크가 없습니다 . 이 프로그램은 해싱 기능 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

파이썬 개념 증명 스크립트- 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
"하나의 느린 제출 이기 때문에 온라인 통역사 링크가 없습니다 ." 이 경우 몇 달을 손으로 정렬 할 수도 있습니다. ;-)
owacoder

아마도 pow / mod를 최적화하기위한 기능 요청을 PR 할 수있을 것입니다.
Nick T

@NickT 그것은 훌륭한 아이디어입니다. 그러나 불행히도 통역사의 설정 방식 (각 연산자가 따로 정의 된 방식)에 따라 조금 까다로울 수 있습니다. 그리고 Jelly는 두 개 이상의 인수를 가진 연산자와 잘 작동하지 않기 때문에 별도의 연산자를 정의하는 것도 효과가 없을 것입니다.
Sp3000

별도의 조작 자나 그 어떤 것도 아니라, 전력 작동에 모듈 식 분할이 있는지 알아보기위한 좀 더 심도있는 조사입니다. 쉽게 들리나요? : P
Nick T

5

파이썬, 64 61 57 바이트

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

람다는 입력으로 두 달이 걸리고 비교합니다. Ideone에서 테스트하십시오 .

3 바이트를 골라 내고 3 개 더 길을 포장 한 @ljeabmreosn에게 감사합니다!


2
마지막으로 젤리 답변에서 정확한 달을 신속하게 계산하는 데 사용한 흑 마법의 비밀을 밝혀 내십시오!
Value Ink

1
겠습니까는 변화 s[10%len(s)](4*s)[10]사용할 수 있습니까?
ljeabmreosn

1
@ljeabmreosn 그것은 실제로 작동합니다. 감사!
Dennis

1
아직 람다에서 기본 인수의 <strike> ab </ strike> 사용을 보지 못했습니다 : P
Nick T

4

파이썬, 81 71 바이트

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

https://repl.it/CluN/1

m두 달의 두 번째와 세 번째 문자의 색인을 비교합니다 .

개월 목록을 정렬하는 83 바이트 버전 :

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

3

루비, 58 바이트

@ atlasologist 's answer 의 월 정렬 트릭을 사용합니다 .

->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

하스켈, 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 함수를 나타내며 (내 생각에 monomorphism 제한으로 인해 4 바이트를 제거 할 수는 없습니다) #infix 함수는 함수에 해당 inOrder합니다.

깔끔한 작은 솔루션이지만 더 많은 바이트를 제거하는 방법이있을 수 있습니다 (이 글을 쓰는 동안 일부를 찾았습니다!)


당신은 단축 할 수 e s=head.drop 10$cycle s사용하여 설명에서했던 것처럼 .대신 $: e=head.drop 10.cycle. 그러나 목록 인덱스 연산자를 사용하는 !!것이 훨씬 짧습니다.e=(!!10).cycle
Laikoni

좋은 제안. 때때로 당신은 이러한 것들을 간과합니다. 고마워 곧 수정합니다.
bower

2

자바 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.

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 바이트를 불어하지만) 몇 바이트를 저장하기 위해 사용 Thumb 명령어로했습니다.

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 모드로 전환하는 코드가 필요하지 않다고 생각합니다. 내가 기억하는 것에서, 당신은 링커에게 당신의 프로 시저가 썸 모드에 있다고 말하면되고 링커는 당신의 프로 시저의 주소에서 LSB를 1로 설정하기 때문에 코드가 호출 될 때 프로세서는 Thumb 모드로 자동 전환 할 것이다.
anatolyg

또한 무엇을 bfac합니까?
anatolyg

@anatolyg는 ite ge조건에 따라 다음 명령 ( movge r0, #0)을 조건부로 실행하고 r3 >= r0, 그렇지 않으면 그 다음에 나오는 명령 ( )을 실행합니다 movlt r0, #1. 나는 여기에 몇 바이트를
넣을

1

펄 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

하스켈, 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

각 달 이름이 첫 번째와 네 번째 문자 (5 월의 3 번째 문자)에서 고유하다는 사실을 사용하여 언어별로 자동 구문 분석 및 비교할 수있는 데이터 유형을 정의합니다. 'r'함수는 처음 네 문자 (또는 그 이하)를 잡고 첫 번째와 마지막을 선택하여 문자열을 변환합니다. 그런 다음 '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

이제 목록을 순서대로 정렬하는 두 번째 과제가 있습니다. 이전 버전에서는 두 달 테스트를 비교했습니다.

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

월 이름의 두 번째 두 문자를 기준으로합니다.



0

자바 스크립트, 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;}

... 여기서 ␉는 탭 문자입니다.

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.