Çince Zodyak işareti hesaplamak


10

Çin Yeni Yılı'nın geleceği göz önüne alındığında, burada belirli bir tarih için Çin Zodyakını, elementini ve Taijitu'yu hesaplamak için bir zorluk var.

Girdi bir tarih olmalıdır:

1/31/2014

Burada kullanılan tarih ABD stilidir mm/dd/yyyy, ancak alternatif olarak ISO-8601 stili de olabilir: yyyy-mm-ddbu nedenle tarih girişi stili katı değildir.

Çıktı , tarihe karşılık gelen elemanı ve Taijitu muadilini içeren Çin Zodyakındaki hayvan işareti olmalıdır :

Horse - Wood - Yang

Burç - element - Taijitu ilişkisini gösteren bir tablo burada görülebilir: Çince Zodyak - Yıl

Çıktı formatı katı değildir, ancak hayvan, element ve Taijitu bileşenini içermelidir ve bir şekilde sınırlandırılmalıdır.

Yukarıdaki tarih için geçerli çıktı örnekleri şunları içerebilir:

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

Programınız, bugünün tarihi de dahil olmak üzere en az 100 yıl boyunca geçerli çıktı döndürmelidir. Bu, en az iki 60 yıllık ( Sexagenary ) döngüyü hesaba katması gerekeceği anlamına gelir .


3
Zodyak yılının başlangıcını nasıl hesaplayacağınız konusunda uygun bir bağlantınız var mı?
E-Yiyecek

3
Nasıl zodaic yıl hesaplamak için hiçbir fikrim yok ama "oldukça basit görünüyor". Belki de şimdilik bu soruyu kapatmalı ve bu küçük ayrıntılar ütülenirse tekrar açmalıyız?

1
Dikkat edilmesi gereken başka bir şey, her zaman 21 Ocak ile 21 Şubat arasında dahil olmasıdır.
Justin

3
Bağladığınız tablo, bu aralığın dışındaki tarihler için doğru çıktıyı vermenin gereksiz olduğuna dair bir kısıtlama eklemediğiniz sürece işe yaramaz.
Peter Taylor

2
Eduard Florinescu, soruda açıklığa kavuşturmanız gereken iki şey: 1) @PeterTaylor'un işaret ettiği gibi giriş tarihi aralığı ve 2) çıktı biçimi örneğinizde belirttiğiniz gibi olmalı mı? Her karakter önemlidir, lütfen bu hedefi yapın. Teşekkürler.
Darren Stone

Yanıtlar:


4

Mathematica 63

Tamam, bu yaşlanıyor olabilir, ancak işe yarıyor (tarih girişi birçok durumda belirsizdir):

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

Misal:

z@"1/31/2014"

"At (Yang Wood)"


Mathematica'nın genişliği beni şaşırtıyor. Çıktı biçiminiz yanlış, ancak bunun kolayca düzeltildiğinden eminim.
Darren Stone

1
@DarrenStone biraz acayiptir çünkü Mathematica sadece W | A'yı çağırır. Çıktının OP'nin biçimlendirmesine tam olarak uyması gerektiğini düşünüyor musunuz?
Yves Klett

Diğer cevaplar tam olarak sorunun örnek çıktısı gibi biçimlendirilmiş gibi görünüyor ve kesinlikle herhangi bir dilde bunu yapmak için ekstra kod gerekiyor. Ama bu gerçekten @EduardFlorinescu için bir soru
Darren Stone

@DarrenStone doğru. Bu kesinlikle biraz ek yük getirecektir. W&C ...
Yves Klett

4

C # - 357 337 339 bayt

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

biçimlendirilmiş:

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 Ayrıca, kaçınarak 20'den fazla karakter kaydedebilirsiniz string.Format.
El-E-Gıda

Evet, doğru, teşekkürler, çeşitli s% 2 == 0 golf oynamaya çalıştım ve büyük olanı unuttum. :-) Ve aslında, tam olarak 20 karakterdi, IIANM.
Mormegil

4

Python 2: 360 * 387 586 594 - Karakterler

Daha da azaltıldı

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]

Yukarıdaki kod aşağıdaki aralıklarla çalışır: 5 Şub 1924 - 31 Aralık 2043

Örnek: yukarıdaki kodu python yorumlayıcı imlecine yapıştırdıktan sonra

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

ve düğmesine basın Enter, böyle bir tarih girin

6/13/2018

ve sonra Entertekrar basın , çıkış

Dog Earth Yang


* Brian'ın yardımı ile 27 bayt azaltıldı yorumları görmek.


2
Baz-36 numaranızın iki kez “matematik” içerdiğini fark ettiniz mi? :)
Timwi

1
@Timwi: D Hayır, yapmadım ve bu hem güzel hem de ürkütücü!
Eduard Florinescu

Eduard, d = int (baz 36 sayı) bölümünü açıklayabilir misiniz? Benzer bir sorun için stackoverflow'da araştırma yaparak cevabınıza rastladım. Yıl hesaplamalarını 1500-2043 yıllarına genişletmem gerekiyor. Herhangi bir yardım için şimdiden teşekkürler.
Luis Miguel

1
Bazı mikrooptimisasyonlarla 23 karakter daha kaydedebilirsiniz. Bkz. Reddit.com/r/Python/comments/2oqobw/…
Brian

1
@Timwi 1math6ve 2math6. Önceki 5 ve aşağıdaki 3 bile aralarında farklı karakterlerle yansıtılmıştır. Bu 3spooky5me.
Sihirli Ahtapot Urn

3

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

Bu, 5 Şubat 1924 ile 29 Ocak 2044 arasındaki tarihler için çalışacaktır.


Bu "sihirli" numara nedir?
Şubat'ta tomsmeding

1
@tomsmeding, kompaktlık için Base 36'da kodlanmış 600 bitlik bir tam sayıdır. Bitfieldlere ayrılmış, 1924-1944 yılları arasında her yıl için ay takviminin ilk gününün bir tablosu.
Darren Stone

3

GolfScript (212 karakter)

Bu yazdırılamayan karakterler kullanır, bu nedenle xxd çıktısı:

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

Dize kullanan eşdeğer bir program kaçar ve bu nedenle biraz daha uzundur:

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

İlginç olan, tarihe göre, söz konusu Gregoryen yılındaki Çin Yeni Yılı'ndan önce veya sonra olsun hesaplama. Önceki bir soruda kullandığım Paskalya hesaplama algoritmasından ilham alarak , Yeni Yıl tarihinin oldukça basit bir hesaplamasını aradım. Sonunda beni orada en çok yol alır basit bir formül, artı hata terimi için bir arama tablosu ile gitti.

Basit hesaplama day_of_year = 21 + (19 * year % 30). Hata terimi aralıkları 0için 8ilgi aralıkta (2044 için 1.924) ve arama tablosu a hata terimlerini toplayarak dengeli üçlü ile kodlanan ve hata hesaplanır böylece, birden fazla tarafından her yıl hiç değişmez üzerinde tablonun öneki.


Güzel, şimdiye kadar en kısa, Mathematica dışında biri harici bir kaynak kullanıyor. +1
Eduard Florinescu

2

C # 630 611 604 572 570 bayt, 120 yıl

(ofseti biliyorsanız ek yıl başına ~ 2⅔ bayt ekleyin)

Bu, 31 Ocak-1900 ile 24 Ocak 2020 arasında doğan insanlar için iyidir ve muhtemelen bu aralığın dışında çökecektir. Kapsanan yılların bonus puanları var mı?

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

Veya yoğunlaştırılmış (satır sonları eklenmiş olarak):

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

Püf noktalarından biri, 28 Ocak'ta ofset masasının başlangıcına sahip olmaktı. Bu, en düşük karakter sayısına sahip olduğunu kanıtladı.

Şans eseri girişin bir dize olması konusunda ısrar ederse, yöntem imzasını şu şekilde değiştirmek için 22 karakter ekleyin:

string Z(string i){

ve satırı ekleyin:

var d=DateTime.Parse(i);

DÜZENLEMELER:

  • Tüm dizeleri bir diziye koyun ve çıkış seçicilerine ofsetleri ekleyin.
  • Gün ofseti 28 Ocak olarak değiştirildi.
  • string.Split()İlham Eduard Florinescu'nun cevabından alınmıştır .
  • Tüm dizileri satır içine aldım. Bana sadece 2 karakter kazandırdı. : - /

Değiştirerek 5 karakter kaydet " - "+new[]{"Yang","Yin"}[x%2]için " - Y"+(x%2<1?"ang":"in"):)
Timwi

-1

Switch deyimini kullanarak PHP ile oldukça düz ileri .

  • Hesaplama istediğiniz kadar ...

    <?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'ye Hoşgeldiniz! Tüm cevapların ciddi rakipler olmasını istiyoruz , bu yüzden kod golfü durumunda, kodu kısaltmak için çaba göstermemiz gerekiyor. Örneğin, tek harfli değişken adları, fazladan boşlukların kaldırılması, vb.
Cehaletin Somutlaştırılması

1
PPCG'ye hoş geldiniz, kodunuz sadece yılların tam tarihleri ​​için çalışmıyor
Eduard Florinescu

bu doğru. Düşündüğümden daha zor…
MACboyet

boşlukları çıkardı ve var zaten kısaltın. için teşekkürler
MACboyet
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.