Lesen Sie ein Datum in der xkcd-Notation

49

In seiner xkcd über das ISO 8601 Standard-Datumsformat schlich sich Randall in eine eher kuriose alternative Notation:

Bildbeschreibung hier eingeben

Die großen Zahlen sind alle Ziffern, die im aktuellen Datum in der üblichen Reihenfolge angezeigt werden, und die kleinen Zahlen sind auf 1 basierende Indizes für das Vorkommen dieser Ziffer. So stellt das obige Beispiel dar 2013-02-27.

Definieren wir eine ASCII-Darstellung für ein solches Datum. Die erste Zeile enthält die Indizes 1 bis 4. Die zweite Zeile enthält die "großen" Ziffern. Die dritte Zeile enthält die Indizes 5 bis 8. Befinden sich in einem Slot mehrere Indizes, werden diese vom kleinsten zum größten Index nebeneinander aufgeführt. Befinden sich höchstens mIndizes in einem einzelnen Slot (dh auf derselben Ziffer und in derselben Zeile), sollte jede Spalte m+1Zeichen breit und linksbündig sein:

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

Siehe auch die Begleitherausforderung für die umgekehrte Konvertierung.

Die Herausforderung

Geben Sie bei einem Datum in der xkcd-Notation das entsprechende ISO 8601-Datum aus ( YYYY-MM-DD).

Sie können ein Programm oder eine Funktion schreiben, indem Sie eine Eingabe über STDIN (oder die nächstgelegene Alternative), ein Befehlszeilenargument oder ein Funktionsargument vornehmen und das Ergebnis über STDOUT (oder die nächstgelegene Alternative), einen Funktionsrückgabewert oder einen Funktionsparameter (out) ausgeben.

Sie können davon ausgehen, dass die Eingabe ein beliebiges gültiges Datum zwischen Jahren 0000und 9999einschließlich ist.

Die Eingabe enthält keine führenden Leerzeichen. Sie können jedoch davon ausgehen, dass die Zeilen mit Leerzeichen zu einem Rechteck aufgefüllt sind, das höchstens eine nachgestellte Spalte mit Leerzeichen enthält.

Es gelten die Standardregeln für .

Testfälle

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
Martin Ender
quelle
11
Leute, die das Datum im "Black Cat" -Format schreiben, sind der Fluch meiner Existenz.
Carcigenicate
1
Vergib mir meine Unwissenheit, aber wie genau stimmt das seltsame Format mit dem Datum überein? Kann nicht für das Leben von mir das Muster erarbeiten.
Tom Carpenter
2
@TomCarpenter Die untere und obere Zeile geben an, wo die Zahlen in der mittleren Zeile im Datum erscheinen. ZB 1ist oben 2, also ist die erste Ziffer 2. 2ist oben 0, also ist die zweite Ziffer 0. 3ist oben 1, 4ist oben 3, so dass wir 2013als die ersten vier Ziffern erhalten. Jetzt 5ist unten 0, also ist die fünfte Ziffer 0, 6und 7beide sind unten 2, also sind diese beiden Ziffern 2. Und schließlich 8ist unten 7, so ist die letzte Ziffer 8, und wir enden mit 2013-02-27. (Die Bindestriche sind in der xkcd-Notation enthalten, da wir wissen, an welchen Positionen sie angezeigt werden.)
Martin Ender

Antworten:

8

CJam, 35 Bytes

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

Probieren Sie es hier aus . Es wird erwartet, dass die Eingabezeilen mit Leerzeichen aufgefüllt werden.

Erläuterung

llLiest zwei Eingabezeilen und {1$e>}*führt einen "Scan" für die zweite Zeile durch : Es nimmt alle Präfixe seiner Eingabe und berechnet das Maximum jedes Präfixes. Für die Eingabezeile "0 1 2 7 8"wird diese gedrückt "0001112227778". Unser Stack sieht jetzt so aus:

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

Wir müssen die Werte mithilfe von neu in eine Liste aufnehmen ]. Dies erfasst auch unsere erste Zeile, so dass wir sie mit rausholen (, um zu bekommen

"0001112227778" "first line"

wie erwartet.

eelee+ Zählt diese Zeile auf, macht dann dasselbe für eine dritte Eingabezeile und verkettet die Ergebnisse, wobei so etwas oben auf dem Stapel verbleibt:

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

Jetzt befindet sich unser Stapel dort, ["0001112227778" X]wo Xsich die oben aufgeführte Liste befindet.

Wir drehen jedes Paar in X( Wf%), sortieren die Paare lexikographisch ( $) und lassen die letzten 8 Paare übrig -8>. Das bringt uns so etwas wie:

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

Dies funktioniert, da bei der Sortierung alle Paare mit Schlüssel '(Leerzeichen) in aufsteigender Reihenfolge vor allen Ziffern stehen.

Dies sind die " x- Positionen" der Zeichen 12345678in der ersten und dritten Zeile: Wir müssen nur die Zeichen aus unserer (modifizierten) zweiten Zeile abrufen, die vertikal mit ihnen ausgerichtet sind.

Dazu nehmen wir jede Position ( Wf=) und indexieren in die Zeichenfolge, die wir zuvor erstellt haben ( \f=). Wir haben "20610222"jetzt auf dem Stapel: Um die Bindestriche hinzuzufügen, teilen wir uns zuerst in Segmente der Länge zwei ( 2/), drucken das erste Segment ohne eine neue Zeile ( (o) und verbinden die verbleibenden Segmente mit Bindestrichen ( '-*).

EDIT : cooler Scan-Trick, Martin! Vier Bytes gespeichert.

BEARBEITEN 2 : zwei weitere Bytes durch Ersetzen eelee+durch l+ee; dies funktioniert, weil die Linien alle die gleichen Längen haben, und die Liste Indizierung in CJam ist automatisch die Liste Länge Modulo, so dass die Indizes n+0, n+1, n+2... schön Karte zu 0, 1, 2...

EDIT 3 : Martin hat im letzten Schritt des Prozesses ein weiteres Byte gespeichert. Nett!

Lynn
quelle
6

Pyth, 48 43

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

Test Suite

Erfordert das Auffüllen eines Rechtecks ​​mit Leerzeichen.

Ich denke nicht, dass dies der beste Ansatz ist, aber im Grunde wird der mittlere Wert in einer Zeichenfolge in den Index geschrieben, auf die durch den oberen oder unteren Wert hingewiesen wird. Nun, ich hatte wohl genug Zeit, um die meisten offensichtlichen Dinge, die ich gesehen habe, zu golfen. : P

FryAmTheEggman
quelle
4

JavaScript (ES7), 115

Anonyme Funktion. Unter Verwendung von Vorlagenzeichenfolgen gibt es eine Zeilenvorschubzeile, die von Bedeutung ist und in der Bytezahl enthalten ist.

Voraussetzung: Die mittlere Eingabezeile darf nicht kürzer als die erste oder die letzte sein. Diese Anforderung ist erfüllt, wenn die Eingabe mit Leerzeichen aufgefüllt wird, um ein Rechteck zu bilden.

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 verwendet .map anstelle des Array-Verständnisses

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

Weniger golfen

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

Testschnipsel

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>

edc65
quelle
Herzlichen Glückwunsch, dass Sie als Erster beide Herausforderungen gelöst haben. :)
Martin Ender
3

Haskell, 125 106 103 Bytes

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]

Erfordert das Auffüllen mit Leerzeichen zu einem vollen Rechteck.

Anwendungsbeispiel: f " 1 3 24\n0 1 2 7 8 \n57 6 8 "-> "1878-02-08".

Wie es funktioniert:

[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)
nimi
quelle
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``}

Testfälle .

Michał Perłakowski
quelle
1

Perl, 154 Bytes

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 & erklärt

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
};
type_outcast
quelle
0

JavaScript (ES6), 131 Byte

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

Erläuterung

Erfordert, dass die Eingabe mit Leerzeichen aufgefüllt wird, um ein Rechteck zu bilden.

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

Prüfung

user81655
quelle
0

Powershell, 119 Bytes

$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-Testskript:

$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"
}

Ausgabe:

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
mazzy
quelle
0

Jelly , 38 Bytes

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

Probieren Sie es online!

Der Helfer ist nur da, um die Eingabe zu erleichtern. das ist eigentlich ein volles programm. Achten Sie auf Folgendes :

  • Die erste und letzte Zeile ( ''') sowie die Zeilen daneben (zur Verdeutlichung leer).
    • Das eigentliche Eingabeformat enthält keine zweiten und vorletzten Leerzeilen, und die Zeichenfolge beginnt und endet direkt neben den Anführungszeichen, ohne dazwischen eine neue Zeile, wie folgt:
      '' '1 3 24
      0 1 2 7 8 
      57 6 8 '' '
      Sie können die Fußzeile in diesem Format belassen. Dies ist wirklich eine mehrzeilige Python-Zeichenfolge, und die Anführungszeichen sind für einige Eingaben erforderlich.
  • Fülle die Eingabe mit Leerzeichen auf! Jede korrekte Ausgabe ohne korrekt gepolsterte Eingabe ist völlig zufällig und wird von mir nicht unterstützt.
Erik der Outgolfer
quelle