Chinesisches Sternzeichen berechnen

10

Angesichts des bevorstehenden chinesischen Neujahrs ist es hier eine Herausforderung, den chinesischen Tierkreis, das chinesische Element und Taijitu für ein bestimmtes Datum zu berechnen.

Die Eingabe sollte ein Datum sein:

1/31/2014

Das hier verwendete Datum ist der US-Stil mm/dd/yyyy, kann aber auch der ISO-8601-Stil sein. Daher ist yyyy-mm-ddder Stil der Datumseingabe nicht streng.

Die Ausgabe sollte das Tierzeichen im chinesischen Tierkreis sein, einschließlich des Elements, das dem Datum entspricht, und seines Taijitu- Gegenstücks:

Horse - Wood - Yang

Eine Tabelle, die die Beziehung zwischen Tierkreiselement und Taijitu zeigt, ist hier zu sehen: Chinesischer Tierkreis - Jahre

Das Ausgabeformat ist nicht streng, sollte jedoch Tier-, Element- und Taijitu-Komponenten enthalten und in gewisser Weise abgegrenzt sein.

Beispiele für eine gültige Ausgabe für das oben genannte Datum können sein:

(horse, wood, yang)
["Horse", "Wood", "Yang"]

Ihr Programm sollte eine gültige Ausgabe für einen Bereich von mindestens 100 Jahren einschließlich des heutigen Datums zurückgeben. Dies bedeutet, dass mindestens zwei 60-jährige ( sexagenäre ) Zyklen berücksichtigt werden müssen .

Eduard Florinescu
quelle
3
Haben Sie einen praktischen Link zur Berechnung des Beginns eines Tierkreisjahres?
Hand-E-Food
3
Sie haben keine Ahnung, wie Sie das Zodaic-Jahr berechnen sollen, aber es scheint "ziemlich einfach" zu sein. Vielleicht sollten wir diese Frage vorerst schließen und wieder öffnen, wenn Sie diese kleinen Details ausgebügelt haben?
1
Eine andere Sache zu beachten ist, dass es immer zwischen dem 21. Januar und dem 21. Februar einschließlich ist.
Justin
3
Die von Ihnen verknüpfte Tabelle ist nur dann von Nutzen, wenn Sie eine Einschränkung hinzufügen, dass es nicht erforderlich ist, die richtige Ausgabe für Daten außerhalb dieses Bereichs anzugeben.
Peter Taylor
2
Eduard Florinescu, zwei Dinge, die Sie in der Frage klären sollten: 1) Eingabedatumsbereich, wie @PeterTaylor hervorhebt, und 2) muss das Ausgabeformat genau so sein, wie Sie es in Ihrem Beispiel angegeben haben? Jeder Charakter zählt, also machen Sie bitte dieses Ziel. Vielen Dank.
Darren Stone

Antworten:

4

Mathematica 63

Okay, das wird vielleicht alt, aber es funktioniert (Datumseingabe ist in vielen Fällen nicht eindeutig):

z=WolframAlpha[#<>" Chinese zodiac",{{"Result",1},"Plaintext"}] &

Beispiel:

z@"1/31/2014"

"Pferd (Yang Wood)"

Yves Klett
quelle
Die Breite von Mathematica überrascht mich. Ihr Ausgabeformat ist falsch, aber ich bin sicher, dass dies leicht behoben werden kann.
Darren Stone
1
@DarrenStone ist etwas unrühmlich, weil Mathematica einfach W | A aufruft. Denken Sie, dass die Ausgabe genau zur Formatierung des OP passen muss?
Yves Klett
Es sieht so aus, als ob andere Antworten genau wie die Beispielausgabe der Frage formatiert sind, und es ist sicherlich zusätzlicher Code erforderlich, um dies in jeder Sprache zu tun. Aber das ist wirklich eine Frage für @EduardFlorinescu
Darren Stone
@DarrenStone wahr. Dies wird sicherlich einen erheblichen Overhead verursachen. W & C ...
Yves Klett
4

C # - 357 337 339 Bytes

string Z(System.DateTime d){var c=new System.Globalization.ChineseLunisolarCalendar();var y=c.GetSexagenaryYear(d);var s=c.GetCelestialStem(y)-1;return",Rat,Ox,Tiger,Rabbit,Dragon,Snake,Horse,Goat,Monkey,Rooster,Dog,Pig".Split(',')[c.GetTerrestrialBranch(y)]+" - "+"Wood,Fire,Earth,Metal,Water".Split(',')[s/2]+" - Y"+(s%2>0?"in":"ang");}

Formatiert:

string Z(System.DateTime d)
{
  var c = new System.Globalization.ChineseLunisolarCalendar();
  var y = c.GetSexagenaryYear(d);
  var s = c.GetCelestialStem(y) - 1;
  return
    ",Rat,Ox,Tiger,Rabbit,Dragon,Snake,Horse,Goat,Monkey,Rooster,Dog,Pig".Split(',')[c.GetTerrestrialBranch(y)]
    + " - "
    + "Wood,Fire,Earth,Metal,Water".Split(',')[s / 2]
    + " - Y" + (s % 2 > 0 ? "in" : "ang");
}
Mormegil
quelle
+1 Sie können auch mehr als 20 Zeichen speichern, indem Sie vermeiden string.Format.
Hand-E-Food
Ja, richtig, danke, ich habe versucht, die verschiedenen s% 2 == 0 usw. zu spielen und habe den großen vergessen. :-) Und tatsächlich waren es genau 20 Zeichen, IIANM.
Mormegil
4

Python 2: 360 * 387 586 594 - Zeichen

Weiter reduziert

m,n,p=map(int,raw_input().split("/"));p-=1924;d=int("5od2nauh6qe4obvj8rf5pd2math6re3ocvi8sf5pd2l9uh6rf3nbvi7sg5pd2k9th6rf4navj7sg5oc1m9ti7qe3navj8sg5pc1math6qd3nbvj8sf4oc1ma"[p],36);p-=31*m-31+n<(d<21)*31+d;print"Rat Ox Tiger Rabbit Dragon Snake Horse Goat Monkey Rooster Dog Pig".split()[p%12],"Wood Fire Earth Metal Water".split()[p%10/2],["Yang","Yin"][p%2]

Der obige Code funktioniert für das folgende Intervall: 5. Februar 1924 - 31. Dezember 2043

Beispiel: Nach dem Einfügen des obigen Codes in den Python-Interpreter-Cursor

>>> m,n,p=map(int,raw_input().split("/"));p-=1924;d=int("5od2nauh6qe4obvj8rf5pd2math6re3ocvi8sf5pd2l9uh6rf3nbvi7sg5pd2k9th6rf4navj7sg5oc1m9ti7qe3navj8sg5pc1math6qd3nbvj8sf4oc1ma"[p],36);p-=31*m-31+n<(d<21)*31+d;print"Rat Ox Tiger Rabbit Dragon Snake Horse Goat Monkey Rooster Dog Pig".split()[p%12],"Wood Fire Earth Metal Water".split()[p%10/2],["Yang","Yin"][p%2]

und drücken Sie dann Enter, geben Sie ein Datum wie dieses ein

6/13/2018

und dann Entererneut drücken , wird ausgegeben

Dog Earth Yang


* Reduzierte weitere 27 Bytes mit Brians Hilfe, siehe Kommentare.

Eduard Florinescu
quelle
2
Haben Sie bemerkt, dass Ihre Basis-36-Nummer zweimal „Mathe“ enthält? :)
Timwi
1
@ Timwi: D Nein, habe ich nicht, und das ist sowohl nett als auch gruselig!
Eduard Florinescu
Eduard, kannst du den Teil d = int (Basis 36 Nummer) erklären? Ich bin auf Ihre Antwort gestoßen, als ich im Stackoverflow nach einem ähnlichen Problem gesucht habe. Ich muss die Jahresberechnungen auf den Bereich der Jahre 1500 - 2043 erweitern. Vielen Dank im Voraus für jede Hilfe.
Luis Miguel
1
Mit einigen Mikrooptimierungen können Sie weitere 23 Zeichen speichern. Siehe reddit.com/r/Python/comments/2oqobw/…
Brian
1
@ Timwi 1math6und 2math6. Sogar die vorhergehenden 5 und die folgenden 3 werden mit unterschiedlichen Zeichen dazwischen gespiegelt. Das ist 3spooky5me.
Magic Octopus Urn
3

Ruby, 340

m,d,y=gets.split(?/).map(&:to_i);y+=1if 31*m+d-51>"d88jac8mlbuppp21ygmkjsnfsd4n3xsrhha4abnq9zgo6g2jupc39zav84434f75op4ftfhdcsa3xhc8nsw1ssw8p9qns1tf14mncy8j18msr9rsb7j7".to_i(36)>>5*y-9625&31
$><<[%w(Goat Monkey Rooster Dog Pig Rat Ox Tiger Rabbit Dragon Snake Horse)[y%12],%w(Metal Water Wood Fire Earth)[(y-1)/2%5],%w(Yin Yang)[y%2]]*' - '

Dies gilt für Daten zwischen dem 5. Februar 1924 und dem 29. Januar 2044.

Darren Stone
quelle
Was zum Teufel ist diese "magische" Zahl?
Tomsmeding
1
@tomsmeding, es ist eine 600-Bit-Ganzzahl, die aus Gründen der Kompaktheit in Base 36 codiert ist. In Bitfelder unterteilt, ist es eine Tabelle des ersten Tages des Mondkalenders für jedes Jahr zwischen 1924 und 1944.
Darren Stone
3

GolfScript (212 Zeichen)

Hierbei werden nicht druckbare Zeichen verwendet. Hier ist die Ausgabe von xxd:

0000000: 272d 272f 6e2a 7e5c 2833 312a 2b5c 3a5e  '-'/n*~\(31*+\:^
0000010: 3139 2a22 d4e3 275a 747f 878c 70cb 996d  19*"..'Zt...p..m
0000020: a4f9 19e9 699e d818 bb61 c4e3 2232 3536  ....i....a.."256
0000030: 6261 7365 2033 6261 7365 5e31 3932 322d  base 3base^1922-
0000040: 3c7b 282d 7d2f 3330 2532 312b 3e5e 352d  <{(-}/30%21+>^5-
0000050: 2b3a 5e31 3225 2752 6174 0a4f 780a 5469  +:^12%'Rat.Ox.Ti
0000060: 6765 720a 5261 6262 6974 0a44 7261 676f  ger.Rabbit.Drago
0000070: 6e0a 536e 616b 650a 486f 7273 650a 476f  n.Snake.Horse.Go
0000080: 6174 0a4d 6f6e 6b65 790a 526f 6f73 7465  at.Monkey.Rooste
0000090: 720a 446f 670a 5069 6727 6e2f 3d6e 5e32  r.Dog.Pig'n/=n^2
00000a0: 2f35 2527 576f 6f64 0a46 6972 650a 4561  /5%'Wood.Fire.Ea
00000b0: 7274 680a 4d65 7461 6c0a 5761 7465 7227  rth.Metal.Water'
00000c0: 6e2f 3d6e 5e31 2627 5961 6e67 0a59 696e  n/=n^1&'Yang.Yin
00000d0: 276e 2f3d                                'n/=

Ein äquivalentes Programm, das String-Escapezeichen verwendet und daher etwas länger ist, ist:

'-'/n*~\(31*+\:^19*"\xD4\xE3'Zt\x87\x8Cp\xCB\x99m\xA4\xF9\x19\xE9i\x9E\xD8\x18\xBBa\xC4\xE3"256base 3base^1922-<{(-}/30%21+>^5-+:^12%'Rat
Ox
Tiger
Rabbit
Dragon
Snake
Horse
Goat
Monkey
Rooster
Dog
Pig'n/=n^2/5%'Wood
Fire
Earth
Metal
Water'n/=n^1&'Yang
Yin'n/=

Der interessante Teil ist die Berechnung des Datums, ob es vor oder nach dem chinesischen Neujahr ist, das in dieses gregorianische Jahr fällt. Ich ließ mich von dem Osterberechnungsalgorithmus inspirieren, den ich bei einer früheren Frage verwendet habe, und suchte nach einer relativ einfachen Berechnung des Neujahrsdatums. Am Ende habe ich eine einfache Formel verwendet, die mich den größten Teil des Weges dorthin bringt, sowie eine Nachschlagetabelle für den Fehlerbegriff.

Die einfache Berechnung ist day_of_year = 21 + (19 * year % 30). Der Fehlerterm reicht von 0bis 8über den interessierenden Bereich (1924 bis 2044) und ändert sich nie von Jahr zu Jahr um mehr als eins. Daher wird die Nachschlagetabelle in einem ausgeglichenen ternären Bereich codiert und der Fehler wird durch Summieren der Fehlerterme von a berechnet Präfix der Tabelle.

Peter Taylor
quelle
Schön, bisher am kürzesten, bis auf die Mathematica verwendet man eine externe Ressource. +1
Eduard Florinescu
2

C #, 630 611 604 572 570 Bytes, 120 Jahre

(Fügen Sie ~ 2⅔ Bytes pro zusätzlichem Jahr hinzu, wenn Sie den Offset kennen.)

Dies ist gut für Menschen, die vom 31. Januar 1900 bis zum 24. Januar 2020 geboren wurden und wahrscheinlich außerhalb dieses Bereichs abstürzen werden. Gibt es Bonuspunkte für die Anzahl der abgedeckten Jahre?

string Z(DateTime date)
{
    int[] days = new int[] {  3, 22, 11,  1, 19,  7, -3, 16,  5, -6, 13,  2,
                             21,  9, -2, 17,  6, -5, 14,  4, 23, 11,  0, 19,
                              8, -3, 16,  5, -5, 13,  2, 20,  9, -2, 17,  7,
                             -4, 14,  3, 22, 11, -1, 18,  8, -3, 16,  5, -6,
                             13,  1, 20,  9, -1, 17,  6, -4, 15,  3, 21, 11,
                              0, 18,  8, -3, 16,  5, -7, 12,  2, 20,  9, -1,
                             18,  6, -5, 14,  3, 21, 10,  0, 19,  8, -3, 16,
                              5, 23, 12,  1, 20,  9, -1, 18,  7, -5, 13,  3,
                             22, 10,  0, 19,  8, -4, 15,  4, -6, 12,  1, 21,
                             10, -2, 17,  6, -5, 13,  3, 22, 11,  0, 19,  8 };
    string[] signs = "Rat,Ox,Tiger,Rabbit,Dragon,Snake,Horse,Goat,Monkey,Rooster,Dog,Pig".Split(',');
    string[] elements = "Metal,Water,Wood,Fire,Earth".Split(',');
    string[] polarities = new string[] { "Yang", "Yin" };
    int year = date.Year - 1900;
    int x = year - (date.DayOfYear < days[year] + 28 ? 1 : 0);
    return signs[x % 12] + " - " + elements[x / 2 % 5] + " - " + polarities[x % 2];
}

Oder komprimiert (mit zusätzlichen Zeilenumbrüchen):

string Z(DateTime d){
int y=d.Year-1900,
x=y-(d.DayOfYear<new[]{3,22,11,1,19,7,-3,16,5,-6,13,2,21,9,-2,17,6,-5,14,4,23,11,0,19,8,-3,16,5,-5,13,2,20,9,-2,17,7,-4,14,3,22,11,-1,18,8,-3,16,5,-6,13,1,20,9,-1,17,6,-4,15,3,21,11,0,18,8,-3,16,5,-7,12,2,20,9,-1,18,6,-5,14,3,21,10,0,19,8,-3,16,5,23,12,1,20,9,-1,18,7,-5,13,3,22,10,0,19,8,-4,15,4,-6,12,1,21,10,-2,17,6,-5,13,3,22,11,0,19,8}[y]+28?1:0);
return "Rat,Ox,Tiger,Rabbit,Dragon,Snake,Horse,Goat,Monkey,Rooster,Dog,Pig".Split(',')[x%12]+" - "+"Metal,Water,Wood,Fire,Earth".Split(',')[x/2%5]+" - "+new[]{"Yang","Yin"}[x%2];
}

Einer der Tricks war, den Ursprung der Offset-Tabelle am 28. Januar zu haben. Dies erwies sich als die niedrigste Zeichenanzahl.

Wenn zufällig darauf bestanden wird, dass die Eingabe eine Zeichenfolge ist, fügen Sie 22 Zeichen hinzu, um die Methodensignatur in Folgendes zu ändern:

string Z(string i){

und fügen Sie die Zeile hinzu:

var d=DateTime.Parse(i);

EDITS:

  • Fügen Sie alle Zeichenfolgen in ein Array ein und fügen Sie den Ausgabeselektoren Offsets hinzu.
  • Der Tagesversatz wurde auf den 28. Januar geändert.
  • string.Split()Inspiration aus Eduard Florinescus Antwort .
  • Inline alle Arrays. Es hat mir nur 2 Zeichen erspart. : - /
Hand-E-Food
quelle
Speichern Sie 5 Zeichen, indem Sie " - "+new[]{"Yang","Yin"}[x%2]zu " - Y"+(x%2<1?"ang":"in"):)
Timwi
-1

Ziemlich einfach mit PHP unter Verwendung der Switch-Anweisung .

  • Die Berechnung ist so weit wie Sie wollen ...

    <?php
    
    // input the year
    $Y = 2020;
    
    // calculate the Z sign
    switch (($Y - 4) % 12) {
      case  0: $z = 'Rat';break;
      case  1: $z = 'Ox';break;
      case  2: $z = 'Tiger';break;
      case  3: $z = 'Rabbit';break;
      case  4: $z = 'Dragon';break;
      case  5: $z = 'Snake';break;
      case  6: $z = 'Horse';break;
      case  7: $z = 'Goat';break;
      case  8: $z = 'Monkey';break;
      case  9: $z = 'Rooster'; break;
      case 10: $z = 'Dog';break;
      case 11: $z = 'Pig';break;
    }
    
    // calculate the e
    switch (($Y / 2) % 5) {
      case  0: $e = 'Metal';break;
      case  1: $e = 'Water';break;
      case  2: $e = 'Wood'; break;
      case  3: $e = 'Fire'; break;
      case  4: $e = 'Earth'; break;
    }
    
    // calculate the polarity
     switch ($Y % 2) {
        case  0: $p = 'Yang';break;
        case  1: $p = 'Yin';break;
    
    }
    
     echo '$Y is $z - $e - $p.';
    
MACboyet
quelle
1
Willkommen bei PPCG! Wir verlangen, dass alle Antworten ernsthafte Konkurrenten sind. Im Fall von Code-Golf benötigen wir Antworten, um den Code zu verkürzen. Zum Beispiel Variablennamen mit einem Buchstaben, Entfernen von Leerzeichen usw.
Verkörperung der Ignoranz
1
Willkommen bei PPCG, Ihr Code funktioniert nur für Jahre, nicht vollständige Daten
Eduard Florinescu
das ist wahr. Es ist schwieriger als ich denke ...
MACboyet
Entfernen Sie die Leerzeichen und kürzen Sie die Var bereits. danke für die Info
MACboyet