Calculer le signe du zodiaque chinois

10

Étant donné que le nouvel an chinois arrive, voici un défi pour calculer le zodiaque chinois, l'élément et le Taijitu pour une date donnée.

L'entrée doit être une date:

1/31/2014

La date utilisée ici est le style américain mm/dd/yyyy, mais peut également être de style ISO-8601: yyyy-mm-ddle style de saisie de la date n'est donc pas strict.

La sortie doit être le signe animal dans le zodiaque chinois, y compris l'élément qui correspond à la date, et son homologue Taijitu :

Horse - Wood - Yang

Un tableau montrant la relation Zodiaque - élément - Taijitu peut être vu ici: Zodiaque chinois - Années

Le format de sortie n'est pas strict mais doit contenir des éléments animal, élément et Taijitu, et doit être délimité d'une certaine manière.

Des exemples de sortie valide pour la date ci-dessus peuvent inclure:

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

Votre programme doit renvoyer une sortie valide pour une plage d'au moins 100 ans, y compris la date d'aujourd'hui. Cela signifie qu'il devra tenir compte d'au moins deux cycles de 60 ans ( sexagénaires ).

Eduard Florinescu
la source
3
Avez-vous un lien pratique pour calculer le début d'une année de zodiaque?
Hand-E-Food
3
Vous ne savez pas comment calculer l'année zodaique mais cela "semble assez simple". Peut-être devrions-nous fermer cette question pour le moment et la rouvrir lorsque vous aurez aplani ces petits détails?
1
Une autre chose à noter est que c'est toujours entre le 21 janvier et le 21 février inclus.
Justin
3
Le tableau que vous liez n'est d'aucune utilité, sauf si vous ajoutez une restriction selon laquelle il n'est pas nécessaire de fournir la sortie correcte pour les dates en dehors de cette plage.
Peter Taylor
2
Eduard Florinescu, deux choses que vous devez clarifier dans la question: 1) la plage de dates d'entrée comme le souligne @PeterTaylor, et 2) le format de sortie doit-il être exactement celui que vous spécifiez dans votre exemple? Chaque personnage compte, alors faites cet objectif. Merci.
Darren Stone

Réponses:

4

Mathematica 63

D'accord, cela peut vieillir, mais cela fonctionne (la saisie de la date est ambiguë dans de nombreux cas):

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

Exemple:

z@"1/31/2014"

"Cheval (bois de Yang)"

Yves Klett
la source
L'étendue de Mathematica m'étonne. Votre format de sortie est incorrect, mais je suis sûr que cela est facilement corrigé.
Darren Stone
1
@DarrenStone c'est un peu peu glorieux car Mathematica appelle simplement W | A. Pensez-vous que la sortie doit correspondre exactement au format de l'OP?
Yves Klett
Il semble que les autres réponses soient formatées exactement comme l'exemple de sortie de la question et il faut certainement du code supplémentaire pour le faire dans n'importe quelle langue. Mais c'est vraiment une question pour @EduardFlorinescu
Darren Stone
@DarrenStone true. Cela ajoutera certainement pas mal de frais généraux. W&C ...
Yves Klett
4

C # - 357 337 339 octets

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

Formaté:

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
la source
+1 De plus, vous pouvez enregistrer plus de 20 caractères en évitant string.Format.
Hand-E-Food du
Oui, c'est vrai, merci, j'ai essayé de jouer aux différents s% 2 == 0 etc., et j'ai oublié le gros. :-) Et, en fait, c'était exactement 20 caractères, IIANM.
Mormegil
4

Python 2: 360 * 387 586 594 - Personnages

Encore réduit

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]

Le code ci-dessus fonctionne pour l'intervalle suivant: 5 février 1924 - 31 décembre 2043

Exemple: après avoir collé le code ci-dessus dans le curseur de l'interpréteur 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]

puis appuyez sur Enter, entrez une date comme celle-ci

6/13/2018

puis appuyez à Enternouveau, la sortie sera

Dog Earth Yang


* réduit encore 27 octets avec l'aide de Brian voir les commentaires.

Eduard Florinescu
la source
2
Avez-vous remarqué que votre numéro de base-36 contient deux fois «math»? :)
Timwi
1
@ Timwi: D Non, je ne l'ai pas fait, et c'est à la fois agréable et effrayant!
Eduard Florinescu
Eduard, pourriez-vous expliquer la partie d = int (nombre de base 36)? Je suis tombé sur votre réponse en faisant des recherches dans stackoverflow pour un problème similaire. J'ai besoin d'étendre les calculs de l'année à la plage des années 1500 - 2043. Merci d'avance pour toute aide.
Luis Miguel
1
Vous pouvez enregistrer 23 autres caractères avec quelques microoptimisations. Voir reddit.com/r/Python/comments/2oqobw/…
Brian
1
@Timwi 1math6et 2math6. Même le précédent 5 et le suivant 3 sont mis en miroir avec différents caractères entre eux. C'est 3spooky5me.
Urne de poulpe magique du
3

Rubis, 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]]*' - '

Cela fonctionnera pour les dates entre le 5 février 1924 et le 29 janvier 2044.

Darren Stone
la source
Qu'est-ce que c'est que ce chiffre "magique"?
tomsmeding
1
@tomsmeding, c'est un entier de 600 bits encodé en Base 36 pour la compacité. Brisé en champs de bits, c'est un tableau du premier jour du calendrier lunaire pour chaque année entre 1924 et 1944.
Darren Stone
3

GolfScript (212 caractères)

Cela utilise des caractères non imprimables, voici donc la sortie de 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 programme équivalent qui utilise des échappements de chaîne et est donc un peu plus long est:

'-'/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 partie intéressante est le calcul, compte tenu de la date, que ce soit avant ou après le nouvel an chinois qui tombe dans cette année grégorienne. En m'inspirant de l' algorithme de calcul de Pâques que j'ai utilisé dans une question précédente, j'ai cherché un calcul assez simple de la date du Nouvel An. En fin de compte, j'ai opté pour une formule simple qui me permet d'obtenir la plupart du temps, plus une table de recherche pour le terme d'erreur.

Le calcul simple est day_of_year = 21 + (19 * year % 30). Le terme d'erreur varie de 0à 8plus de la plage d'intérêt (1924 à 2044) et ne change jamais d'année en année de plus d'un, de sorte que la table de recherche est codée en ternaire équilibré et l'erreur est calculée en additionnant les termes d'erreur d'un préfixe du tableau.

Peter Taylor
la source
Agréable, le plus court jusqu'à présent, sauf que Mathematica utilise une ressource externe. +1
Eduard Florinescu
2

C #, 630 611 604 572 570 octets, 120 ans

(ajoutez ~ 2⅔ octets par année supplémentaire si vous connaissez le décalage)

Ceci est bon pour les personnes nées du 31 janvier 1900 au 24 janvier 2020 et tombera probablement en dehors de cette plage. Y a-t-il des points bonus pour le nombre d'années couvertes?

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

Ou condensé (avec des sauts de ligne supplémentaires):

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

L'une des astuces était d'avoir l'origine de la table offset au 28 janvier. Cela s'est avéré avoir le plus petit nombre de caractères.

Si par hasard on insiste sur le fait que l'entrée est une chaîne, ajoutez 22 caractères pour changer la signature de la méthode en:

string Z(string i){

et ajoutez la ligne:

var d=DateTime.Parse(i);

MODIFICATIONS:

  • Mettez toutes les chaînes dans un tableau et ajoutez des décalages aux sélecteurs de sortie.
  • Changé le décalage du jour au 28-Jan.
  • string.Split()Inspiration tirée de la réponse d' Eduard Florinescu .
  • Inscrit tous les tableaux. Cela ne m'a sauvé que 2 caractères. : - /
Hand-E-Food
la source
Enregistrez 5 caractères en changeant " - "+new[]{"Yang","Yin"}[x%2]pour " - Y"+(x%2<1?"ang":"in"):)
Timwi
-1

Assez simple avec PHP en utilisant l'instruction Switch .

  • Le calcul est aussi loin que vous le souhaitez ...

    <?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
la source
1
Bienvenue chez PPCG! Nous exigeons que toutes les réponses soient de sérieux concurrents , donc dans le cas du code-golf, nous avons besoin de réponses pour faire un effort pour raccourcir le code. Par exemple, noms de variables à une seule lettre, suppression d'espaces supplémentaires, etc.
Incarnation de l'ignorance
1
Bienvenue chez PPCG, votre code ne fonctionne que pendant des années, dates non complètes
Eduard Florinescu
c'est vrai. C'est plus difficile que je ne le pense…
MACboyet
supprimé les espaces et raccourcir le var déjà. merci pour l'info
MACboyet