以xkcd表示法读取日期


49

关于ISO 8601标准日期格式的 xkcd中 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格式的日期,请输出相应的ISO 8601日期(YYYY-MM-DD)。

您可以编写程序或函数,通过STDIN(或最接近的替代方案),命令行自变量或函数自变量获取输入,并通过STDOUT(或最接近的替代方案),函数返回值或函数(out)参数输出结果。

您可以假设输入的是介于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 2015年

1
原谅我的无知,但是奇怪的格式与日期到底有什么对应?无法为我的生活制定模式。
汤姆·卡彭特

2
@TomCarpenter底行和顶行指示日期中间行中的数字出现的位置。例如1在上面2,因此第一个数字是22在上方0,因此第二个数字是03高于14高于3,因此我们得到2013前四位数字。现在5在下面0,所以第五位数字是06并且7都在下面2,所以这两个数字都是2。最后是,8在下面7,所以最后一位是8,我们最后得到2013-02-27。(连字符在xkcd表示法中是隐含的,因为我们知道它们出现在什么位置。)
Martin Ender

Answers:


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上面的枚举列表中。

我们将XWf%)中的每一对翻转,按字典顺序对()进行排序$,最后剩下8对-8>。这使我们得到如下信息:

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

这是可行的,因为排序将所有带有键'(空格)的对放在所有数字之前,并按升序排列。

这些是第一行和第三行中字符的“ x位置” 12345678:我们只需要从(修改的)第二行中与它们垂直对齐的字符中检索字符。

为此,我们将每个位置(Wf=)索引到之前创建的字符串(\f=)中。现在,我们已经"20610222"在堆栈上:要添加破折号,首先我们将其分割为长度为2(2/)的段,打印不带换行符((o)的第一段,并用破折号('-*)连接其余段。

编辑:很酷的扫描技巧,马丁!保存了四个字节。

编辑2:通过替换保存的另外两个字节eelee+l+ee; 这个工程,因为线都具有相同的长度,并在CJam列表索引自动模列表的长度,这样的指标n+0n+1n+2...很好的映射到012...

编辑3:马丁在过程的最后一步中保存了另一个字节。真好!


6

佩斯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``)

少打高尔夫球

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>


恭喜您率先解决了这两个挑战。:)
马丁·恩德

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}

取消说明

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]

取消测试的脚本:

$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多行字符串,某些输入必须使用引号。
  • 用尾随空格填充输入!没有正确填充输入的任何正确输出完全是偶然的,我不认可。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.