Yılın aylarını sırala


19

Bir fonksiyonu veya dize girdileri alır program yazın, başlık halinde ingilizce ay adlarını tam yazıldığından: January, February, Marchvb (boş / CR / LF bunu seçerseniz tamam olmayan bazı alfa karakteriyle sınırlanmış sonlandırıldı) ve ya

  • iki girişi karşılaştırır, ikinci giriş birinciden daha büyükse (ay sırasına göre) bir Doğruluk değeri döndürür. Eşit değerler bir Falsey değeriyle sonuçlanır

  • veya rastgele bir dizisini (liste, sınırlandırılmış dize vb.) kronolojik sırada sıralar

(Zorluğun temel noktası doğru sözlükbilimsel sıralamayı veren bir yöntem / ifade tanımlamaktır. Bazı dillerden biri veya diğeri ile daha kısa bir cevap olabilir)

strptimeAy adını bir sayıya veya ay adlarının önceden hazırlanmış bir eşlemesine çevirmek için dahili zaman ayrıştırma yöntemlerini (örn. ) Kullanamazsınız. Dizelerin özelliklerini, tanımladığınız cimri bir arama tablosunu veya akıllı bir şey kullanın.

Misal

İşlevsel örnekler, ilki kurallar tarafından yasaklanmış olsa da ...

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

Aşağıdaki bilgiler olsa da sorun yok, çünkü bu bilgileri

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]

Veya bir sıralama işlevi yapabilirsiniz

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

Örnek testler

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

Ay adını bir sayıya çevirmek için dahili zaman ayrıştırma yöntemlerini (örn. Strptime) kullanamazsınız. Bu biraz belirsiz. Bir dilin ayların adlarını içeren önceden tanımlanmış bir kelimesini kullanabilir miyiz?
Luis Mendo

O zaman cevabımı silerim. Ama neye izin verildiği ve neye izin verilmediği hala belli değil.
Luis Mendo

Sorun şu ki, önceden tanımlanmış diziler gibi tüm potansiyel hileleri tahmin edemezsiniz. Belki de daha iyi bir seçenek, tamamlanmış adlar gibi daha az yaygın bir dizeler dizisi kullanmak olabilirdi. Ama sanırım bunun için çok geç
Luis Mendo

İfade ettiğim şey net mi? Python'un monthstüm Ay adlarının bir listesi olan bir yerleşkesi olsaydı months[x] < months[y], cevap olarak yasaklamak isterdim . Ay isimleri listesinde, meydan okumayı rastgele oluşturulan dizelere göre daha kolay / zorlaştıran bazı daha tuhaf özellikler (değişen uzunluk, ortaklık) vardır.
Nick T

Evet, bence açık. Sadece açıkça dışlamadığınız başka benzer durumlar olabileceğinden korkuyorum (ama hangilerini bilmiyorum)
Luis Mendo

Yanıtlar:


41

Jöle , 19 bayt

11ị“bMAanlseovc”iµÞ

Bu, listeyi bağımsız değişken olarak alan ve sıralayan monadik bir bağlantıdır. Çevrimiçi deneyin!

Arka fon

Jelly, modüler, 1 tabanlı indeksleme kullanır. Ay adlarını 11 karakter elde etmek için sık sık tekrarlarsak, aşağıdaki diziyi alırız.

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 yılında inci aylardır sırasını belirlemek için kullanırlar, böylece (son) sütununda, tüm karakterler farklıdır.

Nasıl çalışır

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
Sadece merak ediyorum, "bMAanlseovc" ile ayı nasıl sıralıyorsunuz? İlk karakter eşleşmesinin dizini?
ljeabmreosn

Bir açıklama ekledim.
Dennis

8
Vay canına, bu gerçekten zekice!
ljeabmreosn

15

x86 makine kodu, 26 25 bayt

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

Montaj kodu:

    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;

Aşağıdaki hash işlevi, ay adlarını doğru sıraya koymak için olur (kaba kuvvet tarafından bulunur):

(x ^ 0xc0) * 0x01435f30

Küçük endian düzeninde düzenlenmiş giriş dizesinin ilk 4 baytına (32 bit) uygulanır. Sonra sonucu karşılaştırmak ve sonuç SALCkaydını (al) ayarlamak için kullanarak :

  • -1 (true) aylar düzenliyse
  • 0 (yanlış), ikinci ay ilk aydan önce gelirse (veya aynı ise)

4
Etkilendim. Code-golf'e özgü bir dil kullanmadan çok kısa bir kod parçası.
ShuberFu

13

Jöle , 15 bayt

Oḅ32 354*%991µÞ

Çevrimiçi çevirmen bağlantısı yok çünkü bu yavaş bir başvuru. Program, 354^(input interpreted as base 32 int) % 991çıkışları doğru sırayla veren sıralama anahtarı olarak karma işlevini kullanır . Üstelleştirmenin sonuçları dev olduğu için program yakında bitmeyecek - "Eylül" için 0.24 katrilyon basamaklı bir sayının hesaplanması gerekiyor!

Jöle açıklaması:

              Þ         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

Kavram komut dosyasının Python kanıtı - powçok daha verimli olan modüler üslü kullanım için not edin :

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
"Buradaki çevrimiçi tercüman bağlantısı yok çünkü bu yavaş bir gönderim." Bu durumda ayları elle de sıralayabilirsiniz. ;-)
owacoder

Belki güç / mod optimize etmek için bir özellik isteği PR olabilir ...
Nick T

@NickT Bu mükemmel bir fikir, ancak ne yazık ki tercümanın kurulum şekliyle (her operatör ayrı ayrı tanımlanır), bu biraz zor olabilir. Ve Jelly ikiden fazla argümanı olan operatörlerle iyi çalışmaz, bu yüzden ayrı bir operatör tanımlamak da işe yaramaz ...
Sp3000

Ayrı bir operatör veya herhangi bir şey değil, sadece bir güç işleminin modüler bölünme tarafından takip edilip edilmediğini görmek için daha derin bir içgözlem. Kulağa kolay mı geliyor? : P
Nick T

5

Python, 64 61 57 bayt

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

Lambda girdi olarak iki ay alır ve bunları karşılaştırır. Ideone üzerinde test edin .

@Ljeabmreosn'a 3 bayt golf ve 3 yol daha asfaltlama için teşekkürler!


2
Sonunda, Jelly cevabında doğru ayı hızlı bir şekilde hesaplamak için kullandığın kara büyünün ardındaki sırrı ortaya çıkar!
Değer Mürekkep

1
İşe s[10%len(s)]geçmek ister misiniz (4*s)[10]?
ljeabmreosn

1
@ljeabmreosn Gerçekten işe yarıyor. Teşekkürler!
Dennis

1
Henüz bir lambda'da varsayılan argümanların <strike> ab </strike> kullanımını görmedim: P
Nick T

4

Python, 81 71 bayt

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

https://repl.it/CluN/1

mİki aylık ikinci ve üçüncü harflerin indekslerini karşılaştırır .

Bir ay listesini sıralamak için 83 bayt sürümü:

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

3

Yakut, 58 bayt

@ Atlasologist cevabından ay sıralama hilesini kullanır .

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

Karşılaştırma işlevi 63 baytta biraz daha uzundur

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

3

J, 66 65 bayt

F (m) = 2 * (ord (m [0]) + ord (m [-1])) // len (m) 'nin 12 aylık sınırlı alanda geçerli bir işlev olduğu gerçeğini kullanır:

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

Kullanımı:

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

(Hiçbir şekilde bu en iyi fikir değil, ama kimsenin sıralama hilesini çalmak istemedim!)

@ Atlasologist yöntemini kullanarak daha kısa bir versiyon :

J, 63 bayt

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

Kullanımı:

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

@ Dennis'in akıllı yöntemini kullanarak çok daha kısa bir versiyon :

J, 34 bayt

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

3

Haskell, 74 bayt

İlk kodum golf, yay! Bunun genel fikri, Jelly'deki en iyi cevaptan ve ay isimleri çevrildiğinde 11. karakterin her zaman benzersiz olmasından ilham alıyor.

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

Nasıl çalıştığını görmek için ungolfed sürümü:

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İşlev eleventhChar fonksiyonu (ne yazık ki nedeniyle Bence monomorfizm kısıtlamasına 4 bayt kapalı şerit değildir) ve temsil #etmek infix fonksiyonu tekabül inOrderfonksiyonu.

Düzgün küçük bir çözüm, ancak daha fazla bayt tıraş etmenin yolları olabilir (Sadece bunu yazarken buldum!)


Sen kısaltabilir e s=head.drop 10$cycle sEğer kullanarak açıklama yaptığı gibi .yerine $: e=head.drop 10.cycle. Ancak liste endeksi operatörünü kullanmak !!daha da kısadır:e=(!!10).cycle
Laikoni

Harika öneriler. Bazen sadece bunları görmezden gelirsiniz. Çok teşekkürler. Kısa süre içinde düzenleyecek.
bower

2

Java, 133 123

golfed:

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

Montajcı yanıtında olduğu gibi akıllı bir teknik arıyordum, ama anlaması çok uzun sürüyordu, bu yüzden herkesin kullandığı aynı teknikle gittim.

Ungolfed:

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

}

Bunun substringyerine eğer kullanabilirsinizcharAt
anatolyg

@anatolyg teşekkürler, bunun beni nasıl kaçtığından emin değilim. Artık "" +ham madde olmadığı için çıkarmayı başardım char.

2

Linux'ta ARM makine dili 44 40 bayt

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

Farklı bir hash fonksiyonu kullandım anatolyg 'ın çözümü (Ben başparmak moduna giren 8 bayt patladı gerçi) ve birkaç bayt kaydetmek için kullanımı başparmak talimatlarına çalıştı.

GNURoot ile bir Raspberry Pi veya Android cihazında deneyebilirsiniz.

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

Koşmak için bir şey girin

$ ./foo January February; echo $?

Mevcut sürüm eşitlik durumunu (ve diğerlerini) doğru bir şekilde işler.


Açıkça Thumb moduna geçen bir koda ihtiyacınız olmadığını düşünüyorum. Hatırladığım kadarıyla, bağlayıcıya prosedürünüzün başparmak modunda olduğunu söylemeniz yeterlidir ve bağlayıcı prosedürünüzün adresindeki LSB'yi 1 olarak ayarlayacaktır, böylece kodunuz çağrıldığında işlemci otomatik olarak Thumb moduna geçecektir.
anatolyg

Ayrıca, ne yapar bfac?
anatolyg

@anatolyg ite gekoşullu olarak bir sonraki komutu ( movge r0, #0) yürütürse r3 >= r0, aksi takdirde aşağıdaki talimat yürütülür ( movlt r0, #1). Bence burada birkaç bayt vurmak için yer var ama bu çalışmak için zaman yoktu :-)
ceilingcat

1

Perl 6 , 55 bayt

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

Karşılaştırma sürümleri için birkaç bayt daha gerekir:

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

Ölçek:

#! /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 karakter

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

Her ay adının, dil tarafından otomatik olarak ayrıştırılabilen ve karşılaştırılabilen bir veri türü tanımlamak için ilk ve dördüncü karakterlerinde (veya Mayıs için 3'üncü) benzersiz olması gerçeğini kullanır. 'R' işlevi, bir dizeyi ilk dört karakteri (veya daha azını) yakalayıp, yalnızca ilk ve sonuncuyu seçerek dönüştürür. O zaman 'a # b' değerleri karşılaştırmak için bir operatördür:

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

Muhtemelen daha verimli bir şekilde yapılabilirdi, ancak ayları temsil etmek için yararlı bir veri türü kullanarak bunu denemek istedim.


1

PowerShell, 96 88 63 bayt

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

Örneğin

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

Şimdi bir listeyi sıraya dizmek için ikinci zorluk; önceki sürümlerde iki aylık test karşılaştırması yapıldı:

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

Ay adındaki ikinci iki karakteri temel alır.



0

Javascript, 118 bayt

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

Muhtemelen kurtulur cve kullanarak golf olabilir array.map, ama şimdilik bu var ...


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 bayt

bu is_later gibi bir işlev

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

Ölçek

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

0

k4, 29

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

@ Dennis'in Jelly cevabının bir limanı .

Bu karşılaştırıcı değil sıralayıcıdır; ilginç bir şekilde, karşılaştırıcı aynı algoritma ile önemsiz bir şekilde uygulanabilir ve sadece bir bayt daha uzun:

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

0

Bash + coreutils, 94 bayt 93 bayt

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

Bu sözlükbilimsel olarak değişen bir dönüşüm yaratma çabasıdır. Dönüşüm anahtarına yakından bakarsanız FMAyulgSOND, Şubat'tan Aralık'a kadar olan ayları görebilirsiniz (dönüşümden sonra Ocak boşalır; ayırıcı olarak 'B' kullanılarak tepeye çekilir). Anahtarsız harfleri tersine çevirme, kısaltma ve kaldırma, bu hilenin çekilmesini sağlar.

C Yerel Ayarını kullanan 90 bayt

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

... burada ␉ sekme karakteridir.

C Yerel Ayarını kullanan 80 bayt

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

... @ atlasolog'un yöntemini kullanarak. Bu yaklaşımı daha fazla yerlilerle çalışmak için kullanmanın bir yolu olması gerekir.

Testi / Kullanım

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

çıktılar:

January
February
March
April
May
June
July
August
September
October
November
December
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.