Apakah ASI saya sudah kadaluwarsa?


98

Aww, teman, tanggal kadaluwarsa ini tidak menulis bulan dengan surat! Saya tidak tahu apakah akan kedaluwarsa pada tanggal 10 Maret atau 3 Oktober ... Tunggu, tidak, tidak apa-apa, tahun ini mengatakan tahun 2012. (lorong oop bata keju yang sudah setengah digunakan ke tempat sampah seperti pro)

Jadi anggaplah sejenak bahwa Anda terlalu sibuk untuk mencoba mencari tahu kapan toples marinara ini seharusnya berakhir. Anda hanya ingin versi Cliff Notes: seberapa besar kemungkinan bahwa itu sudah lewat jatuh tempo? Mari kita menulis beberapa kode!

Anda tahu bahwa pabrikan mencetak tanggal sebagai tiga kali lipat bilangan bulat, dalam salah satu dari tiga format:

YEAR  MONTH DAY
MONTH DAY   YEAR
DAY   MONTH YEAR

Dan Anda tahu bahwa beberapa tanggal hanya dapat diartikan dalam satu atau dua cara, bukan ketiganya: tanggal 55 55-11-5harus satu tahun, artinya kotak Twinkies khusus ini kedaluwarsa 5 November 1955. Tahun ini kadang-kadang diberikan dalam empat digit dan bukan dua, yang dapat mengesampingkan beberapa opsi. Namun ketika dua digit, 50..99 berarti 1950..1999 dan 0..49 berarti 2000..2049.

Tugas Anda adalah menulis program atau fungsi yang mengambil array bilangan bulat yang merupakan tanggal yang valid dalam setidaknya satu dari interpretasi di atas, dan menghasilkan persen kemungkinan itu masih bagus. Persentase peluang hanyalah persentase interpretasi yang valid dari tanggal yang ada pada atau lebih lambat dari tanggal hari ini.

Array bilangan bulat akan menjadi [Int]jenis bahasa Anda yang panjangnya tiga jika itu adalah argumen untuk suatu fungsi, dan diberikan sebagai bilangan bulat dash, slash-, atau spasi (Anda bisa memilih) jika digunakan sebagai input pada STDIN ke sebuah program lengkap. *

"Tanggal hari ini" dapat menjadi tanggal aktual hari ini, seperti yang diperoleh melalui fungsi tanggal, atau tanggal yang diberikan dalam argumen tambahan untuk fungsi atau paramater tambahan di STDIN. Mungkin dalam detik Unix, triple tahun tahun bulan dimasukkan dalam salah satu dari tiga cara di atas, atau cara lain yang lebih nyaman.

Mari kita punya beberapa contoh! Input tanggal kedaluwarsa akan berada dalam gaya yang dipisahkan dengan tanda hubung, dan menganggap untuk contoh di bawah ini bahwa tanggal hari ini adalah 5 Juli 2006.

  • 14-12-14- Kedua interpretasi yang valid untuk ini (DMY dan YMD) adalah setara, 14 Desember 2014. Outputnya adalah 100 karena produk ini pasti masih bagus.
  • 8-2-2006- Angka terakhir adalah satu tahun, pasti, karena memiliki empat digit. Ini bisa berupa 8 Februari (kedaluwarsa) atau 2 Agustus (masih bagus). Outputnya adalah 50 .
  • 6-7-5- Ini bisa apa saja! Penafsiran "5 Juli 2006" masih bagus (hanya untuk satu hari), tetapi dua yang tersisa keduanya pada tahun 2005 dan harus dilemparkan secepat mungkin. Outputnya adalah 33 .
  • 6-5-7- Di sini, dua dari tiga interpretasi aman. Anda dapat membulatkan desimal Anda ke atas atau ke bawah, sehingga 66 atau 67 keduanya baik-baik saja.
  • 12-31-99- Oke, yang ini jelas dari pergantian abad (tahun 50-99 adalah 19XX, dan 31 tidak mungkin sebulan). Lemak besar 0 , dan Anda benar-benar harus membersihkan lemari es Anda lebih sering.

Anda dapat dengan aman berasumsi bahwa input apa pun yang tidak memenuhi standar di atas tidak diketahui oleh aturan output di atas.

Tidak ada permintaan web atau celah standar. Pustaka penanganan tanggal diizinkan. Ini kode golf: semoga program terpendek menang.

* Jika Anda menggunakan brainfuck atau bahasa dengan cacat data sejenis, Anda dapat mengasumsikan nilai ASCII dari tiga karakter pertama yang dimasukkan adalah bilangan bulat untuk tanggal tersebut. Ini tidak termasuk logika empat digit tahun, tentu, tapi saya pikir kita akan terlalu kaget dengan melihat solusi untuk ini di Brainfuck untuk membuat Anda sedikit kecewa.


39
Umm ... tahun ini adalah tahun 2014, bukan tahun 2006. Susu Anda delapan tahun terakhir masa kadaluwarsanya.
John Dvorak

11
@JanDvorak Saya hanya tidak ingin berusaha sangat keras untuk membangun contoh yang berarti, jadi saya mengubah tanggal hari ini untuk membuatnya lebih mudah.
algorithmshark

7
@ Dgrin91 tidak peduli, saya masih akan memakannya: D
aditsu

6
Di Australia, susu kadaluwarsa sekitar satu minggu sebelum penggunaan berdasarkan tanggal
gnibbler

5
Anda harus menambahkan tes dengan 00 di dalamnya, karena itu bukan hari atau bulan hukum.
MtnViewMark

Jawaban:


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}

Memanggil dengan xdari .z.D(a builtin) untuk dibandingkan dengan hari ini, atau tanggal literal pilihan Anda sebaliknya:

  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

Ini pada dasarnya adalah port dari solusi Python @ Alex-l, dengan beberapa trik golf ditambahkan:

  • Instruksi penataan ulang dikodekan dalam string untuk menyimpan beberapa karakter.
  • Logika kondisional (ab) menggunakan kebenaran-sebagai-integer (tetapi dengan cara yang berbeda dari solusi Python).
  • Uji validitas sedikit berbeda - k4 / q akan dengan senang hati mengurai string apa pun ke dalam tipe data apa pun; itu hanya mengembalikan nol jika itu tidak masuk akal. Jadi, saya mengembalikan daftar tanggal dari fungsi bagian dalam, yang mungkin atau mungkin tidak nol.
  • Hasil akhir datang dari memeriksa berapa banyak interpretasi tanggal yang mungkin adalah nol vs berapa banyak yang kurang dari tanggal perbandingan; penting di sini bahwa tanggal nol dianggap kurang dari tanggal lainnya.

1
Anda dapat menyimpan char dengan menghapus 0 terakhir dari "012201210", karena #mengambil itemnya secara siklis. Bahkan, Anda dapat menyimpan char kedua cara ini dengan menukar dua kasus terakhir: 3 3#.:'"0122102".
algorithmshark

Mencukur satu char lagi dengan membalikkan arg fungsi internal, menyimpan parens (tetapi menambahkan reverse). Adakah yang bisa membantu saya menyimpan dua karakter lagi? APL memukuli saya!
Aaron Davies

Mencukur lima lainnya dengan menulis ulang matematika di akhir. Kembali memimpin!
Aaron Davies

Dan jika saya membungkuk untuk menulis serius kode non-fungsional, saya bisa mencukur byte lain dengan mencemari namespace global: {c*(+/~d<x)%3-+/^d:{"D"$"."/:$|z,y,x+(c*19+x<50)*x<c::100}.'y@/:3 3#.:'$21020101}.
Aaron Davies

14

Ruby, 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}

Ini mendefinisikan fungsi fyang mengambil dua argumen: array yang berisi input, dan tanggal "hari ini".

Contoh:

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

Saya menggunakan modul datetime untuk validitas dan perbandingan tanggal. Jika datetidak dapat membuat datetime yang valid dari input, itu memunculkan ValueError. Cara ini sadalah jumlah dari tanggal yang tidak kedaluwarsa dan tmerupakan jumlah total dari tanggal yang valid. Saya mengambil keuntungan dari fakta bahwa True == 1untuk keperluan penambahan dan pengindeksan dengan Python. Saya juga menyimpan karakter dengan menggunakan 25 * (76,80), bukannya (1900.2000).

Perhatikan baris di lekukan kedua menggunakan karakter tab, bukan 2 spasi.

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

Tambahkan ini ke akhir untuk menguji:

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)
  • Input sebagai int[]via parameter, mis

    PS> ./milk.ps1 5,6,7
    
  • Pesan kesalahan dibungkam melalui try/ catch, selama saya tidak tahu apakah output pada stderr diizinkan atau tidak.
  • Menggunakan +"-1"pada tanggal, yang ditafsirkan sebagai .AddDays(-1)menggeser tanggal saat ini dengan satu hari, sehingga kita dapat membandingkannya dengan kemarin (bukan hanya hari ini). Ini menyelesaikan masalah bahwa kita mendapatkan tanggal dengan 0:00 sebagai waktu tetapi perlu membandingkan dengan tanggal dengan waktu mulai hari ini.
  • Sangat berat sekarang
  • Menggunakan trik baru untuk membungkam kesalahan yang sedikit lebih pendek

6

R, 269

Saya mengharapkan ini mudah di R, tetapi tahun-tahun satu digit adalah bola lengkung yang cukup besar. Saya merasa ini bisa jauh lebih baik dari itu.

lubridateadalah paket dari CRAN, Anda mungkin perlu menginstalnya 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)}

Penggunaan: di f(c(d1,d2,d3))mana c(d1,d2,d3)adalah vektor bilangan bulat.

misalnya f(c(6,10,14))pengembalian 0.3333333.

The lubridatepaket memiliki serangkaian fungsi wrapper untuk parsing tanggal dalam urutan yang berbeda. Saya menggunakan ini untuk melihat format mana yang menghasilkan tanggal yang valid, membuang yang tidak valid, dan kemudian melihat mana yang belum terjadi.


6

Mathematica, 163 153 164 byte

( sunting: tanggal tetap di luar rentang 1950 - 2049)

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

Ini mendefinisikan fungsi yang bisa Anda panggil

f[{6,7,5}]

Saat ini, persentase tidak bulat (menunggu OP untuk mengklarifikasi).

Berikut adalah penjelasan sedikit panjang yang harus dimengerti tanpa pengetahuan Mathematica (catatan yang &membuat segalanya yang tersisa dari itu fungsi anonim yang parameter yang disebut sebagai #, #2, #3...):

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

Ini mendefinisikan fungsi, yang mengubah 3 parameter a,b,cmenjadi 3 daftar {{a,b,c},{c,b,a},{c,a,b}. Perhatikan bahwa ##ini hanyalah urutan dari semua parameter.

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

Diterapkan pada tanggal kedaluwarsa, ini memberikan daftar {y,m,d}untuk masing-masing dari tiga kemungkinan permutasi.

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

Ini adalah fungsi anonim yang mengambil tiga parameter a,b,cdan mengembalikan daftar ketiganya, di mana yang pertama telah dikonversi menjadi tahun sesuai aturan yang diberikan: angka di antara 50dan 99(modulo 100) diubah menjadi tahun abad ke-20, angka di antara 0dan 49( modulo 100) berubah menjadi tahun abad ke-21, semua yang lain dibiarkan begitu saja. Di sini, ##2adalah urutan parameter dimulai dengan yang kedua, yaitu b,c.

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

Diterapkan pada masing-masing dari tiga hasil sebelumnya, ini hanya mengkanonis format tahun. Sebut ini canonicalDatesuntuk mempersingkat ekspresi berikut:

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

Ini memfilter interpretasi yang tidak valid. DateList@dmembuat {y,m,d,h,m,s}representasi penuh dari berbagai format tanggal. Ini akan menginterpretasikan daftar dalam urutan yang sama, tetapi tangkapannya adalah bahwa Anda dapat meneruskannya hal-hal seperti {8,2,2006}dalam hal mana ia akan menghitung 8 years + 2 months + 2006 days. Jadi kami memeriksa bahwa tiga elemen pertama dari daftar yang dikembalikan identik dengan input (yang hanya dapat terjadi jika bulan dan hari dalam rentang yang sesuai).

Untuk mempersingkat baris berikut, saya akan merujuk pada hasil dari ekspresi itu validDatesmulai sekarang:

DateDifference[#,Date[]]&

Fungsi anonim lain yang mengambil tanggal dan mengembalikan perbedaan dalam hari ke hari ini (diperoleh dari Date[]).

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

Petakan itu ke interpretasi tanggal yang valid.

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

Namun fungsi anonim lain yang, diberikan daftar ( #), mengembalikan persentase angka non-positif dalam daftar itu. Ini .bukan perkalian tetapi hanya angka desimal, untuk menghindari bilangan rasional sebagai hasilnya (Anda akan mendapatkan hal-hal seperti 100/3bukannya 33.333- Saya tidak benar-benar tahu apakah itu masalah).

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

Diterapkan pada daftar perbedaan tanggal, ini memberi kita sebagian kecil interpretasi yang belum kedaluwarsa.


Saya pikir Anda salah mengonversi tahun seperti 2999 atau 2099 hingga 1999.
Ventero

@Ventero itu benar. Saya agak berasumsi bahwa kami hanya berurusan dengan tahun 1950 - 2049 (dan versi 1 atau 2 digit mereka), tetapi membaca ulang tantangannya tidak disebutkan.
Martin Ender

@Ventero memperbaiki (tetapi Anda sudah mengalahkan saya secara signifikan;))
Martin Ender

Saya terkejut melihat bahwa Anda memiliki akun di Mathematica tetapi belum mengirim Pertanyaan atau Jawaban. Apakah ada sesuatu yang menahan Anda?
Mr.Wizard

@ Mr.Wizard maaf, benar-benar lupa merespons Anda. Pertanyaan: sejauh ini setiap masalah yang saya miliki dapat diselesaikan dengan googling / pertanyaan SE lainnya. Jawaban: Saya tidak tahu ... Saya kira saya tidak melihat diri saya sebagai yang mahir ketika datang untuk menggunakan Mathematica produktif ... saya hanya menggunakannya untuk potongan cepat di sini dan di sana (dan kode golf). Juga, saya kira untuk menjawab pertanyaan saya harus secara aktif menonton yang baru untuk melihat apa yang bisa saya jawab, dan saat ini semua waktu SE saya dialokasikan untuk PPCG. ;) Jika Anda ingin saya meyakinkan saya sebaliknya, jangan ragu untuk melakukannya dalam obrolan! :)
Martin Ender

4

JavaScript (E6) 159 164 172

Sunting Terima kasih kepada nderscore untuk petunjuk dan untuk mendorong saya untuk berpikir lagi. D diatur ulang menghindari parameter dan memotong beberapa karakter.

Sunting 2 Trik lain oleh nderscore, 2 fungsi digabung menjadi 1. Kemudian dua tanda kurung dihapus menggabungkan ekspresi yang dipisahkan koma menjadi satu. Keterbacaan dekat 0. Sidenote: Tidak membulatkan dapat menyimpan 2 karakter lain (| 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

Tes di konsol FireFox

;[[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)))

Keluaran:

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

Tidak disatukan

Fungsi NB D mencoba membuat Tanggal dengan tahun, bulan, hari tertentu tetapi menghasilkan false jika tanggal yang dibuat bukan yang diinginkan (! = Hari atau bulan)

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 OK untuk perubahan D, kesalahan sintax untuk yang lain. Tetapi tetap disimpan lebih banyak lagi
edc65

Aneh. Pasti ada sesuatu yang terjadi ketika saya menempelkannya di komentar. Optimalisasi terbaru Anda membuatnya tidak relevan :)
nderscore

1
Menempatkan ini di tempel, karena saya tidak percaya lagi komentar SE: (-3) pastie.org/private/6bemdweyndcaiseay70kia
nderscore

4

C # dalam LINQPad - 446 408 272 Bytes

Sunting Ketiga: Terima kasih kepada Le Canard karena telah menunjukkan bahwa DateTime. Hari ini benar, bukan DateTime. Sekarang. Sunting Kedua: Terima kasih VisualMelon untuk solusi pintar ini!

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

Sunting: Terima kasih kepada podiluska dan edc65 karena membantu saya mempersingkat kode! Saya juga memperhatikan bahwa solusi saya tidak benar jika input tahun panjangnya 4 byte, oleh karena itu saya menyertakan perbaikan untuk masalah itu. Skor untuk solusi ini adalah 408 Bytes.

Meskipun saya tidak mengalahkan jawaban sebelumnya, saya masih ingin membagikan solusi C # saya. Bantuan / saran sangat dihargai! ;)

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

Versi yang diformat dan tidak disunat:

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

Saya mencoba membuat solusi di mana "DateTime.TryParse" -Part tidak diulang seperti dalam solusi ini, tapi itu 21 byte lebih lama.

Solusi tanpa mengulangi "DateTime.TryParse": 467 Bytes

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

Versi tidak disatukan:

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
saran: gunakan ternary (? :) bila memungkinkan alih-alih jika / else
edc65

1
@ Thomas. Saya tidak berpikir karena y memiliki 2 nilai yang berbeda, satu kali tergantung pada, yang lain tergantung pada e. Bagaimanapun, terima kasih!
tsavinho

1
Menghapus DateTime.TryParsepanggilan adalah insting pertama saya, menggantinya dengan lambda yang juga mengembalikan nilai q. Juga dilakukan beberapa langkah lain ( pastebin ) untuk mendapatkan 328chars: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 Wow, Anda benar-benar hebat dalam golf kode! Aku tidak pernah melihat Action<string>sebelumnya, jadi saya bisa belajar sesuatu dari Anda;) saya bisa mendapatkan jawaban Anda ke 318 karakter dengan mengganti q.Where(i=>i>=DateTime.Now).Countdengan q.Count(i=>i>=DateTime.Now. Saya juga menghapus tanda kurung xsehingga saya dapat menyimpan 2 karakter lagi!
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)

Nama fungsinya adalah %. Jalankan dengan tanggal tes sebagai tupel dalam urutan kanonik (y, m, d) dengan tahun aktual, dan cap karton sebagai tupel dengan tiga angka:

λ: (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).

Fungsi tes adalah:

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}).

Tidak disatukan

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).

Solusi ini bergantung pada pemahaman daftar. Ia meminjam trik modulo untuk tahun ini dari solusi Haskell. Ini juga digunakan calendar:valid_date/1untuk menangani tanggal yang tidak mungkin karena jumlah hari dalam bulan tertentu (mis. "29-2-2" hanya bisa dalam format YMD). Hari ini juga dalam date()format Erlang (tuple YMD).


2

APL (85)

Ini menggunakan beberapa fungsi baru Dyalog APL 14, tetapi tidak ada perpustakaan eksternal. Untuk perubahan, ini berfungsi di TryAPL .

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

Ini adalah fungsi yang mengambil array 3-elemen sebagai argumen sisi kanan ( ), dan tanggal untuk memeriksa sebagai argumen sisi kiri ( ), sebagai bilangan bulat YYYYMMDDformat. Yaitu, tanggal 2014-07-09direpresentasikan sebagai angka 20140709.

Uji:

      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

Penjelasan:

  • Z←(⊂⌽⍵),(⊂2⌽⍵),⊂⍵: ubah tanggal yang diberikan ke dalam format YMD dengan membalik (⊂⌽⍵), memutarnya ke kiri sebanyak 2 (⊂2⌽⍵), atau hanya tidak melakukan apa-apa ⊂⍵. Setidaknya salah satu dari ini sekarang merupakan tanggal yang tepat dalam format YMD, mungkin lebih dari satu jika tanggalnya tidak jelas.
  • {∧/12 31≥1↓⍵}¨Z: tes jika setiap tanggal valid: tahun (elemen pertama) dijatuhkan, dan bulannya harus tidak lebih dari 12 dan hari harus tidak lebih tinggi dari 31.
  • Z/⍨: filter tanggal yang valid dari Z.
  • {... : untuk setiap tanggal yang valid:
    • ⍵+(99≥⊃⍵)×3↑1900+100×50>⊃⍵: jika tahun tidak lebih tinggi dari 99, tambahkan 1900, lalu 100 jika tahun lebih rendah dari 50.
    • (3/100)⊥: decode seolah-olah itu adalah seperangkat angka dasar-100. (Tahun lebih tinggi dari 100, tetapi ini tidak masalah karena ini adalah elemen pertama.) Ini memberikan angka untuk setiap tanggal yang valid dalam format yang sama dengan argumen kiri.
  • ⍺≤: untuk setiap tanggal, lihat apakah jumlahnya tidak lebih kecil dari . Ini akan memberikan vektor biner di mana 1 berarti OKdan 0 berarti spoiled.
  • 100×(+/÷⍴): bagi jumlah vektor biner dengan panjangnya dan kalikan dengan 100.

Hemat 7 byte (dan kalahkan K dengan margin yang bagus) dengan mengayunkan dan membuat fungsi dalam diam-diam:{100×(+/÷⍴)⍺≤((3/100)⊥⊢+(99≥⊃)×3↑1900+100×50>⊃)¨Z/⍨{∧/12 31≥1↓⍵}¨Z←(⌽⍵)(2⌽⍵)⍵}
Adám

0

Java: 349 Karakter (3 tanpa ruang)

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

Berikut ini adalah kelas yang berisi yang dapat digunakan untuk mengujinya, termasuk versi (sedikit) dari metode ini:

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

Ini adalah babak pertama saya golf kode, dan saya pikir saya tahu mengapa saya biasanya tidak melihat banyak pegolf Jawa.


1
Anda harus menerima int[]argumen sebagai, bukan tiga int.
Joey

ok, saya memperbaikinya.
shieldgenerator7

0

C # 287 byte

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

Pertama kali bermain golf, mencari saran. Khususnya, menghapus byte karena namespace.

Menyalahgunakan fakta bahwa hanya fungsi yang diperlukan, bukan program yang sebenarnya. Juga, fungsi selalu menghasilkan pengecualian tanpa tertangkap.

Tidak disatukan

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

Menggunakan kode m.buettner sebagai titik awal, saya memiliki beberapa peningkatan:

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

Golf mungkin merupakan fungsi yang mengambil daftar tiga-Int sebagai argumen.
algorithmshark

@algorithmshark Terima kasih. Saya tidak tahu bagaimana saya melewatkan itu. Memperbarui ...
Mr.Wizard
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.