นมของฉันหมดอายุหรือยัง?


98

อืมผู้ชายวันที่หมดอายุนี้ไม่ได้เขียนเดือนด้วยตัวอักษร! ฉันไม่สามารถบอกได้ว่ามันจะหมดอายุในวันที่ 10 มีนาคมหรือ 3 ตุลาคม ... รอไม่ไม่เป็นไรปีพูดว่า 2012 (ซอยอิฐ oops-of-oops อิฐของชีสลงในถังขยะอย่างมืออาชีพ)

งั้นลองสมมติว่าคุณยุ่งเกินกว่าจะลองหาเหตุผลว่า marinara ขวดนี้จะหมดอายุเมื่อไหร่ คุณแค่ต้องการรุ่น Cliff Notes: มีความเป็นไปได้ที่จะครบกำหนดแล้ว? ลองเขียนโค้ดกัน!

คุณรู้ว่าผู้ผลิตพิมพ์วันที่เป็นจำนวนเต็มสามเท่าของการสั่งซื้อในหนึ่งในสามรูปแบบ:

YEAR  MONTH DAY
MONTH DAY   YEAR
DAY   MONTH YEAR

และคุณรู้ว่าบางวันสามารถตีความได้เพียงหนึ่งหรือสองวิธีไม่ใช่ทั้งสาม: 55 ใน55-11-5นั้นจะต้องเป็นปีซึ่งหมายความว่ากล่องเฉพาะของ Twinkies นี้หมดอายุในวันที่ 5 พฤศจิกายน 1955 บางครั้งในปีนี้จะมีตัวเลขสี่หลักและ ไม่ใช่สองซึ่งสามารถออกกฎบางตัวเลือก เมื่อเป็นตัวเลขสองหลัก 50..99 หมายถึง 1950..1999 และ 0..49 หมายถึง 2,000..2049

งานของคุณคือการเขียนโปรแกรมหรือฟังก์ชั่นที่ใช้อาร์เรย์ของจำนวนเต็มซึ่งเป็นวันที่ที่ถูกต้องในการตีความอย่างน้อยหนึ่งรายการข้างต้นและให้โอกาสร้อยละที่มันยังดี โอกาสร้อยละเป็นเพียงเปอร์เซ็นต์ของการตีความที่ถูกต้องของวันที่ที่อยู่ในหรือหลังวันที่ของวันนี้

อาเรย์ของจำนวนเต็มจะเป็น[Int]ประเภทความยาวสามภาษาของคุณหากเป็นอาร์กิวเมนต์ของฟังก์ชันและกำหนดเป็นจำนวนเต็มขีดกลาง - ขีดกลางหรือคั่นด้วยช่องว่าง (คุณจะเลือก) ถ้าใช้เป็นอินพุตบน STDIN ไปยัง โปรแกรมเต็มรูปแบบ *

"วันที่วันนี้" อาจเป็นวันที่ที่แท้จริงของวันนี้ตามที่ได้รับผ่านฟังก์ชั่นวันที่หรือวันที่ที่กำหนดในอาร์กิวเมนต์พิเศษในการทำงานหรือพารามิเตอร์พิเศษใน STDIN มันอาจจะเป็นในยุค Unix วินาทีสามเดือนปีวันอื่นเข้ามาในหนึ่งในสามวิธีข้างต้นหรืออีกวิธีที่สะดวกมากขึ้น

มาดูตัวอย่างกัน! อินพุตวันที่หมดอายุจะอยู่ในรูปแบบที่คั่นด้วยเส้นประและถือว่าเป็นตัวอย่างด้านล่างว่าวันที่วันนี้คือ 5 กรกฎาคม 2549

  • 14-12-14- การตีความที่ถูกต้องทั้งสองนี้ (DMY และ YMD) เทียบเท่า 14 ธันวาคม 2014 ผลลัพธ์ที่ได้คือ100เพราะผลิตภัณฑ์นี้ยังดีอยู่
  • 8-2-2006- ตัวเลขสุดท้ายคือปีแน่นอนเพราะมันมีตัวเลขสี่หลัก อาจเป็นได้ทั้งวันที่ 8 กุมภาพันธ์ (หมดอายุ) หรือวันที่ 2 สิงหาคม (ยังดี) การส่งออกเป็น50
  • 6-7-5- นี่อาจเป็นอะไรก็ได้! การตีความ "5 กรกฎาคม 2549" ยังคงดี (สำหรับหนึ่งวันเท่านั้น) แต่การตีความที่เหลือทั้งสองในปี 2005 และควรถูกโยนโดยเร็วที่สุด การส่งออกเป็น33
  • 6-5-7- ที่นี่การตีความสองในสามนั้นปลอดภัย คุณสามารถปัดเศษทศนิยมขึ้นหรือลงดังนั้นทั้ง66หรือ67ก็โอเค
  • 12-31-99- โอเคสิ่งนี้ชัดเจนตั้งแต่ช่วงเปลี่ยนศตวรรษ (ปี 50 ถึง 99 คือ 19XX และ 31 อาจเป็นเดือนไม่ได้) ไขมันใหญ่0และคุณควรทำความสะอาดตู้เย็นของคุณบ่อยขึ้น

คุณสามารถสันนิษฐานได้อย่างปลอดภัยว่าอินพุตใด ๆ ที่ไม่ตรงตามมาตรฐานข้างต้นไม่ได้เป็นความลับของกฎเอาต์พุตด้านบน

ไม่มีการร้องขอจากเว็บหรือช่องโหว่มาตรฐาน อนุญาตให้ใช้การจัดการกับวันที่ นี่คือรหัสกอล์ฟ: โปรแกรมที่สั้นที่สุดอาจชนะ

* ถ้าคุณกำลังใช้ brainfuck หรือภาษาที่มีประเภทข้อมูลที่คล้ายคลึงกันคุณสามารถใช้ค่า ASCII ของอักขระสามตัวแรกในอินพุตเป็นจำนวนเต็มสำหรับวันที่ สิ่งนี้ไม่รวมตรรกะปีสี่หลักแน่นอน แต่ฉันคิดว่าเราจะประหลาดใจเกินไปโดยเห็นวิธีแก้ปัญหานี้ใน Brainfuck เพื่อทำให้คุณรู้สึกเล็กน้อย


39
อืมม ... ปีปัจจุบันคือปี 2014 ไม่ใช่ปี 2006 นมของคุณมีอายุ 8 ปีที่ผ่านมาซึ่งหมดอายุอย่างดีที่สุด
John Dvorak

11
@JanDvorak ฉันไม่ต้องการลองอย่างหนักเพื่อสร้างตัวอย่างที่มีความหมายดังนั้นฉันจึงปรับแต่งวันที่วันนี้เพื่อให้ง่ายขึ้น
algorithmshark

7
@ Dgrin91 ไม่สนใจฉันจะยังกินพวกเขา: D
aditsu

6
ในออสเตรเลียนมจะหมดอายุประมาณหนึ่งสัปดาห์ก่อนการใช้โดยวันที่
gnibbler

5
คุณควรเพิ่มการทดสอบที่มีการทดสอบ 00 เนื่องจากไม่สามารถเป็นวันหรือเดือนที่ถูกกฎหมาย
MtnViewMark

คำตอบ:


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}

วิงวอนกับxของ.z.D(ก builtin) เพื่อเปรียบเทียบกับวันนี้หรือวันที่แท้จริงของคุณเลือกอย่างอื่น

  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

นี่เป็นพอร์ตของโซลูชัน Python ของ @ Alex-l พร้อมด้วยเทคนิคการเล่นกอล์ฟเล็ก ๆ น้อย ๆ เพิ่มเติม:

  • คำแนะนำการจัดเรียงใหม่จะถูกเข้ารหัสในสตริงเพื่อบันทึกอักขระคู่
  • ตรรกะตามเงื่อนไข (ab) ใช้ความจริงตามจำนวนเต็ม (แต่แตกต่างจากวิธีการแก้ปัญหาของงูหลาม)
  • การทดสอบความถูกต้องจะแตกต่างกันเล็กน้อย - k4 / q จะแยกสตริงใด ๆ ลงในประเภทข้อมูลใด ๆ อย่างมีความสุข; มันจะคืนค่า null หากไม่สามารถเข้าใจได้ ดังนั้นฉันกลับรายการวันที่จากฟังก์ชั่นด้านในซึ่งอาจหรือไม่อาจเป็นโมฆะ
  • ผลลัพธ์สุดท้ายมาจากการตรวจสอบว่ามีการตีความวันที่ที่เป็นไปได้จำนวนเท่าใดกับจำนวนที่น้อยกว่าวันที่เปรียบเทียบ สิ่งสำคัญคือที่วันที่ว่างจะถือว่าน้อยกว่าวันที่อื่น

1
คุณสามารถบันทึกตัวถ่านได้โดยลบ 0 ตัวสุดท้ายออกจาก"012201210"เพราะ#เอาไอเทมของมันออกเป็นรอบ ๆ 3 3#.:'"0122102"ในความเป็นจริงคุณสามารถบันทึกถ่านสองวิธีนี้โดยการแลกเปลี่ยนสองกรณีล่าสุด:
algorithmshark

โกนอีกหนึ่งถ่านด้วยการย้อนกลับด้านในของ func ภายในประหยัด parens (แต่เพิ่มกลับ) ทุกคนสามารถช่วยฉันบันทึกสองตัวอักษรได้อีกหรือไม่ APL กำลังตีฉัน!
Aaron Davies

โกนอีกห้าคนโดยเขียนคณิตศาสตร์ใหม่ในตอนท้าย กลับมาเป็นผู้นำ!
Aaron Davies

และถ้าผมก้มลงไปเขียนอย่างจริงจังรหัสที่ไม่ใช่หน้าที่ผมสามารถโกนไบต์อื่นโดยไม่ก่อให้เกิดมลพิษ namespace {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 ตัวอักษร

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}

สิ่งนี้จะกำหนดฟังก์ชั่นfที่รับสองอาร์กิวเมนต์: อาร์เรย์ที่มีอินพุตและวันที่ "วันนี้"

ตัวอย่าง:

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 สำหรับความถูกต้องและการเปรียบเทียบวันที่ หากไม่สามารถทำให้วันที่และเวลาที่ถูกต้องออกจากการป้อนข้อมูลมันก็เกิดdate ValueErrorวิธีนี้sเป็นผลรวมของวันที่ที่ไม่หมดอายุและtเป็นจำนวนวันที่ที่ถูกต้องทั้งหมด ฉันใช้ประโยชน์จากข้อเท็จจริงที่ว่าTrue == 1เพื่อวัตถุประสงค์ในการเพิ่มและจัดทำดัชนีใน Python ฉันยังบันทึกอักขระโดยใช้ 25 * (76,80) แทน (1900,2000)

โปรดสังเกตว่าบรรทัดในการเยื้องระดับที่สองใช้อักขระแท็บไม่ใช่เว้นวรรค 2 ตัว

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

เพิ่มลงในส่วนท้ายเพื่อทดสอบ:

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[]ผ่านพารามิเตอร์เช่น

    PS> ./milk.ps1 5,6,7
    
  • ข้อความแสดงข้อผิดพลาดถูกปิดเสียงผ่านtry/ catchตราบใดที่ฉันไม่ทราบว่าอนุญาตให้ส่งออกบน stderr ได้หรือไม่
  • ใช้+"-1"ในวันที่ซึ่งถูกตีความว่า.AddDays(-1)เป็นการเลื่อนวันที่ปัจจุบันไปหนึ่งวันเพื่อให้เราสามารถเปรียบเทียบกับเมื่อวาน (แทนแค่วันนี้) วิธีนี้จะช่วยแก้ปัญหาที่เราได้รับวันที่ 0:00 เป็นเวลา แต่ต้องเปรียบเทียบกับวันที่มีเวลาตั้งแต่วันนี้
  • ตอนนี้ Inline อย่างมาก
  • การใช้เคล็ดลับใหม่สำหรับข้อผิดพลาดในการปิดเสียงซึ่งค่อนข้างสั้น

6

R, 269

ฉันคาดหวังว่าสิ่งนี้จะเป็นเรื่องง่ายใน R แต่ปีหลักเดียวนั้นเป็นลูกโค้งที่ค่อนข้างใหญ่ ฉันรู้สึกว่ามันน่าจะดีกว่านี้มาก

lubridateเป็นแพคเกจจาก CRAN 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)}

การใช้งาน: f(c(d1,d2,d3))where c(d1,d2,d3)เป็นเวกเตอร์ของจำนวนเต็ม

เช่น ผลตอบแทนf(c(6,10,14))0.3333333

lubridateแพคเกจมีชุดของฟังก์ชั่นเสื้อคลุมสำหรับวันแยกในการสั่งซื้อที่แตกต่างกัน ฉันใช้สิ่งเหล่านี้เพื่อดูว่ารูปแบบใดสร้างวันที่ที่ถูกต้องโยนรูปแบบที่ไม่ถูกต้องออกแล้วดูว่ารูปแบบใดยังไม่เกิดขึ้น


6

Mathematica, 163 153 164 ไบต์

( แก้ไข:วันที่คงที่นอกช่วงปี 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]]&

นี่เป็นการกำหนดฟังก์ชั่นที่คุณสามารถเรียกใช้ได้

f[{6,7,5}]

ขณะนี้เปอร์เซ็นต์ยังไม่ถูกปัดเศษ (รอให้ OP ทำการชี้แจง)

นี่คือคำอธิบายที่ยาวเล็กน้อยที่ควรจะเป็นที่เข้าใจโดยไม่มีความรู้ใด ๆ Mathematica (หมายเหตุที่&ทำให้ทุกอย่างด้านซ้ายของมันฟังก์ชั่นที่ไม่ระบุชื่อที่มีพารามิเตอร์จะเรียกว่า#, #2, #3... ):

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

นี้กำหนดฟังก์ชั่นซึ่งจะเปลี่ยน 3 พารามิเตอร์a,b,cเป็น 3 {{a,b,c},{c,b,a},{c,a,b}รายการ โปรดทราบว่า##เป็นเพียงลำดับของพารามิเตอร์ทั้งหมด

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

นำไปใช้กับวันหมดอายุซึ่งจะแสดงรายการ{y,m,d}ของการเปลี่ยนลำดับที่เป็นไปได้ทั้งสามรายการ

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

นี่เป็นฟังก์ชันที่ไม่ระบุตัวตนซึ่งใช้พารามิเตอร์สามตัวa,b,cและส่งกลับรายการของทั้งสามโดยที่ค่าแรกถูกแปลงเป็นปีตามกฎที่กำหนด: ตัวเลขระหว่าง50และ99(โมดูโล100) จะเปลี่ยนเป็นปีศตวรรษที่ 20 ตัวเลขระหว่าง0และ49( โมดูโล่100) เปลี่ยนเป็นศตวรรษที่ 21 ปีที่เหลืออยู่ทั้งหมด ที่นี่เป็นลำดับของพารามิเตอร์ที่เริ่มต้นด้วยหนึ่งที่สองคือ##2b,c

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

นำไปใช้กับผลลัพธ์ก่อนหน้านี้สามรายการนี้เป็นเพียงรูปแบบปีซึ่งเป็นที่ยอมรับ ลองเรียกสิ่งนี้canonicalDatesเพื่อทำให้นิพจน์ต่อไปนี้สั้นลง:

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

สิ่งนี้จะกรองการตีความที่ไม่ถูกต้องออกไป DateList@dทำให้การ{y,m,d,h,m,s}แสดงเต็มรูปแบบจากรูปแบบวันที่ต่างๆ มันจะตีความรายชื่อในลำดับเดียวกัน แต่จับคือการที่คุณสามารถผ่านสิ่งเช่นในกรณีที่มันจะคำนวณ{8,2,2006} 8 years + 2 months + 2006 daysดังนั้นเราจึงตรวจสอบว่าองค์ประกอบสามรายการแรกของรายการที่ส่งคืนนั้นเหมือนกันกับอินพุต (ซึ่งสามารถเกิดขึ้นได้หากเดือนและวันในช่วงที่เหมาะสม)

หากต้องการย่อบรรทัดต่อไปนี้ให้สั้นลงฉันจะอ้างถึงผลลัพธ์ของนิพจน์ดังกล่าวvalidDatesนับจากนี้เป็นต้นไป:

DateDifference[#,Date[]]&

อีกฟังก์ชั่นที่ไม่ระบุชื่อซึ่งใช้วันที่และส่งกลับความแตกต่างเป็นวันถึงวันนี้ (ที่ได้รับจากDate[])

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

แผนที่ที่ลงวันที่การตีความที่ถูกต้อง

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

อีกฟังก์ชั่นที่ไม่ระบุตัวตนซึ่งรับ list ( #) จะคืนค่าเปอร์เซ็นต์ของจำนวนที่ไม่เป็นบวกในรายการนั้น .ไม่ได้เป็น แต่เพียงการคูณหลักทศนิยมเพื่อหลีกเลี่ยงการสรุปตัวเลขเป็นผล (คุณจะได้รับสิ่งที่ต้องการ100/3แทน33.333- ผมไม่ทราบจริง ๆ ถ้าเป็นปัญหา)

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

นำไปใช้กับรายการความแตกต่างวันที่ซึ่งจะทำให้เรามีส่วนของการตีความที่ยังไม่หมดอายุ


ฉันคิดว่าคุณแปลงปีอย่างไม่ถูกต้องเช่น 2999 หรือ 2099 ถึง 1999
Ventero

@Ventero นั่นเป็นความจริง ฉันคิดว่าเราเพิ่งจะจัดการกับปี 1950 - 2049 (และรุ่น 1 หรือ 2 หลัก) ของพวกเขา แต่อ่านความท้าทายอีกครั้งโดยไม่พูดถึงเรื่องนั้น
Martin Ender

แก้ไข @Ventero แล้ว (แต่คุณเอาชนะฉันไปได้มากแล้ว))
Martin Ender

ฉันประหลาดใจที่เห็นว่าคุณมีบัญชีในMathematicaแต่ยังไม่ได้โพสต์คำถามหรือคำตอบ มีบางอย่างที่รั้งคุณหรือไม่?
Mr.Wizard

@ Mr.Wizard ขอโทษที่ลืมตอบคุณโดยสิ้นเชิง คำถาม: จนถึงทุกปัญหาที่ฉันสามารถแก้ไขได้ด้วย googling / คำถาม SE อื่น ๆ คำตอบ: ผมไม่ทราบว่า ... ผมคิดว่าผมไม่ดูตัวเองเป็นที่มีความเชี่ยวชาญเมื่อมันมาถึงการใช้ Mathematica งอกงาม ... ฉันจะใช้มันสำหรับตัวอย่างรวดเร็วที่นี่และมี (และกอล์ฟ code) นอกจากนี้ฉันเดาว่าจะตอบคำถามฉันต้องดูใหม่ ๆ อย่างกระตือรือร้นเพื่อดูว่าฉันสามารถตอบได้อย่างไรและเวลา SE ของฉันทั้งหมดจัดสรรสำหรับ PPCG ;) หากคุณต้องการให้ฉันโน้มน้าวใจฉันเป็นอย่างอื่นอย่าลังเลที่จะทำเช่นนั้นในการแชท! :)
Martin Ender

4

JavaScript (E6) 159 164 172

แก้ไขขอบคุณขีดล่างสำหรับคำแนะนำและผลักดันให้ฉันคิดอีกครั้ง จัดระเบียบใหม่ D เพื่อหลีกเลี่ยงพารามิเตอร์และการตัดตัวอักษรบางตัว

แก้ไข 2เคล็ดลับอื่นโดย nderscore มี 2 ฟังก์ชันที่รวมกันเป็น 1 จากนั้นวงเล็บสองตัวจะลบเครื่องหมายจุลภาคที่คั่นด้วยการรวมนิพจน์ออกเป็นหนึ่ง ความสามารถในการอ่านใกล้ 0 Sidenote: การปัดเศษไม่สามารถบันทึกได้อีก 2 ตัวอักษร (| 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

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

เอาท์พุท:

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

Ungolfed

ฟังก์ชัน NB D พยายามที่จะสร้างวันที่ที่ได้รับปีเดือนวัน แต่กลับเท็จถ้าวันที่สร้างไม่ใช่สิ่งที่ตั้งใจ (! = วันหรือเดือน)

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  
)   

@ ขีดสั้นตกลงสำหรับการเปลี่ยนแปลงใน D, ข้อผิดพลาด sintax สำหรับอื่น ๆ แต่ช่วยได้มากขึ้นอีกแล้ว
edc65

แปลก. มีบางอย่างเกิดขึ้นเมื่อฉันวางลงในความคิดเห็น การเพิ่มประสิทธิภาพล่าสุดของคุณทำให้ไม่เกี่ยวข้อง :) :)
ขีดล่าง

1
วางสิ่งนี้ในการวางเนื่องจากฉันไม่เชื่อถือความคิดเห็นของ SE อีกต่อไป: (-3) pastie.org/private/6bemdweyndcaiseay70kia
nderscore

4

C # ใน LINQPad - 446 408 272 ไบต์

การแก้ไขที่สาม:ต้องขอบคุณ Le Canard สำหรับการชี้ให้เห็นว่า DateTime วันนี้ถูกต้องไม่ใช่ DateTime.Now แก้ไขที่สอง:ขอบคุณ 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();}

แก้ไข:ขอบคุณ podiluska และ edc65 ที่ช่วยฉันย่อรหัส! ฉันยังสังเกตเห็นว่าวิธีแก้ไขของฉันไม่ถูกต้องหากอินพุตของปีมีความยาว 4 ไบต์ดังนั้นฉันจึงรวมการแก้ไขสำหรับปัญหานั้น คะแนนสำหรับโซลูชันนี้คือ408 Bytes

แม้ว่าฉันจะไม่ได้ตีคำตอบก่อนหน้านี้ แต่ฉันยังต้องการแบ่งปันโซลูชัน C # ของฉัน ความช่วยเหลือ / ข้อเสนอแนะจะได้รับการชื่นชม! ;)

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

เวอร์ชันที่จัดรูปแบบและไม่อัปโหลด:

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" - ส่วนไม่ซ้ำในโซลูชันนี้ แต่มีความยาว 21 ไบต์

โซลูชันโดยไม่ต้องทำซ้ำ "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;}

เวอร์ชันที่ไม่ถูกปรับแต่ง:

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
ข้อเสนอแนะ: ใช้ประกอบไปด้วย (? :) เมื่อเป็นไปได้แทน if / else
edc65

1
@ThomasW ฉันไม่คิดว่าเนื่องจาก y มีค่าแตกต่างกัน 2 ค่าหนึ่งครั้งขึ้นอยู่กับ a อีกครั้งที่ขึ้นอยู่กับ e ขอขอบคุณ!
tsavinho

1
การลบการDateTime.TryParseโทรออกคือสัญชาตญาณแรกของฉันแทนที่ด้วยแลมบ์ดาที่ใส่ค่ากลับเข้าไปในคิว ยังดำเนินการขั้นตอนอื่น ๆ ( pastebin ) เพื่อรับ 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 ว้าวคุณเก่งเรื่องการตีกอล์ฟมาก! ฉันไม่เคยเห็นAction<string>มาก่อนดังนั้นฉันได้เรียนรู้อะไรบางอย่างจากคุณ;) ผมสามารถที่จะได้รับการตอบของคุณลงไป 318 ตัวอักษรโดยการแทนที่ ด้วยq.Where(i=>i>=DateTime.Now).Count q.Count(i=>i>=DateTime.Nowฉันลบวงเล็บไปรอบ ๆxเพื่อที่ฉันจะได้ประหยัดอักขระได้อีก 2 ตัว!
tsavinho

3

Haskell, 171 165 ตัวอักษร

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)

%ชื่อฟังก์ชั่นคือ ดำเนินการตามวันที่ทดสอบในรูปแบบ tuple ตามลำดับ canonical (y, m, d) พร้อมปีจริงและตราประทับกล่องเป็น tuple ของตัวเลขสามตัว:

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

เออร์แลง 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).

ฟังก์ชั่นทดสอบจะเป็น:

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

วิธีการแก้ปัญหานี้ขึ้นอยู่กับความเข้าใจในรายการ มันยืมเคล็ดลับแบบโมดูโลสำหรับปีจากโซลูชั่น Haskell นอกจากนี้ยังใช้calendar:valid_date/1เพื่อจัดการวันที่ที่เป็นไปไม่ได้เนื่องจากจำนวนวันในเดือนที่กำหนด (เช่น "29-2-2" สามารถอยู่ในรูปแบบ YMD เท่านั้น) นอกจากนี้วันนี้อยู่ในdate()รูปแบบของ Erlang (tuple YMD)


2

APL (85)

สิ่งนี้ใช้ฟังก์ชั่นใหม่ของ Dyalog APL 14 แต่ไม่มีไลบรารี่ภายนอก สำหรับการเปลี่ยนแปลงการทำงานบนTryAPL

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

นี่คือฟังก์ชั่นที่รับอาเรย์ 3 องค์ประกอบเป็นอาร์กิวเมนต์ด้านขวา ( ) และวันที่ที่จะตรวจสอบว่าเป็นอาร์กิวเมนต์ด้านซ้าย ( ) ของมันเป็นจำนวนเต็มของYYYYMMDDรูปแบบ เช่นวันที่จะแสดงเป็นตัวเลข2014-07-0920140709

ทดสอบ:

      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

คำอธิบาย:

  • Z←(⊂⌽⍵),(⊂2⌽⍵),⊂⍵: เปลี่ยนวันที่ที่กำหนดเป็นรูปแบบ YMD โดยพลิก(⊂⌽⍵)หมุนไปทางซ้าย 2 (⊂2⌽⍵)หรือทำอะไร⊂⍵เลย อย่างน้อยหนึ่งในนั้นคือวันที่ที่เหมาะสมในรูปแบบ YMD อาจมากกว่าหนึ่งถ้าวันที่ไม่ชัดเจน
  • {∧/12 31≥1↓⍵}¨Z: ทดสอบว่าแต่ละวันนั้นถูกต้องหรือไม่: ปี (องค์ประกอบแรก) ถูกปล่อยแล้วเดือนนั้นจะต้องไม่สูงกว่า 12 และวันนั้นจะต้องไม่สูงกว่า 31
  • Z/⍨: Zกรองวันที่ที่ถูกต้องจาก
  • {... : สำหรับแต่ละวันที่ถูกต้อง:
    • ⍵+(99≥⊃⍵)×3↑1900+100×50>⊃⍵: ถ้าปีไม่สูงกว่า 99 ให้เพิ่ม 1900 จากนั้น 100 ถ้าปีนั้นต่ำกว่า 50
    • (3/100)⊥: ถอดรหัสราวกับว่ามันเป็นชุดของตัวเลขฐาน -100 (ปีสูงกว่า 100 แต่ไม่สำคัญเท่าองค์ประกอบแรก) ซึ่งจะให้ตัวเลขสำหรับวันที่ที่ถูกต้องในรูปแบบเดียวกับอาร์กิวเมนต์ซ้าย
  • ⍺≤เพราะแต่ละวันดูว่ามันไม่ได้มีขนาดเล็กกว่า นี้จะให้เวกเตอร์ไบนารีที่ 1 หมายถึงOKคนและ 0 spoiledหมายถึง
  • 100×(+/÷⍴): หารผลรวมของเวกเตอร์ไบนารีด้วยความยาวและคูณด้วย 100

บันทึก 7 ไบต์ (K และชนะโดยอัตรากำไรที่ดี) กับ stranding และทำให้ฟังก์ชั่นภายในโดยปริยาย:{100×(+/÷⍴)⍺≤((3/100)⊥⊢+(99≥⊃)×3↑1900+100×50>⊃)¨Z/⍨{∧/12 31≥1↓⍵}¨Z←(⌽⍵)(2⌽⍵)⍵}
อดัม

0

Java: 349 ตัวอักษร (3 ช่องว่างโดยไม่มีช่องว่าง)

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

นี่คือคลาสที่บรรจุที่สามารถใช้ในการทดสอบได้รวมถึงวิธีการที่ degolfed รุ่น (เล็กน้อย):

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

นี่เป็นรอบแรกของการเล่นกอล์ฟรหัสและฉันคิดว่าฉันคิดว่าทำไมฉันไม่เห็นนักกอล์ฟ Java จำนวนมาก


1
คุณต้องยอมรับint[]อาร์กิวเมนต์เป็นไม่ใช่สามintวิ
Joey

ตกลงฉันซ่อมมันแล้ว
shieldgenerator7

0

C # 287 ไบต์

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

เล่นกอล์ฟเป็นครั้งแรกโดยมองหาคำแนะนำ โดยเฉพาะอย่างยิ่งการลบไบต์เนื่องจากเนมสเปซ

การใช้ความจริงในทางที่ผิดต้องใช้ฟังก์ชั่นเท่านั้นไม่ใช่โปรแกรมจริง นอกจากนี้ฟังก์ชันยังส่งผลให้เกิดข้อยกเว้นที่ไม่ได้ตรวจสอบเสมอ

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 เป็นจุดเริ่มต้นฉันมีการปรับปรุงเล็กน้อย:

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

กอล์ฟอาจเป็นฟังก์ชั่นที่รับค่าสามค่าเป็นอาร์กิวเมนต์
algorithmshark

@algorithmshark ขอบคุณ ฉันไม่รู้ว่าฉันคิดถึงมันอย่างไร กำลังอัปเดต ...
Mr.Wizard
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.