Ordina i mesi dell'anno


19

Scrivere una funzione o un programma che prende ingressi stringa, completamente farro, i nomi dei mesi in inglese nel caso in cui il titolo: January, February, March, ecc (null / CR / LF terminato OK, delimitato con qualche carattere non-alfa se lo si vuole) e sia

  • confronta due input, restituendo un valore Verità se il secondo input è maggiore (nell'ordine del mese) del primo. Valori uguali producono un valore Falsey

  • o ordina una sequenza arbitraria (elenco, stringa delimitata, ecc.) in ordine cronologico

(Il punto cruciale della sfida è definire un metodo / espressione che dia il corretto ordinamento lessicografico. Alcune lingue potrebbero avere una risposta più breve con l'una o l'altra)

Non è possibile utilizzare alcun metodo di analisi del tempo interno (ad es. strptime) Per tradurre il nome del mese in un numero o una mappatura predefinita dei nomi dei mesi. Usa le proprietà delle stringhe stesse, una tabella di ricerca parsimoniosa che definisci o qualcosa di intelligente.

Esempio

Esempi di funzionamento, sebbene il primo sia vietato dalle regole ...

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

Le versioni seguenti sono OK, perché codifichiamo tali informazioni

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]

Oppure potresti fare una funzione di ordinamento

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

Test di esempio

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

Non è possibile utilizzare alcun metodo di analisi del tempo interno (ad es. Strptime) per tradurre il nome del mese in un numero. Questo non è chiaro. Possiamo usare il letterale predefinito di una lingua che contiene i nomi dei mesi?
Luis Mendo,

Allora cancellerò la mia risposta. Ma non è ancora chiaro cosa sia permesso e cosa no.
Luis Mendo,

Il problema è che non puoi anticipare tutti quei potenziali trucchi, come gli array predefiniti. Forse un'opzione migliore sarebbe stata quella di utilizzare un set di stringhe meno comune, come i nomi inventati. Ma ora è troppo tardi per quello che immagino
Luis Mendo l'

Ciò che sto esprimendo è chiaro? Se Python avesse un built-in monthsche era un elenco di tutti i nomi dei Mese, vorrei proibire months[x] < months[y]come risposta. L'elenco dei nomi dei mesi presenta alcune caratteristiche più peculiari (lunghezza variabile, comunanza) che rendono la sfida più semplice / difficile rispetto alle stringhe generate casualmente.
Nick T

Sì, penso sia chiaro. Temo che potrebbero esserci altri casi simili che non hai escluso esplicitamente (ma non so quali)
Luis Mendo,

Risposte:


41

Gelatina , 19 byte

11ị“bMAanlseovc”iµÞ

Questo è un collegamento monadico che accetta un elenco come argomento e lo ordina. Provalo online!

sfondo

Jelly utilizza l'indicizzazione modulare a 1 base. Se ripetiamo i nomi dei mesi abbastanza spesso per ottenere 11 caratteri, otteniamo il seguente array.

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

Nel 11 ° (ultimo) di colonna, tutti i personaggi sono diversi, in modo da poterli utilizzare per identificare l'ordine dei mesi.

Come funziona

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
Solo curioso, come stai classificando il mese con "bMAanlseovc"? Indice della corrispondenza del primo personaggio?
ljeabmreosn,

Ho aggiunto una spiegazione.
Dennis,

8
Wow, è davvero intelligente!
ljeabmreosn,

15

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

Codice dell'Assemblea:

    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;

La seguente funzione hash capita di mettere i nomi dei mesi nell'ordine corretto (trovato dalla forza bruta):

(x ^ 0xc0) * 0x01435f30

Viene applicato ai primi 4 byte (32 bit) della stringa di input, disposti in ordine little-endian. Quindi confrontando il risultato e usando SALCper impostare il registro dei risultati (al):

  • -1 (vero) se i mesi sono in ordine
  • 0 (falso) se il secondo mese precede il primo mese (o sono uguali)

4
Sono impressionato. Un codice molto breve senza usare un linguaggio specifico per il code-golf.
ShuberFu,

13

Gelatina , 15 byte

Oḅ32 354*%991µÞ

Nessun collegamento di interprete online qui perché si tratta di una presentazione lenta . Il programma utilizza la funzione di hashing 354^(input interpreted as base 32 int) % 991come chiave di ordinamento, che dà le uscite nell'ordine giusto. Il programma non finirà presto perché i risultati dell'espiazione sono giganti: per "settembre", è necessario calcolare un numero con 0,24 quadrilioni di cifre!

Spiegazione della gelatina:

              Þ         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 proof of concept script - nota l'uso di powper esponentiation modulare, che è molto più efficiente:

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
"Nessun link per interprete online qui perché si tratta di una presentazione lenta ." In tal caso, puoi anche ordinare i mesi a mano. ;-)
owacoder l'

Forse potresti PR richiedere una funzione per ottimizzare pow / mod ...
Nick T

@NickT Questa è un'ottima idea, ma sfortunatamente con il modo in cui è impostato l'interprete (con ogni operatore definito separatamente), potrebbe essere un po 'complicato. E Jelly non funziona bene con operatori che hanno più di due argomenti, quindi la definizione di un operatore separato non funzionerebbe nemmeno ...
Sp3000,

Non un operatore separato o altro, solo un'introspezione più profonda per vedere se un'operazione di alimentazione è seguita da una divisione modulare. Sembra facile? : P
Nick T,

5

Python, 64 61 57 byte

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

La lambda impiega due mesi come input e li confronta. Provalo su Ideone .

Grazie a @ljeabmreosn per aver golf 3 byte e spianare la strada per altri 3!


2
Alla fine, sveli il segreto dietro la magia nera che hai usato per calcolare rapidamente il mese corretto nella tua risposta Jelly!
Valore inchiostro

1
Passerebbe s[10%len(s)]al (4*s)[10]lavoro?
ljeabmreosn,

1
@ljeabmreosn Funziona davvero. Grazie!
Dennis,

1
Non ho ancora visto l'uso <strike> ab </strike> di argomenti predefiniti in un 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

Confronta l'indice mdella seconda e terza lettera di due mesi.

Versione a 83 byte per ordinare un elenco di mesi:

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

3

Rubino, 58 byte

Utilizza il trucco di ordinamento del mese dalla risposta di @atlasologo .

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

La funzione di confronto è un po 'più lunga, a 63 byte

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

3

J, 66 65 byte

Utilizza il fatto che f (m) = 2 * (ord (m [0]) + ord (m [-1])) // len (m) è una funzione valida nel dominio limitato dei 12 mesi:

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

Uso:

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

(Non è affatto questa la migliore idea, ma non volevo rubare il trucco di qualcuno!)

Ecco una versione più breve usando il metodo @ atlasologist :

J, 63 byte

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

Uso:

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

E una versione molto più breve usando il metodo intelligente di @Dennis:

J, 34 byte

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

3

Haskell, 74 byte

Il mio primo codice golf, yay! L'idea generale di questo è ispirata alla risposta principale di Jelly e al fatto che quando i nomi dei mesi vengono cambiati, l'undicesimo personaggio è sempre unico.

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

Ecco una versione non golfata per vedere come funziona:

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)

La efunzione rappresenta l'undicesima funzione Char (purtroppo non è possibile rimuovere 4 byte a causa della limitazione del monomorfismo credo) e la #funzione infix corrisponde alla inOrderfunzione.

Una piccola soluzione ordinata, ma potrebbero esserci dei modi per radere più byte (ne ho trovati alcuni proprio mentre scrivevo questo!)


Si potrebbe accorciare e s=head.drop 10$cycle scome avete fatto nella vostra spiegazione utilizzando .al posto di $: e=head.drop 10.cycle. Tuttavia, l'utilizzo dell'operatore dell'indice elenco !!è ancora più breve:e=(!!10).cycle
Laikoni

Grandi suggerimenti. A volte trascuri queste cose. Molte grazie. Lo modificherò a breve.
cenere

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

Stavo cercando una tecnica intelligente come nella risposta dell'assemblatore, ma ci stava impiegando troppo tempo per capire, quindi sono andato con la stessa tecnica utilizzata da tutti gli altri.

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

}

È possibile utilizzare substringinvece secharAt
anatolyg

@anatolyg grazie, non sono sicuro di come mi sia sfuggito. Sono stato anche in grado di rimuovere "" +poiché non ci sono più raw char.

2

Linguaggio macchina ARM su 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

Ho usato una funzione hash diverso anatolyg s' soluzione e cercato di istruzioni uso pollice per risparmiare pochi byte (se Soffiai 8 byte entrano modalità pollice).

Puoi provarlo su un dispositivo Raspberry Pi o Android con 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]);}

Per eseguire inserire qualcosa di simile

$ ./foo January February; echo $?

La versione corrente ora gestisce correttamente il caso di uguaglianza (e altri).


Penso che non sia necessario un codice che passi esplicitamente alla modalità Thumb. Da quello che ricordo, devi solo dire al linker che la tua procedura è in modalità pollice, e il linker imposterà LSB nell'indirizzo della procedura su 1, quindi il processore passerà automaticamente alla modalità Thumb quando viene chiamato il tuo codice.
Anatolyg

Inoltre, cosa fa bfac?
Anatolyg

@anatolyg ite ge esegue in modo condizionale l'istruzione successiva ( movge r0, #0) if r3 >= r0, altrimenti viene eseguita l'istruzione seguente ( movlt r0, #1). Penso che ci sia spazio per eliminare un paio di byte qui, ma non ho avuto il tempo di lavorare su questo :-)
ceilingcat,

1

Perl 6 , 55 byte

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

Richiederebbe qualche byte in più per le versioni di confronto:

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

Test:

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

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

Utilizza il fatto che ogni mese il nome è univoco nel suo primo e quarto carattere (o 3 ° per maggio) per definire un tipo di dati che può essere analizzato e confrontato automaticamente dalla lingua. La funzione 'r' converte una stringa afferrando i primi quattro caratteri (o meno), quindi selezionando solo il primo e l'ultimo. Quindi 'a # b' è un operatore per confrontare i valori:

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

Probabilmente potrebbe essere fatto in un modo più efficiente, ma volevo provare a farlo usando un tipo di dati utile per rappresentare i mesi.


1

PowerShell, 96 88 63 byte

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

per esempio

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

Ora fa la seconda sfida di ordinare un elenco in ordine; le versioni precedenti hanno confrontato due mesi di test:

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

Basato sui secondi due caratteri nel nome del mese.



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

Potrebbe essere giocato a golf di più, probabilmente eliminando ce usando array.map, ma questo è quello che ho per ora ...


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

questa è una funzione come 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}));}

test

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

0

k4, 29

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

Una porta della risposta Jelly di @Dennis .

Questo è lo smistatore, non il comparatore; è interessante notare che il comparatore è banalmente implementabile dallo stesso algoritmo e solo un byte in più:

{(<)."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;}

Questo è un tentativo di escogitare una trasformazione di tipo lessicografico. Se osservi attentamente la chiave di trasformazioneFMAyulgSOND puoi vedere i mesi da febbraio a dicembre (gennaio diventa vuoto dopo la trasformazione; viene portato in alto usando 'B' come separatore). L'inversione, il troncamento e la rimozione di lettere senza chiave consentono di eseguire questo trucco.

90 byte usando C Locale

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

... dove ␉ è il carattere di tabulazione.

80 byte usando C Locale

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

... usando il metodo @ atlasolog. Vincolato ad essere un modo per usare questo approccio per lavorare con più locali.

Test / Uso

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

uscite:

January
February
March
April
May
June
July
August
September
October
November
December
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.