Sortieren Sie die Monate des Jahres

19

Schreiben Sie eine Funktion oder ein Programm , das String - Eingänge nimmt, voll Dinkel, Englisch Monatsnamen in Titel Fall: January, February, Marchusw. (null / CR / LF beendet OK, mit einigen nicht-alpha Zeichen begrenzt , wenn Sie so wählen) und entweder

  • vergleicht zwei Eingaben und gibt einen Wahrheitswert zurück, wenn die zweite Eingabe größer ist (in Monatsreihenfolge) als die erste. Gleiche Werte führen zu einem falschen Wert

  • oder sortiert eine beliebige Reihenfolge (Liste, durch Trennzeichen getrennte Zeichenfolge usw.) in chronologischer Reihenfolge

(Der Kern der Herausforderung besteht darin, eine Methode / einen Ausdruck zu definieren, die / der die richtige lexikografische Sortierung ergibt. Einige Sprachen haben möglicherweise eine kürzere Antwort auf die eine oder die andere)

Sie können keine internen Zeitanalyse-Methoden verwenden (z. B. strptime), um den Monatsnamen in eine Zahl oder eine vordefinierte Zuordnung von Monatsnamen zu übersetzen. Verwenden Sie die Eigenschaften der Zeichenfolgen selbst, eine von Ihnen definierte sparsame Nachschlagetabelle oder eine clevere Funktion.

Beispiel

Funktionsbeispiele, obwohl das erste durch die Regeln verboten ist ...

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

Die folgenden Versionen sind jedoch in Ordnung, da wir diese Informationen codieren

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]

Oder Sie könnten eine Sortierfunktion ausführen

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

Beispieltests

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')
Nick T
quelle
Sie können keine internen Zeitanalyse-Methoden (z. B. strptime) verwenden, um den Monatsnamen in eine Zahl zu übersetzen. Das ist etwas unklar. Können wir das vordefinierte Literal einer Sprache verwenden, das die Monatsnamen enthält?
Luis Mendo
Ich werde meine Antwort dann löschen. Aber es ist immer noch nicht klar, was erlaubt ist und was nicht.
Luis Mendo
Das Problem ist, dass Sie nicht alle diese potenziellen Tricks vorhersehen können, z. B. vordefinierte Arrays. Möglicherweise wäre es eine bessere Option gewesen, weniger gebräuchliche Zeichenfolgen zu verwenden, z. B. erfundene Namen. Aber dafür ist es jetzt wohl zu spät
Luis Mendo
Ist das, was ich ausdrücke, klar? Wenn Python eine integrierte monthsListe aller Monatsnamen hätte, würde ich dies months[x] < months[y]als Antwort verbieten wollen . Die Liste der Monatsnamen enthält einige Besonderheiten (unterschiedliche Länge, Gemeinsamkeiten), die die Herausforderung bei zufällig generierten Zeichenfolgen erleichtern / erschweren.
Nick T
Ja, ich denke es ist klar. Ich fürchte nur, dass es andere ähnliche Fälle geben könnte, die Sie nicht ausdrücklich ausgeschlossen haben (aber ich weiß nicht, welche)
Luis Mendo

Antworten:

41

Jelly , 19 Bytes

11ị“bMAanlseovc”iµÞ

Dies ist ein monadischer Link, der eine Liste als Argument nimmt und sortiert. Probieren Sie es online!

Hintergrund

Jelly verwendet eine modulare, 1-basierte Indexierung. Wenn wir die Monatsnamen oft genug wiederholen, um 11 Zeichen zu erhalten, erhalten wir das folgende 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

Im 11 - ten (letzten) Spalte sind alle Zeichen anders, so dass wir sie nutzen können , um die Reihenfolge der Monate zu identifizieren.

Wie es funktioniert

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).
Dennis
quelle
1
Nur neugierig, wie bewerten Sie den Monat mit "bMAanlseovc"? Index der ersten Zeichenübereinstimmung?
1.
Ich habe eine Erklärung hinzugefügt.
Dennis
8
Wow, das ist wirklich schlau!
1.
15

x86-Maschinencode, 26 25 Bytes

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

Assembler-Code:

    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;

Die folgende Hash-Funktion bringt die Monatsnamen in die richtige Reihenfolge (ermittelt durch Brute Force):

(x ^ 0xc0) * 0x01435f30

Es wird auf die ersten 4 Bytes (32 Bits) der Eingabezeichenfolge angewendet, die in Little-Endian-Reihenfolge angeordnet sind. Vergleichen Sie dann das Ergebnis und SALCsetzen Sie das Ergebnisregister (al) mit:

  • -1 (true) wenn die Monate in Ordnung sind
  • 0 (falsch), wenn der zweite Monat dem ersten Monat vorausgeht (oder sie sind gleich)
anatolyg
quelle
4
Ich bin beeindruckt. Ein sehr kurzes Stück Code ohne Verwendung einer Code-Golf-spezifischen Sprache.
ShuberFu
13

Gelee , 15 Bytes

Oḅ32 354*%991µÞ

Kein Online-Dolmetscher-Link hier, da dies eine langsame Einreichung ist. Das Programm verwendet die Hash-Funktion 354^(input interpreted as base 32 int) % 991als Sortierschlüssel, wodurch die Ausgaben in der richtigen Reihenfolge erfolgen. Das Programm wird in Kürze beendet, da die Ergebnisse der Exponentiation gigantisch sind - für "September" muss eine Zahl mit 0,24 Billiarden Ziffern berechnet werden!

Jelly Erklärung:

              Þ         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-Skript - Beachten Sie die Verwendung powfür die modulare Exponentiation, die wesentlich effizienter ist:

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))
Sp3000
quelle
5
Msgstr "Kein Online - Dolmetscherlink hier, da dies eine langsame Einreichung ist." In diesem Fall können Sie die Monate auch manuell sortieren. ;-)
Owacoder
Vielleicht könnten Sie eine Feature-Anfrage PR, um Pow / Mod zu optimieren ...
Nick T
@NickT Das ist eine hervorragende Idee, aber leider ist die Einrichtung des Interpreters (wobei jeder Operator separat definiert wird) etwas schwierig. Und Jelly funktioniert nicht gut mit Operatoren, die mehr als zwei Argumente haben, so dass das Definieren eines separaten Operators auch nicht ganz funktioniert ...
Sp3000
Kein separater Bediener oder etwas anderes, nur eine tiefergehende Überprüfung, ob auf eine Stromoperation eine modulare Aufteilung folgt. Klingt einfach? : P
Nick T
5

Python, 64 61 57 Bytes

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

Das Lambda nimmt als Eingabe zwei Monate in Anspruch und vergleicht sie. Teste es auf Ideone .

Vielen Dank an @ljeabmreosn für das Abschlagen von 3 Bytes und das Vorbereiten des Weges für weitere 3 Bytes!

Dennis
quelle
2
Endlich enthüllen Sie das Geheimnis hinter der schwarzen Magie, mit der Sie in Ihrer Gelee-Antwort schnell den richtigen Monat berechnet haben!
Wert Tinte
1
Würde s[10%len(s)]zur (4*s)[10]Arbeit wechseln ?
1.
1
@ ljeabmreosn Das funktioniert in der Tat. Vielen Dank!
Dennis
1
<Strike> ab </ strike> Verwendung von Standardargumenten in einem Lambda noch nicht gesehen: P
Nick T
4

Python, 81 71 Bytes

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

https://repl.it/CluN/1

Vergleicht den Index mdes zweiten und dritten Buchstabens von zwei Monaten.

83-Byte-Version zum Sortieren einer Liste von Monaten:

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

Ruby, 58 Bytes

Verwendet den Monatssortiertrick aus der Antwort von @atlasologist .

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

Die Vergleichsfunktion ist mit 63 Bytes etwas länger

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

J 66 65 Bytes

Verwendet die Tatsache, dass f (m) = 2 * (ord (m [0]) + ord (m [-1])) // len (m) eine gültige Funktion im begrenzten Bereich der 12 Monate ist:

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

Verwendung:

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

(Das ist auf keinen Fall die beste Idee, aber ich wollte keinen Ranglistentrick stehlen!)

Hier ist eine kürzere Version unter Verwendung der @ atlasologist- Methode:

J, 63 Bytes

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

Verwendung:

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

Und eine viel kürzere Version mit der cleveren Methode von @ Dennis :

J, 34 Bytes

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

Haskell, 74 Bytes

Mein erster Code Golf, yay! Die Grundidee dieses Artikels ist inspiriert von der Top-Antwort in Jelly und der Tatsache, dass das 11. Zeichen beim Wechseln der Monatsnamen immer eindeutig ist.

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

Hier ist eine ungolfed Version, um zu sehen, wie es funktioniert:

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)

Die eFunktion repräsentiert die eleventhChar-Funktion (leider können 4 Bytes aufgrund der Monomorphismus-Einschränkung nicht entfernt werden, denke ich) und die #Infix-Funktion entspricht der inOrderFunktion.

Eine nette kleine Lösung, aber es kann Möglichkeiten geben, mehr Bytes zu sparen (einige habe ich gerade beim Schreiben gefunden!)

Laube
quelle
Sie könnten verkürzen , e s=head.drop 10$cycle swie Sie durch den Einsatz in Ihrer Erklärung haben .statt $: e=head.drop 10.cycle. Die Verwendung des !!e=(!!10).cycle
Listenindexoperators
Tolle Vorschläge. Manchmal übersieht man diese Dinge einfach. Vielen Dank. Wird es in Kürze bearbeiten.
Laube
2

Java, 133, 123

Golf gespielt:

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

Ich suchte nach einer cleveren Technik wie in der Assembler-Antwort, aber es dauerte zu lange, um herauszufinden, weshalb ich dieselbe Technik verwendete, die auch alle anderen verwendeten.

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

}

quelle
Sie könnten substringstattdessen verwenden, wenncharAt
anatolyg
@anatolyg danke, ich bin nicht sicher, wie dieser mir entgangen ist. Ich konnte auch entfernen, "" +da es keine rohen chars mehr gibt.
2

ARM Maschinensprache unter Linux 44 40 Bytes

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

Ich habe eine andere Hash-Funktion verwendet als die Lösung von anatolyg verwendet und versucht, mithilfe von Thumb-Anweisungen ein paar Bytes zu sparen (obwohl ich 8 Bytes in den Thumb-Modus geworfen habe ).

Sie können dies auf einem Raspberry Pi oder Android-Gerät mit GNURoot ausprobieren.

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

Zum Laufen geben Sie so etwas wie ein

$ ./foo January February; echo $?

Die aktuelle Version behandelt jetzt den Gleichheitsfall (und andere) korrekt.

Ceilingcat
quelle
Ich denke, Sie brauchen keinen Code, der explizit in den Thumb-Modus wechselt. Soweit ich mich erinnere, müssen Sie dem Linker nur mitteilen, dass sich Ihre Prozedur im Thumb-Modus befindet, und der Linker setzt das LSB in der Adresse Ihrer Prozedur auf 1, sodass der Prozessor automatisch in den Thumb-Modus wechselt, wenn Ihr Code aufgerufen wird.
Anatolyg
Was macht bfacman auch?
Anatolyg
@anatolyg ite geführt die nächste Anweisung ( movge r0, #0) bedingt aus r3 >= r0, andernfalls die folgende Anweisung ( movlt r0, #1). Ich denke, es gibt hier Platz, um ein paar Bytes zu
verlieren,
1

Perl 6 , 55 Bytes

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

Für die Vergleichsversionen wären einige Bytes mehr erforderlich:

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

Prüfung:

#! /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;
}
Brad Gilbert b2gills
quelle
1

Haskell, 118 Zeichen

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

Verwendet die Tatsache, dass jeder Monatsname in seinem ersten und vierten Zeichen (oder 3. für Mai) eindeutig ist, um einen Datentyp zu definieren, der von der Sprache automatisch analysiert und verglichen werden kann. Die 'r'-Funktion konvertiert einen String, indem sie die ersten vier Zeichen (oder weniger) aufnimmt und dann nur das erste und das letzte auswählt. Dann ist 'a # b' ein Operator zum Vergleichen der Werte:

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

Könnte wahrscheinlich effizienter sein, aber ich wollte versuchen, einen nützlichen Datentyp für die Darstellung der Monate zu verwenden.

Jules
quelle
1

PowerShell, 96 88 63 Bytes

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

z.B

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

Nun folgt die zweite Herausforderung: Sortieren einer Liste nach Reihenfolge. Vorgängerversionen führten den Vergleich von zweimonatigem Test durch:

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

Basierend auf den zweiten beiden Zeichen im Monatsnamen.

TessellatingHeckler
quelle
1

Python 83 82 Bytes

lambda x,y,m=(lambda a:'2&9<@FD6A?L%'.find(chr(sum(map(ord,a[:3]))%77))):m(x)<m(y)

Test: https://repl.it/repls/TimelyDecimalBrowsers

Ruft die Summe der ersten 3 Zeichen ab und erstellt ein einzelnes Zeichen für die Suche.

Baris
quelle
0

Javascript, 118 Bytes

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

Könnte mehr Golf gespielt werden, wahrscheinlich, indem man es loswird cund benutzt array.map, aber das habe ich jetzt ...

Bald Bantha
quelle
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 Bytes

Dies ist die Funktion von 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}));}

Prüfung

$ f January December && echo later || echo not later
not later
user58494
quelle
0

k4, 29

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

Ein Port von @ Dennis's Jelly Antwort .

Dies ist der Sortierer, nicht der Komparator; Interessanterweise ist der Komparator mit demselben Algorithmus trivial implementierbar und nur ein Byte länger:

{(<)."ubMAanlseovc"?(*|11#)'x}
Aaron Davies
quelle
0

Bash + Coreutils, 94 Bytes 93 Bytes

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

Dies ist ein Versuch, eine Transformation zu entwickeln, die lexikografisch sortiert ist. Wenn Sie sich den Transformationsschlüssel genau ansehen, FMAyulgSONDsehen Sie die Monate Februar bis Dezember (der Januar wird nach der Transformation leer; durch Verwendung von 'B' als Trennzeichen wird er nach oben gezogen). Durch Umkehren, Abschneiden und Entfernen von Buchstaben ohne Schlüssel kann dieser Trick ausgeführt werden.

90 Bytes unter Verwendung von C Locale

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

... wobei ␉ das Tabulatorzeichen ist.

80 Bytes unter Verwendung von C-Gebietsschema

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

... mit der @ atlasolog-Methode. Ich bin fest entschlossen, diesen Ansatz zu nutzen, um mit mehr Gebietsschemas zu arbeiten.

Test / Verwendung

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

Ausgänge:

January
February
March
April
May
June
July
August
September
October
November
December
H Walters
quelle