xkcd表記で日付を読み取ります


49

ISO 8601標準の日付形式についての彼のxkcd で、ランドールはかなり奇妙な代替表記法に潜んでいます

ここに画像の説明を入力してください

大きな数字はすべて通常の順序で現在の日付に表示される数字であり、小さな数字はその数字の出現の1から始まるインデックスです。したがって、上記の例はを表し2013-02-27ます。

そのような日付のASCII表現を定義しましょう。最初の行にはインデックス1〜4が含まれます。2行目には「大きい」数字が含まれます。3行目には、インデックス5〜8が含まれます。1つのスロットに複数のインデックスがある場合、最小から最大の順に並んで表示されます。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

入力に先行スペースはありませんが、行のスペースが最大で1つのスペースの列を含む長方形になるまで、行にスペースが埋め込まれていると想定できます。

標準の規則が適用されます。

テストケース

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
「黒猫」形式で日付を書く人は、私の存在の悩みの種です。
発がん物質

1
私の無知を許しますが、奇妙なフォーマットはどのくらい正確に日付に対応していますか?私の人生のためにパターンを解決することはできません。
トムカーペンター

2
@TomCarpenter一番下の行と一番上の行は、日付の真ん中の行の数字の位置を示しています。たとえば1、上2にあるので、最初の数字は2です。2は上0にあるので、2桁目は03は上で143であるため2013、最初の4桁として取得します。現在5は下0にあるので、5桁目は06あり7、両方が下2にあるので、それらの数字の両方がそう2です。そして最後に、8は以下な7ので、最後の数字は8であり、最終的にはになります2013-02-27。(ハイフンはxkcd表記で暗黙的に使用されます。これは、ハイフンが表示される位置がわかっているためです。)
Martin Ender

回答:


8

CJam、35バイト

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

ここで試してみてください。入力行にスペースが埋め込まれることが期待されています。

説明

ll入力の2行を読み取り、2行{1$e>}*目の「スキャン」を実行します。入力のすべてのプレフィックスを取得し、各プレフィックスの最大値を計算します。入力行の"0 1 2 7 8"場合、これはプッシュされ"0001112227778"ます。スタックは次のようになります。

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

を使用して、値をリストに再キャプチャする必要があり]ます。これは最初の行もキャプチャするので(、を使用してそれをポップアウトして取得します

"0001112227778" "first line"

予想通り。

eelee+ この行を列挙し、3番目の入力行に対して同じことを行い、結果を連結して、スタックの一番上に次のようなものを残します。

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

これは、ソートが'すべての数字の前にキー(スペース)を持つすべてのペアを昇順で配置するためです。

これらは、1行目と3行目の文字の「x位置」です12345678。垂直方向に位置合わせされた(変更された)2行目から文字を取得するだけです。

これを行うには、各位置(Wf=)を取得し、前に作成した文字列にインデックスを付けます(\f=)。我々は"20610222"まず、長さ2(のセグメントに分割し、ダッシュを追加する:今スタック上2/(改行せずに、第1のセグメントを印刷)(o)及び(ダッシュで残りのセグメントを結合します'-*)。

編集:クールなスキャントリック、マーティン!4バイトを保存しました。

編集2:置換することにより、さらに2バイトを保存しましたeelee+によりl+ee、た。行はすべて同じ長さを有し、かつCJam内のリストのインデックスがあるため、インデックスがように、この作品は、自動的に、リストの長さを法n+0n+1n+2...うまくマッピングするために012...

編集3:マーティンは、プロセスの最終ステップで別のバイトを保存しました。いいね!


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

配列内包の代わりに.mapを使用するES6バージョン117

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

ハスケル、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)


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ɗ”-

オンラインでお試しください!

ヘルパーは、入力を簡単にするためだけにあります。これは実際には完全なプログラムです。気をつけてください

  • 最初と最後の行(''')、およびそれらの隣の行(空、わかりやすくするためにあります)。
    • 実際の入力形式には、2番目と最後から2番目の空行がありません。文字列は、次のように引用符の直後で改行なしで開始および終了します。
      '' '1 3 24
      0 1 2 7 8 
      57 6 8 '' '
      この形式を使用している間は、フッターを残すことができます。これは実際にはPythonの複数行の文字列であり、一部の入力には引用符が必要です。
  • 入力の末尾にスペースを埋めてください!正しくパディングされた入力のない正しい出力は完全に偶然であり、私によって承認されていません。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.