Sütümün süresi doldu mu?


98

Aww, dostum, bu son kullanma tarihi ayları harflerle yazmıyor! 10 Mart'ta mı yoksa 3 Ekim'de mi bittiğini söyleyemem ... Bekle, hayır, boşver, yıl 2012 diyor. (Sokaktaki yarı kullanılmış peynir tenekesi çöp kutusuna benzeyebilir)

Bir an için bu marinara kavanoğunun ne zaman bitmesi gerektiğine karar vermek için çok meşgul olduğunuzu varsayalım. Sadece Cliff Notes versiyonunu istiyorsan: vadesi geçmiş olması ne kadar olası? Biraz kod yazalım!

Üreticilerin, tarihi üç tam formattan birinde, sipariş edilen bir tam sayı üçlüsü olarak yazdığını biliyorsunuz:

YEAR  MONTH DAY
MONTH DAY   YEAR
DAY   MONTH YEAR

Ve bazı tarihlerin sadece bir veya iki şekilde yorumlanabileceğini biliyorsunuz, üçünün hepsinde değil: 55'inin 55-11-5bir yıl olması gerekir, yani bu özel Twinki kutusu kutusu 5 Kasım 1955'te sona erdi. Yıl bazen dört basamaklı iki değil, bazı seçenekleri ekarte edebilir. İki basamak olduğunda, 50, 99, 1950.1999 ve 0..49, 2000..2049 anlamına gelir.

İşiniz, yukarıdaki yorumlardan en az birinde geçerli bir tarih olan ve tam olarak hala iyi olma şansını veren bir tam sayı dizisi alan bir program veya işlev yazmaktır. Yüzde şans, sadece bugünün tarihinden önceki veya sonraki tarihin geçerli yorumlarının yüzdesidir .

Bir tamsayı dizisi, [Int]eğer bir işlevin argümanı ise , dilin uzunluğu 3 türünde olacaktır ve STDIN’de bir tam program. *

"Bugünün tarihi", bir tarih fonksiyonu aracılığıyla elde edilen bugünün gerçek tarihi veya STDIN'de işlev veya ekstra paramater için ekstra argüman olarak verilen tarih olabilir. Unix çağında, yukarıdaki üç yoldan birine girilen bir yıl-ay-gün üçlü veya daha uygun bir şekilde olabilir.

Hadi birkaç örnek verelim! Son kullanma tarihi girişi çizgi ile ayrılmış bir stilde olacaktır ve aşağıdaki örneklerin bugünün tarihinin 5 Temmuz 2006 olduğunu varsayalım.

  • 14-12-14- Bunun için her iki geçerli yorum (DMY ve YMD) 14 Aralık 2014'e eşdeğerdir. Çıktı 100, çünkü bu ürün kesinlikle hala iyi.
  • 8-2-2006- Son sayı, dört basamaklı olduğundan kesinlikle bir yıldır. Bu, 8 Şubat (süresi dolmuş) veya 2 Ağustos (hala iyi) olabilir. Çıktı 50 .
  • 6-7-5- Bu herhangi bir şey olabilir! "5 Temmuz 2006" yorumu hala iyi (sadece bir gün için), fakat kalan ikisi 2005 yılında yapıldı ve mümkün olduğunca çabuk atılması gerekiyor. Çıkış 33 .
  • 6-5-7- Burada, üç yorumdan ikisi güvende. Ondalık yukarı veya aşağı yuvarlayabilirsiniz, böylece 66 ya da 67 her ikisi de tamamdır.
  • 12-31-99- Tamam, bu, yüzyılın başından itibaren açıkça belli (50 - 99 yaşları 19XX, ve 31 muhtemelen bir ay olamaz). Büyük bir yağ 0 ve gerçekten buzdolabınızı daha sık temizlemelisiniz.

Yukarıda belirtilen standartlara uymayan herhangi bir girişin yukarıdaki çıkış kurallarına özgü olmadığını güvenle kabul edebilirsiniz.

Web isteği veya standart boşluk yok. Tarih işleme kütüphanelerine izin verilir. Bu kod golf: En kısa program kazanabilir.

* Eğer beyin ya da benzer şekilde veri türü engellenmiş bir dil kullanıyorsanız, girdideki ilk üç karakterin ASCII değerlerinin tarih için tamsayılar olduğunu varsayabilirsiniz. Bu, dört basamaklı yıl mantığını hariç tutuyor, elbette, ancak Brainfuck'ta bunun için bir çözüm görerek çok sizi şaşırtacağımızı düşünüyorum.


39
Hmm ... şu anki yıl 2014 değil, 2006 değil. Sütünüz en geç sekiz seneyi geçiyor.
John Dvorak

11
@JanDvorak Anlamlı örnekler oluşturmak için çok uğraşmak istemedim, bu yüzden kolaylaştırmak için bugünün tarihini değiştirdim.
algorithmshark

7
@ Dgrin91 umurumda değil, ben hala onları yiyeceğim: D
aditsu

6
Avustralya'da, süt kullanımdan bir hafta öncesine kadar sona eriyor
gnibbler

5
Yasal bir gün veya ay olamayacağından, içinde 00 olan bir test eklemelisiniz.
MtnViewMark

Yanıtlar:


5

k4 (90) (88) (87) (82)

{100*(+/~d<x)%3-+/^d:{"D"$"."/:$|z,y,x+(x<100)*100*19+x<50}.'y@/:3 3#.:'$21020101}

İle Çağır xait .z.Dbugüne kıyasla ya da başka seçtiğiniz değişmez bir tarih için (bir yerleşiği):

  f:{100*(+/~d<x)%3-+/^d:{"D"$"."/:$|z,y,x+(x<100)*100*19+x<50}.'y@/:3 3#.:'$21020101}
  .z.D f'(14 12 14;8 2 2006;6 7 5;6 5 7;12 31 99)
100 0 0 0 0f
  2006.07.05 f'(14 12 14;8 2 2006;6 7 5;6 5 7;12 31 99)
100 50 33.33333 66.66667 0

Bu, temel olarak @ Alex-l'in Python çözümünün limanıdır, birkaç tane çeşitli golf oyunu eklenmiştir:

  • Düzenleme talimatları, birkaç karakter kaydetmek için bir dizgede kodlanmıştır.
  • Koşullu mantık (ab), tamsayı olarak gerçeği kullanır (ancak Python çözümünden farklı bir şekilde).
  • Geçerlilik testi biraz farklıdır - k4 / q herhangi bir dizgiyi herhangi bir veri tipine ayrıştırır; mantıklı gelmezse, sadece null değerini döndürür. Böylece, iç işlevdeki boş olan veya olmayan tarih listesini veririm.
  • Nihai sonuç, muhtemel tarih yorumlarının ne kadarının sıfır olduğunu ve karşılaştırma tarihinden ne kadar az olduğunu kontrol etmekten gelir; Burada boş tarihin diğer tarihlerden daha az olduğu kabul edilir.

1
Sen son 0 kaldırarak bir char kaydedebilirsiniz "012201210"beri #periyodik olarak öğeleri alır. Aslında, son iki dava değiştirerek ikinci Char bu şekilde kaydedebilirsiniz: 3 3#.:'"0122102".
algorithmshark

İç func'un artalarını tersine çevirerek bir parka daha kavuşup parenleri kurtardı (ancak tersini ekledim). Biri başka iki karakter kurtarmama yardım edebilir mi? APL beni atıyor!
Aaron Davies

Sonunda matematiği yeniden yazarak başka bir beş tane daha tıraş ettim. Başa dön!
Aaron Davies,

Ciddi işlevsel olmayan kod yazmadan tenezzül eğer, ben genel ad alanını kirletici başka byte tıraş edebilirsiniz: {c*(+/~d<x)%3-+/^d:{"D"$"."/:$|z,y,x+(c*19+x<50)*x<c::100}.'y@/:3 3#.:'$21020101}.
Aaron Davies,

14

Yakut, 115 karakter

f=->a,t{[a,a.rotate(~s=r=0),a.reverse].map{|x,*y|(t>Time.gm(x<100?x+2e3-100*x/=50:x,*y)||r+=100
s+=1)rescue p}
r/s}

Bu fiki argüman alan bir işlevi tanımlar : girişi içeren bir dizi ve "bugünün" tarihi.

Örnekler:

f[[14,12,14], Time.new]
100
f[[8,2,2006], Time.new]
0
f[[8,2,2006], Time.new(2006, 7, 5)]
50
f[[6,7,5], Time.new(2006, 7, 5)]
33

12

Python 2,7 - 172

Datetime modülünü geçerlilik ve tarihlerin karşılaştırması için kullanıyorum. Eğer dategiriş çıkış geçerli bir datetime yapamaz, bu yükseltir ValueError. Bu süre sdolmamış tarihlerin toplamıdır ve tgeçerli tarihlerin toplamıdır. True == 1Python'a ekleme ve indeksleme amacıyla bu gerçeği kullanıyorum . Ayrıca (1900,2000) yerine 25 * (76,80) kullanarak bir karakter kaydederim.

İkinci girinti seviyesindeki satırların 2 boşluk değil, bir sekme karakteri kullandığına dikkat edin.

def f(e,c,s=0,t=3):
 for Y,M,D in(0,1,2),(2,0,1),(2,1,0):
  y=e[Y]
  try:s+=date(y+25*[[76,80][y<50],0][y>99],e[M],e[D])>=c
  except:t-=1
 return 100*s/t

Bunu testin sonuna ekleyin:

examples = [[14,12,14],[8,2,2006],[6,7,5],[6,5,7],[12,31,99]]
for e in examples:
 print f(e, date(2006,7,5))

10

PowerShell, 183 173 168

[int](100*(($d=@(($a,$b,$c=$args[0]),($c,$a,$b),($c,$b,$a)|%{$_[0]+=1900*($_[0]-le99)+100*($_[0]-le49)
.{date($_-join'-')}2>$x}|sort -u))-ge(date)+'-1').Count/$d.Count)
  • int[]Parametre olarak giriş , örneğin

    PS> ./milk.ps1 5,6,7
    
  • Stderr'deki çıkışın izin verilip verilmediğini bilmediğim sürece hata mesajları try/ aracılığıyla susturulur catch.
  • Günün tarihini bir gün değiştirecek şekilde +"-1"yorumlanan tarihi kullanmak .AddDays(-1), böylece dünle (yalnızca bugün yerine) karşılaştırabiliriz. Bu, saat 0:00 ile randevu almamız sorununu çözer ancak bugünden saat ile tarih karşılaştırmamız gerekir.
  • Şimdiye kadar yoğun şekilde satır içi
  • Hataları kısmak için yeni bir numara kullanmak biraz daha kısa

6

R, 269

Bunun R'de kolay olmasını bekliyordum, ancak tek basamaklı yıllar oldukça büyük bir eğrelticiydi. Bunun olduğundan daha iyi olabileceğini hissediyorum.

lubridateCRAN'dan bir pakettir, yüklemeniz gerekebilir install.packages("lubridate").

require(lubridate)
f = function(d){
d=sapply(d,function(l)if(nchar(l)==1)sprintf("%02d",l)else l)
d=paste0(d,collapse="-")
t=ymd(Sys.Date())
s=na.omit(c(ymd(d),mdy(d),dmy(d)))
s=lapply(s,function(d){
if(year(d)>2049){year(d)=year(d)-100;d}
else d})
sum(s>t)/length(s)}

Kullanım: tamsayı vektörü f(c(d1,d2,d3))nerede c(d1,d2,d3)?

örneğin f(c(6,10,14))iadeler 0.3333333.

lubridatePaket farklı sıralarda tarihleri ayrıştırmak için sarıcı fonksiyonları bir dizi vardır. Bunları hangi formatların geçerli tarihler ürettiğini, geçersiz olanları attığını ve sonra da hangilerinin henüz oluşmadığını görmek için kullanırım.


6

Mathematica, 163 153 164 bayt

( düzenleme: 1950 - 2049 aralığının dışındaki sabit tarihler)

f=100.Count[#,x_/;x<1]/Length@#&[DateDifference[#,Date[]]&/@Cases[{If[#<100,Mod[#+50,100]+1950,#],##2}&@@@{{##},{#3,#2,#},{#3,#,#2}}&@@#,d_/;DateList@d~Take~3==d]]&

Bu, sizin gibi çağırabileceğiniz bir işlevi tanımlar.

f[{6,7,5}]

Şu anda, yüzde yuvarlatılmamıştır (OP'nin netleşmesini beklemek).

İşte herhangi Mathematica bilgisi olmadan anlaşılabilir olmalıdır biraz uzun açıklama (notudur &parametreler anonim fonksiyon olarak adlandırılır Ondan geriye kalan her şeyi yapar #, #2, #3...):

{{##},{#3,#2,#},{#3,#,#2}}&

Bu, 3 parametreyi a,b,c3 listeye dönüştüren bir fonksiyon tanımlar {{a,b,c},{c,b,a},{c,a,b}. Bunun ##sadece tüm parametrelerin bir dizisi olduğuna dikkat edin.

{{##},{#3,#2,#},{#3,#,#2}}&@@#

Son kullanma tarihi {y,m,d}için geçerli olan bu üç olası permütasyonun her birinin listesini verir .

{If[#<100,Mod[#+50,100]+1950,#],##2}&

Bu, üç parametreyi alan a,b,cve ilklerin verilen kurallara göre bir yıla dönüştürüldüğü üçün bir listesini döndüren adsız bir işlevdir : 50ve ve arasındaki sayılar 99(modulo 100), bir 20. yüzyıl yılına dönüştürülür, 0ve arasındaki sayılar ve 49( modulo 100) bir 21. yüzyıl yılına çevrildi, diğerleri kaldı. Burada, ##2ikincisi ile başlayan bir dizi parametredir, yani b,c.

{If[#<100,Mod[#+50,100]+1950,#],##2}&@@@{{##},{#3,#2,#},{#3,#,#2}}&@@#

Önceki üç sonucun her birine uygulandığında, bu yıl formatlarını kanlılaştırır. Bunu canonicalDatesşu ifadeyi kısaltmak için diyelim :

Cases[canonicalDates,d_/;DateList@d~Take~3==d]

Bu geçersiz yorumları filtreliyor. Çeşitli tarih biçimlerinden DateList@dtam bir {y,m,d,h,m,s}gösterim yapar . Aynı sırayla listelerini yorumlayacaktır ama yakalamak Bunun ne olabilir gibi şeyler geçmesine {8,2,2006}o hesaplar bu durumda 8 years + 2 months + 2006 days. Bu nedenle, iade edilen listenin ilk üç öğesinin girdiyle aynı olduğunu kontrol ediyoruz (bu, yalnızca uygun aralıktaki ay ve gün olduğunda gerçekleşebilir).

Aşağıdaki satırları kısaltmak için şu validDatesandan itibaren o ifadenin sonucuna bakacağım :

DateDifference[#,Date[]]&

Tarih alan ve gün içindeki farkı döndüren başka bir adsız işlev (bugünden itibaren Date[]).

DateDifference[#,Date[]]&/@validDates

Bunu geçerli tarih yorumlarına ekleyin.

100.Count[#,x_/;x<1]/Length@#&

Bir liste ( #) verilen başka bir anonim işlev, o listedeki pozitif olmayan sayıların yüzdesini döndürür. .Sonuç olarak rasyonel sayıları önlemek için bir çarpma ama sadece son rakam değil (gibi şeyler olsun istiyorum 100/3yerine 33.333- bu bir sorun olmadığını Aslında bilmiyorum).

100.Count[#,x_/;x<1]/Length@#&[DateDifference[#,Date[]]&/@validDates]

Tarih farklılıkları listesine uygulandığında, bu bize henüz süresi dolmamış yorumların bir kısmını verir.


Sanırım yanlış 2999 veya 2099 ile 1999 yılları arasındaki yılları dönüştürüyorsunuz.
Ventero

@Ventero bu doğru. Ben biraz biz olduğunu düşündük sadece 2049 (ve onların 1 veya 2 haneli sürümleri), ama bu hiçbir söz yoktur meydan yeniden okuma - yıllar 1950 ile uğraşan.
Martin Ender

@Ventero sabit (ama zaten zaten beni önemli ölçüde yendin;))
Martin Ender

Mathematica'da bir hesabınız olduğunu ancak herhangi bir Soru veya Cevap göndermediğinizi gördüğüme şaşırdım . Seni engelleyen bir şey mi var?
Mr.Wizard

@ Mr.Wizard üzgünüm, size cevap vermeyi tamamen unuttum. Sorular: Şimdiye kadar sahip olduğum her problem, googling / diğer SE soruları ile çözülebilirdi. Cevaplar: Bilmiyorum ... Mathematica'yı verimli bir şekilde kullanmak söz konusu olduğunda kendimi o kadar yetkin görmüyorum sanırım ... Sadece burada ve oradaki hızlı snippet'lerde kullanıyorum (ve kod golf). Ayrıca, cevap verebileceklerimi görmek için aktif olarak yenilerini izlemek zorunda kalacağım soruları yanıtlayacağımı ve şu anda tüm SE zamanlarımın PPCG'ye tahsis edildiğini tahmin ediyorum. ;) Beni başka türlü ikna etmek istiyorsan, bunu sohbette yapmaktan çekinme! :)
Martin Ender

4

JavaScript (E6) 159 164 172

Düzen İpuçları ve tekrar düşünmeye zorladığım için nderscore'a teşekkürler. Parametreleri önlemek ve bazı karakterleri kesmek için yeniden düzenlenmiş D.

Düzenleme 2 Nderscore tarafından başka bir numara, 2 fonksiyon 1 ile birleştirildi. Ardından iki parantez virgülle ayrılmış ifadeleri bire dönüştürdü. 0'a yakın okunabilirlik. Sidenote: Yuvarlama değil, 2 karakter daha kazandırabilir (| 0).

F=(a,t)=>t?100*(3-((i=F([y,m,d]=a))<t)-((j=F([m,d,y]=a))<t)-((k=F([d,m]=a))<t))/(3-!i-!j-!k)|0:(q=new Date(y<50?y+2e3:y,--m,d)).getMonth()==m&q.getDate()==d&&q

FireFox konsolunda test edin

;[[14,12,14],[8,2,2006],[6,7,5],[6,5,7],[12,31,99]]
.map(x=>x + ' ' + F(x, new Date(2006,6,5)))

Çıktı:

["14,12,14 100", "8,2,2006 50", "6,7,5 33", "6,5,7 66", "12,31,99 0"]

Ungolfed

NB D işlevi, verilen yıl, ay, gün ile bir Tarih oluşturmaya çalışır, ancak oluşturulan tarih amaçlanan değilse, yanlış döndürür (! = Gün veya ay)

F=(d,t)=>
(
  D=(y,m,d)=>(
    q=new Date(y<50?y+2000:y, --m, d), // decr m as javascript (like java) counts months starting at 0
    q.getMonth() == m & q.getDate() == d && q
  ),
  [a,b,c] = d, 
  x=D(...d), // three ways of express the date ...
  y=D(c,a,b),
  z=D(c,b,a),
  100 * (3-(x<t)-(y<t)-(z<t)) / (3-!x-!y-!z) | 0  
)   

@nderscore, D için değişiklikler için diğeri sintaks hatası için tamam. Ama yine de daha fazla tasarruf
edc65

Tuhaf. Yoruma yapıştırdığımda bir şeyler olmuş olmalı. En son optimizasyonlarınız, ilgisiz olmasına rağmen :)
nderscore

1
Artık SE'nin yorumlarına güvenmediğim için bunu bir macun içine koymak: (-3) pastie.org/private/6bemdweyndcaiseay70kia
nderscore

4

LINQPad'deki C # - 446 408 272 Bayt

Üçüncü Düzenleme: Le Canard, DateTime.Today öğesinin DateTime.Now değil doğru olduğunu belirttiği için teşekkürler. İkinci Düzenleme: Bu akıllı çözüm için teşekkürler VisualMelon!

void g(int[]d){var p=".";int a=d[2],b=d[1],e=d[0],y=a+(a<100?a>49?1900:2000:0),q=0,s=0;DateTime c;Action<string>z=x=>{if(DateTime.TryParse(x,out c)){s++;if(c>=DateTime.Today)q+=100;}};z(e+p+b+p+y);z(b+p+e+p+y);z(a+p+b+p+(e<100?‌​e>49?1900+e:2000+e:e));(q/(s>0?s:1)).Dump();}

Düzenleme: Kodu kısaltmama yardım ettiğin için podiluska ve edc65'e teşekkürler! Yıl girişi 4 byte uzunluğunda olsaydı çözümümün doğru olmadığını da fark ettim, bu yüzden bu problemi çözdüm. Bu çözüm için puan 408 Bytes.

Önceki cevaplardan hiçbirini geçmeme rağmen, yine de C # çözümümü paylaşmak istedim. Herhangi bir yardım / öneri takdir edilmektedir! ;)

void g(int[]d){var q=new List<DateTime>();var p=".";int s=0,a=d[2],b=d[1],e=d[0],y=0;var c=new DateTime();y=(a<100)?(a>49)?1900+a:2000+a:a;if(DateTime.TryParse(e+p+b+p+y,out c)){q.Add(c);s++;}if(DateTime.TryParse(b+p+e+p+y,out c)){q.Add(c);s++;}y=(e<100)?(e>49)?1900+e:2000+e:e;if(DateTime.TryParse(a+p+b+p+y,out c)){q.Add(c);s++;}q=q.Where(i=>i>=DateTime.Now).ToList();if(s==0){s=1;}(q.Count*100/s).Dump();}

Biçimlendirilmiş ve ungolfed versiyonu:

void g(int[] d)
    {
        var q = new List<DateTime>();
        var p = ".";
        int s = 0, a = d[2],b = d[1],e = d[0], y=0;
        var c = new DateTime();
        y = (a < 100) ?((a > 49) ? 1900 + a : 2000 + a) : a;

        if (DateTime.TryParse(e + p + b + p + y, out c))
        {
            q.Add(c);
            s++;
        }
        if (DateTime.TryParse(b + p + e + p + y, out c))
        {
            q.Add(c);
            s++;
        }
        y = (e < 100) ? ((e > 49) ? 1900 + e : 2000 + e) : e;

        if (DateTime.TryParse(a + p + b + p + y, out c))
        {
            q.Add(c);
            s++;
        }
        q = q.Where(i => i >= DateTime.Now).ToList();
        if (s == 0)
        {
            s = 1;
        }
        (q.Count*100/s).Dump();
    }

"DateTime.TryParse" -Part ürününün bu çözümde olduğu gibi tekrarlanmadığı ancak 21 bayt daha uzun olduğu bir çözüm yapmaya çalıştım.

"DateTime.TryParse" yinelenmeden çözüm: 467 Bayt

void g(int[]d){var q=new List<DateTime>();int s=0;int a=d[2];int b=d[1];int e=d[0];int y=0;if(a<100){if(a>49){y=1900+a;}else{y=2000+a;}}if(z(e,b,y,q)){s++;}if(z(b,e,y,q)){s++;}if(e<100){if(e>49){y=1900+e;}else{y=2000+e;}}if(z(a,b,y,q)){s++;}q=q.Where(i=>i>=DateTime.Now).ToList();if(s==0){s=1;}(q.Count*100/s).Dump();}bool z(int a,int b,int d,List<DateTime> q){var c=new DateTime();var p=".";if(DateTime.TryParse(a+p+b+p+d,out c)){q.Add(c);return true;}return false;}

Ungolfed versiyonu:

private void g(int[] d)
    {
        var q = new List<DateTime>();
        int s = 0;
        int a = d[2];
        int b = d[1];
        int e = d[0];
        int y = 0;
        if (a < 100)
        {
            if (a > 49)
            {
                y = 1900 + a;
            }
            else
            {
                y = 2000 + a;
            }
        }
        if (z(e, b, y, q))
        {
            s++;
        }
        if (z(b, e, y, q))
        {
            s++;
        }
        if (e < 100)
        {
            if (e > 49)
            {
                y = 1900 + e;
            }
            else
            {
                y = 2000 + e;
            }
        }
        if (z(a, b, y, q))
        {
            s++;
        }
        q = q.Where(i => i >= DateTime.Now).ToList();
        if (s == 0)
        {
            s = 1;
        }
        (q.Count*100/s).Dump();
    }

    private bool z(int a, int b, int d, List<DateTime> q)
    {
        var c = new DateTime();
        string p = ".";
        if (DateTime.TryParse(a + p + b + p + d, out c))
        {
            q.Add(c);
            return true;
        }
        return false;
    }

2
int s=0;int a=d[2];int b=d[1];int e=d[0];->int s=0,a=d[2],b=d[1],e=d[0];
podiluska

2
öneri: kullanın ternary (? :) eğer mümkünse eğer / else
edc65

1
@ThomasW. Y'nin 2 farklı değeri olduğunu sanmıyorum, bir keresinde a, diğeri de e'ye bağlı. Yine de teşekkürler!
tsavinho

1
DateTime.TryParseÇağrıları kaldırmak ilk içgüdümdü, yerine q değerini de veren bir lambda kullandı. Ayrıca diğer bazı adımları gerçekleştirdikten ( pastebin ) 328chars almak için:void g(int[]d){var q=new List<DateTime>();var p=".";int a=d[2],b=d[1],e=d[0],y;DateTime c;y=(a<100)?(a>49)?1900+a:2000+a:a;Action<string>z=(x)=>{if(DateTime.TryParse(x,out c))q.Add(c);};z(e+p+b+p+y);z(b+p+e+p+y);y=(e<100)?(e>49)?1900+e:2000+e:e;z(a+p+b+p+y);(q.Where(i=>i>=DateTime.Now).Count()*100/(q.Any()?q.Count:1)).Dump();}
VisualMelon

1
@VisualMelon Vay, kod golf oynamak gerçekten çok iyi! Hiç göremediğim Action<string>önce, bu yüzden sizden bir şey öğrenmek olabilir;) Ben değiştirerek 318 karakter halledilebilecek cevap almak başardı q.Where(i=>i>=DateTime.Now).Countile q.Count(i=>i>=DateTime.Now. Ayrıca köşeli parantezleri kaldırdım, xböylece 2 karakter daha kazanabilirim!
tsavinho

3

Haskell, 171 165 karakter

l=length
r y|y<100=(y+50)`mod`100+1950|y>0=y
q d m y z|d<32&&m<13&&d*m>0=(r y,m,d):z|1<3=z
v(a,b,c)=q c b a$q b a c$q a b c[]
t%d=(l$filter(>t)(v d))*100`div`l(v d)

İşlevin adı %. Test tarihi ile gerçek yıl için kanonik (y, m, d) sırada bir tuple olarak ve karton damga üç sayının bir tuple olarak çalıştırın:

λ: (2006,6,5)%(14,12,14)
100

λ: (2006,6,5)%(8,2,2006)
50

λ: (2006,6,5)%(6,7,5)
33

λ: (2006,6,5)%(6,5,7)
66

λ: (2006,6,5)%(12,31,99)
0

λ: (2006,6,5)%(0,1,7)
0

2

Erlang, 146

f([A,B,C]=U,N)->F=[T||T<-[{(Y+50)rem 100+1950,M,D}||[Y,M,D]<-[U,[C,A,B],[C,B,A]]],calendar:valid_date(T)],100*length([1||T<-F,T>=N])div length(F).

Test fonksiyonu şöyle olacaktır:

t() ->
    0 = f([12,31,99],{2006,6,5}),
    66 = f([6,5,7],{2006,6,5}),
    33 = f([6,7,5],{2006,6,5}),
    100 = f([14,12,14],{2006,6,5}),
    50 = f([8,2,2006],{2006,6,5}),
    100 = f([29,2,2],{2006,6,5}).

Ungolfed

f([A,B,C]=U,Today)->
    Perms = [U,[C,A,B],[C,B,A]],
    WithYears = [{(Y+50) rem 100+1950,M,D} || [Y,M,D] <- Perms],
    ValidDates = [T || T <- WithYears, calendar:valid_date(T)],
    100*length([1 || T <- ValidDates, T >= Today]) div length(ValidDates).

Bu çözüm liste anlamalarına dayanır. Bu yılki modulo numarasını Haskell çözümünden ödünç alıyor. Ayrıca, calendar:valid_date/1belirli bir aydaki gün sayısı nedeniyle imkansız tarihleri ​​yönetmek için de kullanılır (örneğin, "29-2-2" yalnızca YMD biçiminde olabilir). Ayrıca, Bugün date()Erlang'ın biçiminde (bir YMD tuple).


2

APL (85)

Bu, Dyalog APL 14'ün bazı yeni işlevlerini kullanır ancak harici kütüphaneleri kullanmaz. Bir değişiklik için TryAPL'de çalışır .

{100×(+/÷⍴)⍺≤{(3/100)⊥⍵+(99≥⊃⍵)×3↑1900+100×50>⊃⍵}¨Z/⍨{∧/12 31≥1↓⍵}¨Z←(⊂⌽⍵),(⊂2⌽⍵),⊂⍵}

Bu, 3-element dizisini sağ taraf ( ) argümanı ve tarihin sol taraf ( ) argümanı olarak kontrol etmek için YYYYMMDDformat tamsayı olarak alan bir fonksiyondur . Yani tarih 2014-07-09sayı olarak gösterilir 20140709.

Ölçek:

      20060705 {100×(+/÷⍴)⍺≤{(3/100)⊥⍵+(99≥⊃⍵)×3↑1900+100×50>⊃⍵}¨Z/⍨{∧/12 31≥1↓⍵}¨Z←(⊂⌽⍵),(⊂2⌽⍵),⊂⍵} 14 12 14
100
      20060705 {100×(+/÷⍴)⍺≤{(3/100)⊥⍵+(99≥⊃⍵)×3↑1900+100×50>⊃⍵}¨Z/⍨{∧/12 31≥1↓⍵}¨Z←(⊂⌽⍵),(⊂2⌽⍵),⊂⍵} 8 2 2006
50
      20060705 {100×(+/÷⍴)⍺≤{(3/100)⊥⍵+(99≥⊃⍵)×3↑1900+100×50>⊃⍵}¨Z/⍨{∧/12 31≥1↓⍵}¨Z←(⊂⌽⍵),(⊂2⌽⍵),⊂⍵} 6 7 5
33.3333
      20060705 {100×(+/÷⍴)⍺≤{(3/100)⊥⍵+(99≥⊃⍵)×3↑1900+100×50>⊃⍵}¨Z/⍨{∧/12 31≥1↓⍵}¨Z←(⊂⌽⍵),(⊂2⌽⍵),⊂⍵} 12 31 99
0

Açıklama:

  • Z←(⊂⌽⍵),(⊂2⌽⍵),⊂⍵: verilen tarihi çevirerek (⊂⌽⍵), sola 2 döndürerek (⊂2⌽⍵)veya hiçbir şey yapmadan YMD formatına getirin ⊂⍵. Bunlardan en az biri şimdi tarih belirsiz ise, YMD formatında uygun bir tarih, belki birden fazladır.
  • {∧/12 31≥1↓⍵}¨Z: Her tarihin geçerli olup olmadığını test edin: yıl (ilk öğe) bırakılır ve ardından ay 12'den büyük olmamalıdır ve gün 31'den yüksek olmamalıdır.
  • Z/⍨: geçerli tarihleri ​​filtrele Z.
  • {... : her geçerli tarih için:
    • ⍵+(99≥⊃⍵)×3↑1900+100×50>⊃⍵: yıl 99’dan yüksek değilse, 1900’ü, ardından 50’den düşükse 100’ü ekleyin.
    • (3/100)⊥: bir baz-100 sayılar kümesiymiş gibi çözer. (Yıl 100'den yüksektir, ancak ilk öğe olduğu için farketmez.) Bu, her geçerli tarih için sol argümanla aynı formatta bir sayı verir.
  • ⍺≤: Her tarih için, küçük olup olmadığına bakın . Bu, 1 OKve 0 anlamına gelen bir ikili vektör verecektir spoiled.
  • 100×(+/÷⍴): İkili vektörün toplamını uzunluğuna bölün ve 100 ile çarpın.

{100×(+/÷⍴)⍺≤((3/100)⊥⊢+(99≥⊃)×3↑1900+100×50>⊃)¨Z/⍨{∧/12 31≥1↓⍵}¨Z←(⌽⍵)(2⌽⍵)⍵}
Stranding

0

Java: 349 Karakter (3 boşluksuz)

int e(int[]n,Date t){int a=n[0],b=n[1],c=n[2];Date[]d=new Date[3];if(b<13&&c<32)d[0]=new Date((a<50?100:(a>100?-1900:0))+a,b-1,c);if(b<13&&a<32)d[1]=new Date((c<50?100:(c>100?-1900:0))+c,b-1,a);if(a<13&&b<32)d[2]=new Date((c<50?100:(c>100?-1900:0))+c,a-1,b);int v=0,g=0;for(int i=0;i<3;i++)if(d[i]!=null){if(!d[i].before(t))g++;v++;}return 100*g/v;}

Burada, yöntemin (biraz) aşınmış bir versiyonunu içeren, test etmek için kullanılabilecek bir sınıf var:

import java.util.*;
class i{

   int e(int[]n,Date t){
      int a=n[0],b=n[1],c=n[2];
      Date[]d=new Date[3];
      if(b<13&&c<32)d[0]=new Date((a<50?100:(a>100?-1900:0))+a,b-1,c);
      if(b<13&&a<32)d[1]=new Date((c<50?100:(c>100?-1900:0))+c,b-1,a);
      if(a<13&&b<32)d[2]=new Date((c<50?100:(c>100?-1900:0))+c,a-1,b);
      int v=0,g=0;
      for(int i=0;i<3;i++)
         if(d[i]!=null){
            if(!d[i].before(t))
               g++;
            v++;
         }
      return 100*g/v;}

   public static void main(String[] args){
      int[]i=new int[3];
      for(int k=0;k<3;k++)
         i[k] = Integer.parseInt(args[k]);
      int j = new i().e(i,new Date());
      System.out.println(j+"%");
   }   
}

Bu benim ilk kod golf turum ve sanırım neden genellikle çok fazla Java golfçüsü görmediğimi anladım.


1
Bir int[]argüman olarak kabul etmelisin , üç intsaniye değil .
Joey,

tamam, tamir ettim.
shieldgenerator7

0

C # 287 bayt

namespace System{class E{static float a,o,l;void M(int[]i){int d=i[0],m=i[1],y=i[2],t;if(l<3)try{if(l==1){t=y;y=d;d=t;}if(l++==0){t=d;d=m;m=t;}if(y<100&&(y+=1900)<1950)y+=100;o+=new DateTime(y,m,d)>=DateTime.Today?1:0;a++;if(l<3)i[9]=9;}catch{M(i);throw;}Console.Write(o/a);}}}

İlk defa golf oynayıp tavsiyelere bakalım. Özellikle, ad alanı nedeniyle baytları kaldırma.

Gerçek bir program değil, sadece bir fonksiyonun gerekli olduğu gerçeğini kötüye kullanmak. Ayrıca, işlev her zaman yakalanmamış bir istisna ile sonuçlanır.

Ungolfed

namespace System {
    class E {
        static float a, o, l;
        void M(int[] i) {
            int d = i[0], m = i[1], y = i[2], t;
            if (l < 3)
                try {
                    if (l == 1) { 
                        t = y; y = d; d = t; 
                    } 
                    if (l++ == 0) { 
                        t = d; d = m; m = t; 
                    } 
                    if (y < 100 && (y += 1900) < 1950)
                        y += 100; 
                    o += new DateTime(y, m, d) >= DateTime.Today ? 1 : 0; // # not expired
                    a++; // # valid dates
                    if (l < 3)
                        i[9] = 9; // throw new Exception()
                } 
                catch { 
                    M(i);
                    throw; // fail after the first Console.Write()
                } 
            Console.Write(o / a); 
        } 
    } 
}

0

Mathematica , 118

M.buettner'ın kodunu başlangıç ​​noktası olarak kullanarak birkaç geliştirmem var:

⌊100Mean@UnitStep@Cases[DateDifference@{If[#<100,Mod[#+50,100]+1950,#],##2}&@@@{#,RotateRight@#,Reverse@#},_Integer]⌋&

Golf argüman olarak üç-Int listesini alan bir fonksiyon olabilir.
algorithmshark

@algorithmshark Teşekkürler. Bunu nasıl özlediğimi bilmiyorum. Güncelleniyor ...
Mr.Wizard
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.