Read a date in xkcd notation
CJam, 35 bytes
ll{1$e>}*](l+eeWf%$-8>Wf=\f=2/(o'-*
Try it here. It expects the input lines to be padded with spaces.
Explanation
ll
reads two lines of input, and {1$e>}*
performs a "scan" on the second one: it it takes all prefixes of its input and computes the maximum of each prefix. For the input line "0 1 2 7 8"
, this pushes "0001112227778"
. Our stack now looks like this:
"first line" '0 '0 '0 '1 '1 '1 ...
We need to re-capture the values into a list ourselves using ]
; this captures our first line as well, so we pop it back out using (
, to get
"0001112227778" "first line"
as expected.
eelee+
enumerates this line, then does the same for a third input line, and concatenates the results, leaving something like this on the top of the stack:
[[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]]
Now our stack is ["0001112227778" X]
where X
is the enumerated list above.
We flip each pair in X
(Wf%
), sort the pairs lexicographically ($
), and leave the last 8 pairs -8>
. This gets us something like:
[['1 8] ['2 0] ['3 12] ['4 4] ['5 0] ['6 8] ['7 9] ['8 10]]
This works, because the sort places all the pairs with key '
(space) before all the digits in ascending order.
These are the "x-positions" of the characters 12345678
on the first and third lines: we only need to retrieve the characters from our (modified) second line that are vertically aligned with them.
To do this, we take each position (Wf=
), index into the string we made earlier (\f=
). We have "20610222"
on the stack now: to add the dashes, first we split into segments of length two (2/
), print the first segment without a newline ((o
) and join the remaining segments with dashes ('-*
).
EDIT: cool scan trick, Martin! Saved four bytes.
EDIT 2: saved two more bytes by replacing eelee+
with l+ee
; this works, because the lines all have the same lengths, and list indexing in CJam is automatically modulo the list length, so the indices n+0
, n+1
, n+2
... nicely map to 0
, 1
, 2
...
EDIT 3: Martin saved another byte in the final step of the process. Nice!
Pyth, 48 43
j\-cj\-ctuuXN.xsTZK?qJhtHdKJ+hHeHGC.z*9d4 7
Test Suite
Requires padding with spaces into a rectangle.
I don't think this is the best approach, but basically it writes the middle value to the index in a string pointed at by the top or bottom value. Well I guess I had enough time to golf most of the obvious stuff I saw. :P
JavaScript (ES7), 115
Anonymous function. Using template strings, there is a newline that is signifiocant and included in byte count.
Requirement: the middle input line cannot to be shorter than the first or the last. This requirement is satisfied when the input is padded with spaces to form a rectangle.
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 version 117 using .map instead of array comprehension
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``)
Less 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``
)
Test snippet
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>