อ่านวันที่ในรูปแบบ xkcd


49

ใน xkcd ของเขาเกี่ยวกับรูปแบบวันที่มาตรฐาน ISO 8601 Randall ดักในสัญกรณ์ทางเลือกที่ค่อนข้างอยากรู้:

ป้อนคำอธิบายรูปภาพที่นี่

ตัวเลขขนาดใหญ่คือตัวเลขทั้งหมดที่ปรากฏในวันที่ปัจจุบันตามลำดับปกติและตัวเลขขนาดเล็กเป็นดัชนีที่อิงกับ 1 ครั้งของการเกิดขึ้นของตัวเลขนั้น 2013-02-27ดังนั้นตัวอย่างข้างต้นหมายถึง

ลองกำหนดการแสดง ASCII สำหรับวันดังกล่าว บรรทัดแรกมีดัชนี 1 ถึง 4 บรรทัดที่สองประกอบด้วยตัวเลข "ใหญ่" บรรทัดที่สามประกอบด้วยดัชนี 5 ถึง 8 หากมีดัชนีหลายรายการในสล็อตเดียวรายการเหล่านั้นจะอยู่ติดกันตั้งแต่ขนาดเล็กที่สุดไปหามากที่สุด หากมีmดัชนีมากที่สุดในช่องเดียว (เช่นในหลักเดียวกันและในแถวเดียวกัน) แต่ละคอลัมน์ควรมีm+1อักขระกว้างและจัดชิดซ้าย:

2  3  1  4
0  1  2  3  7
5     67    8

ดูความท้าทายสำหรับคู่หูสำหรับการแปลงฝั่งตรงข้าม

ความท้าทาย

ได้รับวันที่ในรูปแบบ xkcd-notation ให้ส่งออกวันที่ ISO 8601 ที่สอดคล้องกัน ( YYYY-MM-DD)

คุณสามารถเขียนโปรแกรมหรือฟังก์ชั่น, รับอินพุตผ่าน STDIN (หรือทางเลือกที่ใกล้เคียงที่สุด), อาร์กิวเมนต์บรรทัดคำสั่งหรืออาร์กิวเมนต์ของฟังก์ชันและส่งผลลัพธ์ผ่าน STDOUT (หรือทางเลือกที่ใกล้เคียงที่สุด), ค่าส่งคืนของฟังก์ชันหรือพารามิเตอร์

คุณอาจจะสมมติว่าการป้อนข้อมูลเป็นวันที่ที่ถูกต้องระหว่างปี0000และ9999รวม

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

ใช้กฎมาตรฐานของ

กรณีทดสอบ

2  3  1  4
0  1  2  3  7
5     67    8
2013-02-27

2  3  1     4
0  1  2  4  5
   5  67 8
2015-12-24

     1234
1    2
5678
2222-11-11

   1     3  24
0  1  2  7  8
57    6     8
1878-02-08

2   4   1   3
0   1   2   6
5       678
2061-02-22

      1 4 2 3
0 1 2 3 4 5 6 8
6 5 7         8
3564-10-28

1234
1
5678
1111-11-11

1 2 3 4
0 1 2 3
8 5 6 7
0123-12-30

11
คนที่เขียนวันที่ในรูปแบบ "แมวดำ" เป็นความหายนะของการมีอยู่ของฉัน
Carcigenicate

1
ให้อภัยความไม่รู้ของฉัน แต่รูปแบบแปลก ๆ ตรงกับวันที่อย่างไร ไม่สามารถใช้ชีวิตแบบที่ฉันทำออกมาได้
Tom Carpenter

2
@TomCarpenter บรรทัดด้านล่างและด้านบนระบุตำแหน่งที่ตัวเลขในบรรทัดกลางปรากฏในวันที่ เช่น1อยู่เหนือดังนั้นหลักแรกคือ2 อยู่เหนือดังนั้นหลักที่สองคือ อยู่เหนือ, อยู่เหนือเพื่อให้เราได้รับเป็นตัวเลขสี่หลักแรก ตอนนี้อยู่ด้านล่างดังนั้นหลักที่ห้าคือ, และมีทั้งที่ด้านล่างเพื่อให้ทั้งสองของตัวเลขเหล่านี้จะ และในที่สุดก็อยู่ด้านล่างดังนั้นหลักสุดท้ายเป็นและเราจบลงด้วย (ยัติภังค์มีความหมายโดยนัยในเครื่องหมาย xkcd เพราะเรารู้ว่าตำแหน่งใดที่ปรากฏ)22003143201350067228782013-02-27
Martin Ender

คำตอบ:


8

CJam, 35 ไบต์

ll{1$e>}*](l+eeWf%$-8>Wf=\f=2/(o'-*

ลองได้ที่นี่ คาดว่าบรรทัดอินพุตจะถูกเติมด้วยช่องว่าง

คำอธิบาย

llอ่านอินพุตสองบรรทัดและ{1$e>}*ดำเนินการ "สแกน" บนบรรทัดที่สอง: ใช้ส่วนนำหน้าทั้งหมดของอินพุตและคำนวณค่าสูงสุดของแต่ละคำนำหน้า สำหรับสายการป้อนข้อมูลนี้ผลักดันให้"0 1 2 7 8" "0001112227778"กองของเราตอนนี้มีลักษณะดังนี้:

"first line" '0 '0 '0 '1 '1 '1 ...

เราต้องเก็บค่าลงในรายการที่เราใช้]อีกครั้ง นี่เป็นการจับภาพบรรทัดแรกของเราด้วยดังนั้นเราจึงนำมันกลับมาใช้(อีก

"0001112227778" "first line"

อย่างที่คาดไว้.

eelee+ ระบุบรรทัดนี้จากนั้นทำเช่นเดียวกันสำหรับอินพุตบรรทัดที่สามและต่อผลลัพธ์โดยปล่อยบางอย่างเช่นนี้ไว้ที่ด้านบนของสแต็ก:

[[0 '5] [1 ' ] [2 ' ] [3 ' ] [4 ' ] [5 ' ] [6 ' ] [7 ' ] [8 '6] [9 '7] [10 '8] [11 ' ] [12 ' ]
 [0 '2] [1 ' ] [2 ' ] [3 ' ] [4 '4] [5 ' ] [6 ' ] [7 ' ] [8 '1] [9 ' ] [10 ' ] [11 ' ] [12 '3]]

ตอนนี้สแต็กของเราอยู่["0001112227778" X]ที่ไหนXเป็นรายการที่แจกแจงข้างต้น

เราพลิกแต่ละคู่ในX( Wf%) เรียงลำดับคู่ lexicographically ( $) และปล่อยสุดท้าย 8 -8>คู่ นี่ทำให้เราชอบ:

[['1 8] ['2 0] ['3 12] ['4 4] ['5 0] ['6 8] ['7 9] ['8 10]]

ใช้งานได้เนื่องจากการเรียงลำดับวางคู่ทั้งหมดด้วยคีย์'(ช่องว่าง) หน้าตัวเลขทั้งหมดในลำดับจากน้อยไปหามาก

นี่คือ " x -positions" ของตัวละคร12345678ในบรรทัดแรกและบรรทัดที่สาม: เราต้องการดึงอักขระจากบรรทัดที่สองของเรา (แก้ไข) ที่เรียงตามแนวตั้งกับพวกเขาเท่านั้น

ในการทำสิ่งนี้เรารับแต่ละตำแหน่ง ( Wf=) ทำดัชนีลงในสตริงที่เราทำไว้ก่อนหน้านี้ ( \f=) เรามี"20610222"สแต็กตอนนี้: เพื่อเพิ่มขีดกลางก่อนอื่นเราแบ่งออกเป็นเซ็กเมนต์ของความยาวสอง ( 2/) พิมพ์กลุ่มแรกโดยไม่ต้องขึ้นบรรทัดใหม่ ( (o) และเข้าร่วมส่วนที่เหลือด้วยเครื่องหมายขีดคั่น ( '-*)

แก้ไข : เคล็ดลับการสแกนที่ยอดเยี่ยมมาร์ติน! บันทึกสี่ไบต์

แก้ไข 2 : บันทึกอีกสองไบต์โดยแทนที่eelee+ด้วยl+ee; การทำงานนี้เพราะเส้นที่ทุกคนต้องมีความยาวเดียวกันและการจัดทำดัชนีในรายการ CJam โดยอัตโนมัติ modulo ความยาวรายการดังนั้นดัชนีn+0, n+1, n+2... อย่างแมปไป0, 1, 2...

แก้ไข 3 : Martin บันทึกอีกหนึ่งไบต์ในขั้นตอนสุดท้ายของกระบวนการ ดี!


6

Pyth, 48 43

j\-cj\-ctuuXN.xsTZK?qJhtHdKJ+hHeHGC.z*9d4 7

ชุดทดสอบ

ต้องใช้ช่องว่างภายในที่มีช่องว่างเป็นรูปสี่เหลี่ยมผืนผ้า

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


4

JavaScript (ES7), 115

ฟังก์ชั่นไม่ระบุชื่อ ใช้สตริงแม่แบบมีการขึ้นบรรทัดใหม่ที่มีความหมายและรวมอยู่ในการนับไบต์

ความต้องการ: สายอินพุตกลางไม่สามารถสั้นกว่าครั้งแรกหรือครั้งสุดท้ายได้ ความต้องการนี้เป็นที่พอใจเมื่ออินพุทนั้นเต็มไปด้วยช่องว่างเพื่อสร้างสี่เหลี่ยมผืนผ้า

x=>([a,z,b]=o=x.split`
`,d=i=0,[for(c of z)o[a[i]-1]=o[b[i++]-1]=d=+c||d],o.splice(4,2,'-',o[4],o[5],'-'),o.join``)

ES6เวอร์ชัน117ใช้. map แทนการเข้าใจอาร์เรย์

x=>([a,z,b]=o=x.split`
`,d=0,[...z].map((c,i)=>o[a[i]-1]=o[b[i]-1]=d=+c||d],o.splice(4,2,'-',o[4],o[5],'-'),o.join``)

น้อย golfed

x=>(
  o=[],
  [a,z,b] = x.split`\n`,
  d=i=0,
  [ for(c of z) (
      d = +c||d, // each new digit found in z goes in d (but not the spaces and not the '0' (d starts at 0 anyway)
      o[a[i]-1] = o[b[i]-1] = d, // if the index char is space, that gives index -1 that is ignored when joining later
      ++i
  )],
  o.splice(4,2,'-',o[4],o[5],'-'), // add the dashes in the right places
  o.join``
)

ตัวอย่างการทดสอบ

f=x=>(
  [a,z,b]=o=x.split`\n`,
  d=i=0,[for(c of z)o[a[i]-1]=o[b[i++]-1]=d=+c||d],
  o.splice(4,2,'-',o[4],o[5],'-'),o.join``
)


console.log=x=>O.textContent+=x+'\n';

[['2  3  1  4\n0  1  2  3  7\n5     67    8','2013-02-27']
,['2  3  1     4\n0  1  2  4  5\n   5  67 8','2015-12-24']
,['      1234\n1     2   \n5678','2222-11-11']
,['   1     3  24\n0  1  2  7  8 \n57    6     8','1878-02-08']
,['2   4   1   3\n0   1   2   6  \n5       678','2061-02-22']
,['      1 4 2 3\n0 1 2 3 4 5 6 8\n6 5 7         8','3564-10-28']
,['1234\n1   \n5678','1111-11-11']
,['1 2 3 4\n0 1 2 3\n8 5 6 7','0123-12-30']]
.forEach(t=>(k=t[1],r=f(t[0]),console.log(t[0]+'\n'+r+'\n'+(r==k?'OK\n':'Fail\n'))))
<pre id=O></pre>


ขอแสดงความยินดีที่เป็นคนแรกในการแก้ปัญหาทั้งสองอย่าง :)
Martin Ender

3

Haskell, 125 106 103 ไบต์

a#' '=a
a#b=b
f i|[a,b,c]<-('-':)<$>lines i=[o|m<-"1234-56-78",(n,o,p)<-zip3 a(scanl1(#)b)c,m==n||m==p]

ต้องใช้ช่องว่างภายในกับช่องว่างเพื่อสี่เหลี่ยมผืนผ้าเต็ม

ตัวอย่างการใช้งาน: ->f " 1 3 24\n0 1 2 7 8 \n57 6 8 ""1878-02-08"

มันทำงานอย่างไร:

[a,b,c]<-('-':)<$>lines i          -- split input into lines, prepend a '-' to
                                   -- each, call them a, b and c
               (scanl1(#)b)        -- fill spaces of the middle line with the
                                   -- previous char, e.g.
                                   -- "-0  1  2  7  8 " -> "-00011122277788"
        zip3 a (scanl...) c        -- combine the lines element wise into triples.
                                   -- This is our lookup table for "1234-56-78" 
o|m<-"1234...",  (n,o,p)<-zip...,  m==n||m==p
                                   -- whenever m equals n or p (i.e. was originally
                                   -- in the first or last line), take the
                                   -- corresponding char o (middle line)

2

JavaScript ES6, 231

a=>{r=[];var b=[d,f,e]=a.split`
`.map(n=>n.split``);Array(Math.max(...b.map(n=>n.length))).fill().map((m,i)=>{(m=f[i])&&m!=" "&&(c=m);[d,e].map(m=>(g=m[i])&&g!=" "&&(r[g-1]=c))}),r.splice(4,0,"-"),r.splice(7,0,"-");return r.join``}

กรณีทดสอบ


1

Perl, 154 ไบต์

sub{$_=$_[1];@n=/\d/g;/ +/;map{map{$p[$i++].=$_}unpack"(a$+[0])*";$i=0}@_[0,2];map{map{$r[$_-1]=$n[$i]if/\d/}s plit$"='';$i++}@p;"@r"=~s/....\K(..)/-$1-/r}

Ungolfed & อธิบาย

sub{
    $_=$_[1]; # $_[1] is 2nd argument (i.e., 2nd line)
    @n=/\d/g; # @n now contains all digits in 2nd line
    / +/;     # $+[0] now the chunk length in 2nd line
              # Equivalent to /( +)/;$l = 1 + length $1;
    map{      # Perl golfer's for-loop
        map{ 
            $p[$i++] .= $_    # @p contains positions of each digit
        } unpack "(a$+[0])*"; # Split line into same chunk width
        $i=0 # At end of loop so we don't need $i=0 before next one
    } @_[0,2];# Outer map works on 1st and 3rd lines
    map{
        map{
            # Shove $n[$i] into ($_-1)th slot in @r if $_ is a number
            $r[$_-1] = $n[$i] if /\d/
        } split $"=''; # Equivalent to split '', but sets $"='' for free
        $i++
    }@p;
    # Concatenate @r, convert 20130227 to 2013-02-27, and return
    "@r"=~s/....\K(..)/-$1-/r
};

0

JavaScript (ES6), 131 ไบต์

s=>[...(r=[,,,,"-",,,"-"],l=s.split`
`)[1]].map((c,i)=>(c>"-"?n=c:0,y=+l[0][i],d=+l[2][i],y?r[y-1]=n:0,d?r[d+(d>6)]=n:0))&&r.join``

คำอธิบาย

ต้องใช้อินพุตที่จะเสริมด้วยช่องว่างเพื่อสร้างสี่เหลี่ยมผืนผ้า

s=>
  [...(
    r=[,,,,"-",,,"-"], // r = array of result characters, prefill with "-" symbols
    l=s.split`
`                      // l = array of lines
  )[1]].map((c,i)=>(   // for each character on the middle line
    c>"-"?n=c:0,       // n = the most recent digit encountered
    y=+l[0][i],        // y = index on the year line at the current position
    d=+l[2][i],        // d = index on the date line at the current position
    y?r[y-1]=n:0,      // if y is a number, put n at the index y of the result
    d?r[d+(d>6)]=n:0   // if d is a number, put n at the index d (accounting for "-"s)
  ))
  &&r.join``           // return the result as a string

ทดสอบ


0

Powershell, 119 ไบต์

$r=,'-'*99
($a=$args-split'
')[1]|% t*y|%{if($_-32){$d=$_}
$a[0,2]|%{$r[$_[+$p]-48]=$d}
$p++}
-join$r[1..4+0+5+6+0+7+8]

สคริปต์ทดสอบ Ungolfed:

$f = {

$r=,'-'*99                       # init a result as an array of '-' repeated 99 times
($a=$args-split"`n")[1]|% t*y|%{ # split argument string, store a top, middle and bottom to $a, then for each char of the middle line...
    if($_-32){$d=$_}             # store a digit to $d if the current character of the middle is not a space
    $a[0,2]|%{                   # for the top and the bottom lines...
        $r[$_[+$p]-48]=$d        # store a digit to the result array
    }                            # Note: if char in the current position is a space, then expression $_[+$p]-48 less then 0.
                                 # In this case, the expression $r[32-48]=$d changes unused element in a end of the array.
                                 # That is why the array was created by a large.
    $p++                         # next position
}
-join$r[1..4+0+5+6+0+7+8]        # return joined char with specified numbers
                                 # Note: element with index 0 has value '-'
}

@(
,(@"
2  3  1  4   
0  1  2  3  7
5     67    8
"@,"2013-02-27")

,(@"
2  3  1     4
0  1  2  4  5
    5  67 8  
"@,"2015-12-24")

,(@"
     1234
1    2   
5678     
"@,"2222-11-11")

,(@"
1     3  24
0  1  2  7  8 
57    6     8 
"@,"1878-02-08")

,(@"
2   4   1   3
0   1   2   6
5       678  
"@,"2061-02-22")

,(@"
      1 4 2 3  
0 1 2 3 4 5 6 8
6 5 7         8
"@,"3564-10-28")

,(@"
1234
1   
5678
"@,"1111-11-11")

,(@"
1 2 3 4
0 1 2 3
8 5 6 7
"@,"0123-12-30")

) | % {
    $a,$expected = $_
    $result = &$f $a
    "$(""$result"-eq"$expected"): $result"
}

เอาท์พุท:

True: 2013-02-27
True: 2015-12-24
True: 2222-11-11
True: 1878-02-08
True: 2061-02-22
True: 3564-10-28
True: 1111-11-11
True: 0123-12-30

0

เยลลี่ , 38 ไบต์

Ỵṙ-Zn⁶Ṫ€œṗƊḊZḟ⁶V€$€;2/p/Ʋ€ẎṢṪ€s2Ḣ;jɗ”-

ลองออนไลน์!

ผู้ช่วยอยู่ที่นั่นเพื่อให้อินพุตง่ายขึ้น อันที่จริงนี่คือโปรแกรมเต็มรูปแบบ ให้แน่ใจว่าได้ดูแล :

  • บรรทัดแรกและบรรทัดสุดท้าย ( ''') รวมถึงบรรทัดถัดจากบรรทัดเหล่านั้น (ว่างเปล่าเพื่อความชัดเจน)
    • รูปแบบการป้อนข้อมูลจริงไม่มีบรรทัดที่สองและช่องว่างสุดท้ายและสตริงจะเริ่มต้นและสิ้นสุดโดยตรงถัดจากเครื่องหมายคำพูดโดยไม่มีการขึ้นบรรทัดใหม่เช่นนี้:
      '' '1 3 24
      0 1 2 7 8 
      57 6 8 '' '
      คุณสามารถปล่อยให้ส่วนท้ายในขณะที่ใช้รูปแบบนี้ นี่เป็นสตริงแบบหลายบรรทัดของ Python และเครื่องหมายคำพูดจำเป็นสำหรับอินพุตบางตัว
  • แผ่นอินพุตด้วยช่องว่างต่อท้าย! เอาท์พุทที่ถูกต้องโดยไม่ต้องใส่เบาะอย่างถูกต้องเป็นเรื่องบังเอิญทั้งหมดและไม่ได้รับการรับรองจากฉัน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.