中国の干支を計算する


10

中国の旧正月が近づいていることを考えると、特定の日付の中国の黄道帯、元素、および太極拳を計算するための課題があります。

入力は日付でなければなりません:

1/31/2014

ここで使用される日付はUSスタイルですが、mm/dd/yyyyISO-8601スタイルの場合もあります。yyyy-mm-ddそのため、日付入力のスタイルは厳密ではありません。

出力は、日付に対応する要素とそれに対応するTaijituを含む、中国の黄道帯の動物の標示である必要があります。

Horse - Wood - Yang

黄道帯-要素-Taijituの関係を示す表は次のとおりです。中国の黄道帯-年

出力形式は厳密ではありませんが、動物、要素、およびTaijituコンポーネントを含み、何らかの方法で区切られる必要があります。

上記の日付の有効な出力の例には、次のものがあります。

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

プログラムは、今日の日付を含め、少なくとも100年の範囲で有効な出力を返す必要があります。これは、少なくとも60年(干支)の2サイクルを考慮する必要があることを意味します。


3
干支の年の始まりを計算する方法への便利なリンクがありますか?
Hand-E-Food

3
ゾディアック年の計算方法はわかりませんが、「非常に単純なようです」。たぶん、今のところこの質問を閉じて、これらの小さな詳細が解決されたら、もう一度開く必要がありますか?

1
もう1つ注意すべき点は、常に1月21日から2月21日までの間であることです。
ジャスティン

3
リンクするテーブルは、その範囲外の日付に対して正しい出力を提供する必要がないという制限を追加しない限り、役に立ちません。
Peter Taylor

2
Eduard Florinescu、質問で明確にする必要がある2つのこと:1)@PeterTaylorが指す入力日付範囲、および2)出力形式は、例で指定したとおりにする必要がありますか?すべてのキャラクターが重要なので、この目的を達成してください。ありがとう。
ダレンストーン

回答:


4

Mathematica 63

さて、これは古くなっているかもしれませんが、動作します(多くの場合、日付入力があいまいです):

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

例:

z@"1/31/2014"

「馬(ヤンウッド)」


Mathematicaの幅広さに驚きます。出力形式は正しくありませんが、簡単に修正できると思います。
ダレンストーン

1
@DarrenStone Mathematicaが単にW | Aと呼ぶので、それはいくぶん不審です 出力はOPのフォーマットに正確に一致する必要があると思いますか?
Yves Klett

他の回答は質問の出力例とまったく同じようにフォーマットされており、どの言語でもそうするためには確かに追加のコードが必要です。しかし、それは本当に@EduardFlorinescuの質問です
ダレンストーン

@DarrenStone true。これは確かにかなりのオーバーヘッドを追加します。W&C ...
イブ・クレット2014年

4

C#– 357 337 339バイト

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

フォーマット済み:

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また、を回避することで、20文字以上を節約できますstring.Format
Hand-E-Food

ええ、そうです、ありがとう、私はさまざまなs%2 == 0などをゴルフしようとしましたが、大きなものを忘れていました。:-)そして、実際には、それはちょうど20文字、IIANMでした。
モルメジル2014年

4

Python 2:360 * 387 586 594-文字

さらに削減

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]

上記のコードは、次の間隔で機能します。1924年2月5日– 2043年12月31日

例:上記のコードを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]

次にを押してEnter、このような日付を入力します

6/13/2018

そしてEnterもう一度押すと、出力は

Dog Earth Yang


* ブライアンのコメント参照のヘルプにより、さらに27バイト削減


2
base-36の数値に「math」が2回含まれていることに気付きましたか?:)
Timwi

1
@Timwi:Dいいえ、私はしませんでした、そしてそれは素晴らしくて不気味です!
Eduard Florinescu 2014

エデュアルド、d = int(base 36 number)の部分を説明してもらえますか?同様の問題についてスタックオーバーフローの研究を行っているあなたの答えに出くわしました。年の計算を1500〜2043年の範囲に拡張する必要があります。助けてくれてありがとう。
Luis Miguel

1
いくつかのマイクロ最適化により、さらに23文字を保存できます。reddit.com/r/Python/comments/2oqobw/…を
Brian

1
@Timwi 1math6および2math6。前の5と次の3でさえ、その間に異なる文字がミラーリングされています。それは3spooky5meです。
マジックタコの壺

3

ルビー、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]]*' - '

これは、1924年2月5日から2044年1月29日までの日付で機能します。


その「マジック」番号は一体何なのでしょうか?
tomsmeding 2014

1
@tomsmeding、それはコンパクトさのためにBase 36でエンコードされた600ビット整数です。ビットフィールドに分け、それは1924年と1944年の間に毎年旧暦の最初の日のテーブルだ
ダレン・ストーン

3

GolfScript(212文字)

これは印刷不可能な文字を使用するため、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/=

文字列エスケープを使用し、したがって少し長い同等のプログラムは次のとおりです。

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

興味深い部分は、日付を指定すると、そのグレゴリオ年に該当する旧正月の前か後かを計算することです。私は前の質問で使用したイースター計算アルゴリズムからインスピレーションを得て、新年の日付のかなり単純な計算を探しました。結局、私はそこまでの道のりをたどる簡単な式と、エラー項のルックアップテーブルを使用しました。

簡単な計算はday_of_year = 21 + (19 * year % 30)です。エラー項はからの範囲(1924〜2044)08超え、年ごとに2倍以上変化しないため、ルックアップテーブルはバランスのとれた3値でエンコードされ、エラーはaのエラー項を合計することによって計算されます。テーブルの接頭辞。


Mathematicaが外部リソースを使用していることを除いて、これまでのところ、最も短いです。+1
エドゥアルドフロリネスク2014

2

C#、630 611 604 572 570バイト、120年

(オフセットがわかっている場合は、追加の年ごとに〜2⅔バイトを追加します)

これは、1900年1月31日から2020年1月24日までに生まれた人には適切であり、その範囲外でクラッシュする可能性があります。対象年数にボーナスポイントはありますか?

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

または圧縮(改行を追加):

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

トリックの1つは、オフセットテーブルの原点を1月28日にすることでした。これは、文字数が最も少ないことがわかりました。

偶然に入力が文字列であると主張されている場合は、22文字を追加してメソッドシグネチャを次のように変更します。

string Z(string i){

次の行を追加します。

var d=DateTime.Parse(i);

編集:

  • すべての文字列を1つの配列に入れ、出力セレクターにオフセットを追加します。
  • 日オフセットを1月28日に変更しました。
  • string.Split()エドゥアルドフロリネスクの回答からのインスピレーション。
  • すべてのアレイをインライン化。2文字しか節約できませんでした。:-/

:)に変更" - "+new[]{"Yang","Yin"}[x%2]して5文字を節約します" - Y"+(x%2<1?"ang":"in")
Timwi

-1

PHPでSwitchステートメントを使用するのはかなり簡単です。

  • 計算はあなたがしたい限りです...

    <?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
PPCGへようこそ!すべての回答は真剣な競争相手である必要があるため、コードゴルフの場合は、コードを短くするための努力をするための回答が必要です。たとえば、1文字の変数名、余分な空白の削除など
無視の実施形態

1
PPCGへようこそ。コードは完全な日付ではなく、数年間のみ機能します
Eduard Florinescu

それは本当です。思ったより難しい…
MACboyet

スペースを削除し、varを既に短縮しました。情報をありがとう
MACboyet
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.