Sắp xếp các tháng trong năm


19

Viết một hàm hoặc chương trình mà sẽ đưa đầu vào chuỗi, hoàn toàn chính tả, tên tiếng Anh tháng trong trường hợp tiêu đề: January, February, March, vv (null / CR / LF chấm dứt OK, phân định với một số nhân vật phi-alpha nếu bạn lựa chọn) và một trong hai

  • so sánh hai đầu vào, trả về giá trị Truthy nếu đầu vào thứ hai lớn hơn (theo thứ tự tháng) so với đầu vào thứ nhất. Giá trị bằng nhau dẫn đến giá trị Falsey

  • hoặc sắp xếp một chuỗi tùy ý (danh sách, chuỗi phân cách, v.v.) của chúng theo thứ tự thời gian

(Mấu chốt của thách thức là xác định một phương thức / biểu thức đưa ra cách sắp xếp từ vựng chính xác. Một số ngôn ngữ có thể có câu trả lời ngắn hơn với một hoặc khác)

Bạn không thể sử dụng bất kỳ phương pháp phân tích thời gian nội bộ nào (ví dụ strptime) để dịch tên tháng thành số hoặc ánh xạ đóng hộp trước tên tháng. Sử dụng các thuộc tính của chính các chuỗi, một bảng tra cứu tuyệt vời mà bạn xác định hoặc một cái gì đó thông minh.

Thí dụ

Các ví dụ chức năng, mặc dù lần đầu tiên bị cấm theo quy tắc ...

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

Các phiên bản dưới đây là OK, bởi vì chúng tôi mã thông tin đó

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]

Hoặc bạn có thể làm một chức năng sắp xếp

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

Ví dụ kiểm tra

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

Bạn không thể sử dụng bất kỳ phương pháp phân tích thời gian nội bộ nào (ví dụ: strptime) để dịch tên tháng thành một số. Điều này là một chút không rõ ràng. Chúng ta có thể sử dụng nghĩa đen được xác định trước bằng ngôn ngữ có chứa tên của tháng không?
Luis Mendo

Tôi sẽ xóa câu trả lời của tôi sau đó. Nhưng vẫn chưa rõ những gì được phép và những gì không.
Luis Mendo

Vấn đề là bạn không thể lường trước tất cả các thủ thuật tiềm năng đó, chẳng hạn như mảng được xác định trước. Có lẽ một lựa chọn tốt hơn sẽ là sử dụng một chuỗi các chuỗi ít phổ biến hơn, chẳng hạn như tên được tạo. Nhưng tôi đoán là đã quá muộn rồi
Luis Mendo

Là những gì tôi đang thể hiện rõ ràng? Nếu Python có nội monthsdung là danh sách tất cả các tên Tháng, tôi muốn cấm months[x] < months[y]làm câu trả lời. Danh sách các tên tháng có một số tính năng đặc biệt hơn (độ dài khác nhau, tính phổ biến) làm cho thử thách trở nên dễ dàng / khó khăn hơn so với các chuỗi được tạo ngẫu nhiên.
Nick T

Vâng, tôi nghĩ rằng nó rõ ràng. Tôi chỉ sợ rằng có thể có những trường hợp tương tự khác mà bạn không loại trừ rõ ràng (nhưng tôi không biết đó là trường hợp nào)
Luis Mendo

Câu trả lời:


41

Thạch , 19 byte

11ị“bMAanlseovc”iµÞ

Đây là một liên kết đơn âm lấy một danh sách làm đối số và sắp xếp nó. Hãy thử trực tuyến!

Lý lịch

Jelly sử dụng lập chỉ mục mô-đun, dựa trên 1. Nếu chúng ta lặp lại tên tháng thường đủ để có được 11 ký tự, chúng ta sẽ nhận được mảng sau.

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

Trong cột thứ 11 (cuối cùng), tất cả các ký tự đều khác nhau, vì vậy chúng ta có thể sử dụng chúng để xác định thứ tự của các tháng.

Làm thế nào nó hoạt động

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
Chỉ tò mò, làm thế nào bạn xếp hạng tháng với "bMAanlseovc"? Chỉ số phù hợp với nhân vật đầu tiên?
ljispmreosn

Tôi đã thêm một lời giải thích.
Dennis

8
Wow, thật là thông minh!
ljispmreosn

15

mã máy x86, 26 25 byte

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

Mã hội:

    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;

Hàm băm sau đây xảy ra để đặt tên tháng theo thứ tự phù hợp (được tìm thấy bởi brute force):

(x ^ 0xc0) * 0x01435f30

Nó được áp dụng cho 4 byte đầu tiên (32 bit) của chuỗi đầu vào, được sắp xếp theo thứ tự cuối nhỏ. Sau đó so sánh kết quả và sử dụng SALCđể thiết lập thanh ghi kết quả (al):

  • -1 (đúng) nếu các tháng theo thứ tự
  • 0 (sai) nếu tháng thứ hai trước tháng đầu tiên (hoặc chúng giống nhau)

4
Tôi rất ấn tượng. Một đoạn mã rất ngắn mà không sử dụng ngôn ngữ cụ thể của mã golf.
ShuberFu

13

Thạch , 15 byte

Oḅ32 354*%991µÞ

Không có liên kết phiên dịch trực tuyến ở đây vì đây là một trình chậm . Chương trình sử dụng chức năng băm 354^(input interpreted as base 32 int) % 991làm khóa sắp xếp, điều này xảy ra để đưa ra kết quả theo đúng thứ tự. Chương trình sẽ không hoàn thành sớm bất cứ lúc nào vì kết quả của số mũ là rất lớn - cho "tháng 9", một số có 0,24 triệu chữ số cần phải được tính!

Jelly giải thích:

              Þ         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 bằng chứng về kịch bản khái niệm - lưu ý việc sử dụng powlũy thừa mô đun, hiệu quả hơn nhiều:

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
"Không có liên kết phiên dịch trực tuyến ở đây vì đây là một trình chậm ." Trong trường hợp đó, bạn cũng có thể sắp xếp các tháng bằng tay. ;-)
owacoder

Có lẽ bạn có thể PR một yêu cầu tính năng để tối ưu hóa pow / mod ...
Nick T

@NickT Đó là một ý tưởng tuyệt vời, nhưng thật không may với cách thiết lập trình thông dịch (với mỗi toán tử được xác định riêng), điều đó có thể hơi khó. Và Jelly không hoạt động tốt với các toán tử có nhiều hơn hai đối số, do đó, việc xác định một toán tử riêng biệt cũng sẽ không hoạt động ...
Sp3000

Không phải là một nhà điều hành riêng biệt hoặc bất cứ điều gì, chỉ cần một số nội tâm sâu sắc hơn để xem nếu một hoạt động năng lượng được theo sau bởi phân chia mô-đun. Nghe có vẻ dễ dàng? : P
Nick T

5

Python, 64 61 57 byte

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

Lambda mất hai tháng làm đầu vào và so sánh chúng. Kiểm tra nó trên Ideone .

Cảm ơn @ljispmreosn vì đã chơi golf 3 byte và mở đường cho 3 người nữa!


2
Cuối cùng, bạn tiết lộ bí mật đằng sau phép thuật đen bạn đã sử dụng để nhanh chóng tính toán tháng chính xác trong câu trả lời Jelly của bạn!
Mực giá trị

1
Sẽ thay đổi s[10%len(s)]để (4*s)[10]làm việc?
ljispmreosn

1
@ljispmreosn Điều đó thực sự hoạt động. Cảm ơn!
Dennis

1
Chưa thấy việc sử dụng <strike> ab </ strike> trong các đối số mặc định trong lambda: P
Nick T

4

Python, 81 71 byte

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

https://repl.it/CluN/1

So sánh chỉ số trong mcác chữ cái thứ hai và thứ ba của hai tháng.

Phiên bản 83 byte để sắp xếp danh sách các tháng:

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


3

J, 66 65 byte

Sử dụng thực tế là f (m) = 2 * (ord (m [0]) + ord (m [-1])) // len (m) là một hàm hợp lệ trong miền giới hạn của 12 tháng:

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

Sử dụng:

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

(Đây không phải là ý tưởng tốt nhất, nhưng tôi không muốn đánh cắp mánh khóe xếp hạng của bất kỳ ai!)

Đây là phiên bản ngắn hơn sử dụng phương pháp của @ atlasologist :

J, 63 byte

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

Sử dụng:

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

Và một phiên bản ngắn hơn nhiều bằng cách sử dụng phương pháp thông minh của @ Dennis :

J, 34 byte

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

3

Haskell, 74 byte

Golf mã đầu tiên của tôi, yay! Ý tưởng chung của cái này được lấy cảm hứng từ câu trả lời hàng đầu trong Jelly, và thực tế là khi tên tháng được đạp xe, nhân vật thứ 11 luôn là duy nhất.

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

Đây là một phiên bản chưa được chỉnh sửa để xem nó hoạt động như thế nào:

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)

Các echức năng đại diện cho chức năng eleventhChar (buồn bã không thể lột 4 byte do sự hạn chế monomorphism tôi nghĩ) và #tương ứng với chức năng ghi vào đến inOrderchức năng.

Một giải pháp nhỏ gọn, nhưng có thể có nhiều cách để loại bỏ nhiều byte hơn (tôi đã tìm thấy một số trong khi viết này!)


Bạn có thể rút ngắn e s=head.drop 10$cycle snhư bạn đã làm trong lời giải thích của mình bằng cách sử dụng .thay vì $: e=head.drop 10.cycle. Tuy nhiên, việc sử dụng toán tử chỉ mục danh sách !!thậm chí còn ngắn hơn:e=(!!10).cycle
Laikoni 17/8/2016

Gợi ý tuyệt vời. Đôi khi bạn chỉ bỏ qua những điều này. Cảm ơn rất nhiều. Sẽ chỉnh sửa nó trong thời gian ngắn.
Chòi

2

Java, 133 123

Chơi gôn

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

Tôi đã tìm kiếm một kỹ thuật thông minh như trong câu trả lời của trình biên dịch chương trình, nhưng mất quá nhiều thời gian để tìm ra nên tôi đã sử dụng cùng một kỹ thuật mà mọi người khác đã sử dụng.

Ung dung:

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

}

Bạn có thể sử dụng substringthay thế nếucharAt
anatolyg

@anatolyg cảm ơn, tôi không chắc người đó đã trốn thoát tôi như thế nào. Tôi cũng có thể loại bỏ "" +vì không còn nguyên liệu charnữa.

2

Ngôn ngữ máy ARM trên Linux 44 40 byte

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

Tôi đã sử dụng một hàm băm khác với giải pháp của anatolyg và đã thử sử dụng các hướng dẫn ngón tay cái để lưu một vài byte (mặc dù tôi đã thổi 8 byte vào chế độ ngón tay cái).

Bạn có thể dùng thử trên thiết bị Raspberry Pi hoặc Android với GNURoot.

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]);}

Để chạy nhập một cái gì đó như

$ ./foo January February; echo $?

Phiên bản hiện tại xử lý trường hợp bình đẳng (và các trường hợp khác) một cách chính xác.


Tôi nghĩ bạn không cần mã chuyển rõ ràng sang chế độ Thumb. Từ những gì tôi nhớ, bạn chỉ cần thông báo cho trình liên kết quy trình của bạn ở chế độ ngón tay cái và trình liên kết sẽ đặt LSB trong địa chỉ thủ tục của bạn thành 1, do đó bộ xử lý sẽ tự động chuyển sang chế độ Thumb khi mã của bạn được gọi.
anatolyg

Ngoài ra, bfaclàm gì?
anatolyg

@anatolyg có ite geđiều kiện thực hiện lệnh tiếp theo ( movge r0, #0) nếu r3 >= r0không, nếu không thì lệnh theo sau được thực thi ( movlt r0, #1). Tôi nghĩ rằng có chỗ để loại bỏ một vài byte ở đây nhưng tôi không có thời gian để làm việc này :-)
trần nhà

1

Perl 6 , 55 byte

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

Nó sẽ yêu cầu thêm một vài byte cho các phiên bản so sánh:

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

Kiểm tra:

#! /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 ký tự

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

Sử dụng thực tế là mỗi tên tháng là duy nhất trong các ký tự đầu tiên và thứ tư (hoặc thứ 3 cho tháng 5) để xác định loại dữ liệu có thể được phân tích tự động và so sánh bằng ngôn ngữ. Hàm 'r' chuyển đổi một chuỗi bằng cách lấy bốn ký tự đầu tiên (hoặc ít hơn), sau đó chỉ cần chọn đầu tiên và cuối cùng. Sau đó, 'a # b' là toán tử để so sánh các giá trị:

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

Có lẽ có thể được thực hiện theo cách hiệu quả hơn, nhưng tôi muốn thử làm điều đó bằng cách sử dụng một loại dữ liệu hữu ích để biểu thị các tháng.


1

PowerShell, 96 88 63 byte

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

ví dụ

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

Bây giờ thử thách thứ hai là sắp xếp một danh sách theo thứ tự; các phiên bản trước đã so sánh thử nghiệm hai tháng:

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

Dựa trên hai ký tự thứ hai trong tên tháng.



0

Javascript, 118 byte

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ó thể chơi golf nhiều hơn, probobly bằng cách loại bỏ cvà sử dụng array.map, nhưng đây là những gì tôi có bây giờ ...


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

0

Bash, 101 byte

đây là chức năng như 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}));}

kiểm tra

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

0

k4, 29

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

Một cảng của câu trả lời Jelly @ Dennis .

Đây là bộ sắp xếp, không phải bộ so sánh; thật thú vị, bộ so sánh có thể thực hiện được một cách tầm thường bởi cùng một thuật toán và chỉ dài hơn một byte:

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

0

Bash + coreutils, 94 byte 93 byte

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

Đây là một nỗ lực để đưa ra một biến đổi sắp xếp theo từ vựng. Nếu bạn nhìn kỹ vào phím biến đổiFMAyulgSOND bạn có thể thấy các tháng từ tháng 2 đến tháng 12 (tháng 1 trở nên trống rỗng sau khi biến đổi; nó được kéo lên đầu bằng cách sử dụng 'B' làm dấu phân cách). Đảo ngược, cắt bớt và loại bỏ các chữ cái không khóa cho phép thủ thuật này được gỡ bỏ.

90 byte sử dụng ngôn ngữ C

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

... Trong đó ␉ là ký tự tab.

80 byte sử dụng ngôn ngữ C

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

... sử dụng phương pháp @ atlasolog. Giới hạn là một cách để sử dụng phương pháp này để làm việc với nhiều địa phương hơn.

Kiểm tra / Sử dụng

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

đầu ra:

January
February
March
April
May
June
July
August
September
October
November
December
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.