Calcola il segno zodiacale cinese


10

Dato che il nuovo anno cinese sta arrivando, ecco una sfida per calcolare lo zodiaco cinese, l'elemento e il Taijitu per una determinata data.

L'input dovrebbe essere una data:

1/31/2014

La data usata qui è lo stile americano mm/dd/yyyy, ma in alternativa può essere lo stile ISO-8601: yyyy-mm-ddquindi lo stile dell'input della data non è rigoroso.

L'output dovrebbe essere il segno animale nello zodiaco cinese compreso l'elemento che corrisponde alla data e la sua controparte Taijitu :

Horse - Wood - Yang

Una tabella che mostra la relazione Zodiac - element - Taijitu può essere vista qui: Chinese Zodiac - Years

Il formato di output non è rigoroso ma dovrebbe contenere animali, elementi e componenti di Taijitu e dovrebbe essere delimitato in qualche modo.

Esempi di output validi per la data sopra potrebbero includere:

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

Il programma dovrebbe restituire un output valido per un intervallo di almeno 100 anni, inclusa la data odierna. Ciò significa che dovrà tenere conto di almeno due cicli di 60 anni ( sessagenari ).


3
Hai un comodo link su come calcolare l'inizio di un anno zodiacale?
Hand-E-Food

3
Non hai idea di come calcolare l'anno zodaico ma "sembra piuttosto semplice". Forse dovremmo chiudere questa domanda per ora e riaprirla quando hai risolto quei piccoli dettagli?

1
Un'altra cosa da notare è che è sempre tra il 21 gennaio e il 21 febbraio inclusi.
Justin,

3
La tabella collegata è inutile a meno che non si aggiunga una restrizione che non è necessario fornire l'output corretto per le date al di fuori di tale intervallo.
Peter Taylor,

2
Eduard Florinescu, due cose che dovresti chiarire nella domanda: 1) inserisci l'intervallo di date come sottolinea @PeterTaylor e 2) il formato di output deve essere esattamente come specificato nel tuo esempio? Ogni personaggio conta quindi per favore fai questo obiettivo. Grazie.
Darren Stone,

Risposte:


4

Mathematica 63

Va bene, potrebbe invecchiare, ma funziona (l'inserimento della data è ambiguo in molti casi):

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

Esempio:

z@"1/31/2014"

"Cavallo (Yang Wood)"


L'ampiezza di Mathematica mi stupisce. Il formato di output non è corretto, ma sono sicuro che sia stato risolto facilmente.
Darren Stone,

1
@DarrenStone è in qualche modo senza gloria perché Mathematica chiama semplicemente W | A. Pensi che l'output debba adattarsi esattamente alla formattazione dell'OP?
Yves Klett,

Sembra che le altre risposte siano formattate esattamente come l'output di esempio della domanda e ci vuole sicuramente del codice extra per farlo in qualsiasi lingua. Ma questa è davvero una domanda per @EduardFlorinescu
Darren Stone,

@DarrenStone true. Ciò aggiungerà sicuramente un po 'di sovraccarico. W&C ...
Yves Klett,

4

C # - 357 337 339 byte

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

formattato:

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

+1 Inoltre, puoi salvare oltre 20 caratteri evitando string.Format.
Hand-E-Food

Sì, giusto, grazie, ho provato a giocare a golf con le varie s% 2 == 0 ecc. E ho dimenticato quello grande. :-) E, in realtà, aveva esattamente 20 caratteri, IIANM.
Mormegil,

4

Python 2: 360 * 387 586 594 - Personaggi

Ridotto ulteriormente

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]

Il codice sopra funziona per il seguente intervallo: 5 febbraio 1924 - 31 dic 2043

Esempio: dopo aver incollato il codice sopra nel cursore dell'interprete python

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

quindi premere Enter, inserire una data come questa

6/13/2018

e quindi premere di Enternuovo, l'uscita sarà

Dog Earth Yang


* Ridotto ulteriori 27 byte con l'aiuto di Brian vedere i commenti.


2
Hai notato che il tuo numero di base 36 contiene "matematica" due volte? :)
Timwi,

1
@Timwi: D No, non l'ho fatto, e questo è bello e spettrale!
Eduard Florinescu,

Eduard, potresti spiegare la parte d = int (numero base 36)? Ho trovato la tua risposta facendo ricerche su StackOverflow per un problema simile. Devo estendere i calcoli dell'anno tra il 1500 e il 2043. Grazie in anticipo per qualsiasi aiuto.
Luis Miguel,

1
Puoi salvare altri 23 caratteri con alcune microottimizzazioni. Vedi reddit.com/r/Python/comments/2oqobw/…
Brian

1
@Timwi 1math6e 2math6. Anche il precedente 5 e il successivo 3 sono specchiati con caratteri diversi tra loro. Questo è 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]]*' - '

Funzionerà per le date tra il 5 febbraio 1924 e il 29 gennaio 2044.


Che diavolo è quel numero "magico"?
Tomsmeding,

1
@tomsmeding, è un numero intero a 600 bit codificato in Base 36 per compattezza. Suddiviso in bitfield, è una tabella del primo giorno del calendario lunare per ogni anno tra il 1924 e il 1944.
Darren Stone,

3

GolfScript (212 caratteri)

Questo utilizza caratteri non stampabili, quindi ecco l'output di 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/=

Un programma equivalente che utilizza escape di stringa ed è quindi un po 'più lungo è:

'-'/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/=

La parte interessante è calcolare, data la data, che sia prima o dopo il capodanno cinese che cade in quell'anno gregoriano. Prendendo ispirazione dall'algoritmo di calcolo pasquale che ho usato su una domanda precedente, ho cercato un calcolo ragionevolmente semplice della data di Capodanno. Alla fine sono andato con una formula semplice che mi porta quasi ovunque, oltre a una tabella di ricerca per il termine di errore.

Il semplice calcolo è day_of_year = 21 + (19 * year % 30). Gli intervalli termine di errore 0per 8oltre il campo di interesse (1924 a 2044), e non cambia mai di anno in anno da più di uno, così la tabella di ricerca è codificato in ternario bilanciato e l'errore viene calcolato sommando i termini di errore di un prefisso della tabella.


Bello, il più breve finora, tranne quello di Mathematica che utilizza una risorsa esterna. +1
Eduard Florinescu,

2

C #, 630 611 604 572 570 byte, 120 anni

(aggiungi ~ 2⅔ byte per anno aggiuntivo se conosci l'offset)

Questo è un bene per le persone nate dal 31 gennaio al 1900 fino al 24 gennaio 2020 e probabilmente andrà in crash al di fuori di tale intervallo. Ci sono punti bonus per il numero di anni coperti?

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

O condensato (con interruzioni di riga aggiunte):

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

Uno dei trucchi era avere l'origine della tabella offset al 28 gennaio. Ciò ha dimostrato di avere il numero di caratteri più basso.

Se per caso si insiste sul fatto che l'input è una stringa, aggiungere 22 caratteri per modificare la firma del metodo in:

string Z(string i){

e aggiungi la riga:

var d=DateTime.Parse(i);

Modifiche:

  • Metti tutte le stringhe in un array e aggiungi gli offset ai selettori di output.
  • Modificato l'offset del giorno a 28 gennaio.
  • string.Split()Ispirazione presa dalla risposta di Eduard Florinescu .
  • Allineato tutti gli array. Mi ha salvato solo 2 personaggi. : - /

Salva 5 caratteri cambiando " - "+new[]{"Yang","Yin"}[x%2]in " - Y"+(x%2<1?"ang":"in"):)
Timwi

-1

Abbastanza semplice con PHP usando l'istruzione Switch .

  • Il calcolo è quanto vuoi ...

    <?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.';
    

1
Benvenuti in PPCG! Abbiamo bisogno che tutte le risposte siano concorrenti seri , quindi nel caso del code-golf, abbiamo bisogno di risposte per fare uno sforzo per accorciare il codice. Ad esempio, nomi di variabili a lettera singola, rimozione di spazi bianchi aggiuntivi, ecc.
Incarnazione dell'ignoranza,

1
Benvenuto in PPCG, il tuo codice funziona solo per anni non date complete
Eduard Florinescu,

questo è vero. È più difficile di quanto penso ...
MACboyet,

rimosso gli spazi e accorciare già il var. grazie per le informazioni
MACboyet,
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.