Leggi una data in notazione xkcd


49

Nel suo xkcd sul formato di data standard ISO 8601 Randall ha inserito una notazione alternativa piuttosto curiosa:

inserisci qui la descrizione dell'immagine

I numeri grandi sono tutte le cifre che appaiono nella data corrente nel loro solito ordine e i numeri piccoli sono indici basati su 1 delle occorrenze di quella cifra. Quindi l'esempio sopra rappresenta 2013-02-27.

Definiamo una rappresentazione ASCII per tale data. La prima riga contiene gli indici da 1 a 4. La seconda riga contiene le cifre "grandi". La terza riga contiene gli indici da 5 a 8. Se ci sono più indici in un singolo slot, vengono elencati uno accanto all'altro dal più piccolo al più grande. Se ci sono al massimo mindici in un singolo slot (cioè sulla stessa cifra e nella stessa riga), ogni colonna dovrebbe avere m+1caratteri larghi e allineati a sinistra:

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

Vedi anche la sfida del compagno per la conversione opposta.

La sfida

Data una data in notazione xkcd, genera la data ISO 8601 corrispondente ( YYYY-MM-DD).

È possibile scrivere un programma o una funzione, prendendo l'input tramite STDIN (o l'alternativa più vicina), l'argomento della riga di comando o l'argomento della funzione e producendo il risultato tramite STDOUT (o l'alternativa più vicina), il valore di ritorno della funzione o il parametro della funzione (out).

Si può presumere che l'input sia una data valida tra anni 0000e 9999, compresi.

Non ci saranno spazi iniziali nell'input, ma puoi supporre che le linee siano riempite di spazi in un rettangolo, che contiene al massimo una colonna di spazi finali.

Si applicano le regole standard del .

Casi test

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
Le persone che scrivono la data nel formato "gatto nero" sono la rovina della mia esistenza.
Carcigenicate,

1
Perdona la mia ignoranza, ma in che modo esattamente il formato strano corrisponde alla data? Non posso per la vita di me capire il modello.
Tom Carpenter,

2
@TomCarpenter La riga inferiore e superiore indicano dove compaiono i numeri nella riga centrale nella data. Ad esempio 1è sopra 2, quindi la prima cifra è 2. 2è sopra 0, quindi la seconda cifra è 0. 3è sopra 1, 4è sopra 3, quindi otteniamo 2013le prime quattro cifre. Ora 5è sotto 0, quindi la quinta cifra è 0, 6e 7sono entrambe sotto 2, quindi entrambe le cifre sono 2. E infine, 8è sotto 7, quindi l'ultima cifra è 8, e finiamo con 2013-02-27. (I trattini sono impliciti nella notazione xkcd perché sappiamo in quali posizioni appaiono.)
Martin Ender

Risposte:


8

CJam, 35 byte

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

Provalo qui . Si aspetta che le linee di input siano riempite di spazi.

Spiegazione

lllegge due righe di input ed {1$e>}*esegue una "scansione" sulla seconda: prende tutti i prefissi del suo input e calcola il massimo di ciascun prefisso. Per la linea di input "0 1 2 7 8", questo spinge "0001112227778". Il nostro stack ora è simile al seguente:

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

Dobbiamo acquisire nuovamente i valori in un elenco usando noi stessi ]; questo cattura anche la nostra prima linea, quindi la rimettiamo indietro usando (, per ottenere

"0001112227778" "first line"

come previsto.

eelee+ enumera questa riga, quindi fa lo stesso per una terza riga di input e concatena i risultati, lasciando qualcosa del genere in cima allo 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]]

Ora il nostro stack è ["0001112227778" X]dove si Xtrova l'elenco elencato sopra.

Capovolgiamo ogni coppia in X( Wf%), ordiniamo le coppie lessicograficamente ( $) e lasciamo le ultime 8 coppie -8>. Questo ci dà qualcosa del tipo:

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

Funziona perché l'ordinamento posiziona tutte le coppie con chiave '(spazio) prima di tutte le cifre in ordine crescente.

Queste sono le " x -positions" dei caratteri 12345678sulla prima e terza riga: dobbiamo solo recuperare i caratteri dalla nostra (modificata) seconda linea che sono allineati verticalmente con loro.

Per fare questo, prendiamo ogni posizione ( Wf=), indice nella stringa che abbiamo creato in precedenza ( \f=). Ora abbiamo "20610222"in pila: per aggiungere i trattini, prima dividiamo in segmenti di lunghezza due ( 2/), stampiamo il primo segmento senza una nuova riga ( (o) e uniamo i segmenti rimanenti con trattini ( '-*).

EDIT : bel trucco di scansione, Martin! Quattro byte salvati.

EDIT 2 : salvato altri due byte sostituendo eelee+con l+ee; Questo funziona, perché le linee hanno tutti le stesse lunghezze, e la lista indicizzazione in CJam è con modulo automaticamente la lunghezza della lista, così gli indici n+0, n+1, n+2... ben mappati 0, 1, 2...

EDIT 3 : Martin ha salvato un altro byte nella fase finale del processo. Bello!


6

Pyth, 48 43

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

Test Suite

Richiede imbottitura con spazi in un rettangolo.

Non penso che questo sia l'approccio migliore, ma fondamentalmente scrive il valore medio nell'indice in una stringa puntata dal valore superiore o inferiore. Beh, credo di aver avuto abbastanza tempo per giocare a golf con la maggior parte delle cose ovvie che ho visto. : P


4

JavaScript (ES7), 115

Funzione anonima. Usando le stringhe di template, c'è una nuova riga che è significativa e inclusa nel conteggio dei byte.

Requisito: la riga di input centrale non può essere più corta della prima o dell'ultima. Questo requisito è soddisfatto quando l'ingresso è riempito con spazi per formare un rettangolo.

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 versione 117 utilizzando .map invece della comprensione dell'array

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

Meno golf

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>


Complimenti per essere stato il primo a risolvere entrambe le sfide. :)
Martin Ender,

3

Haskell, 125 106 103 byte

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]

Richiede imbottitura con spazi per un rettangolo completo.

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

Come funziona:

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

Casi di test .


1

Perl, 154 byte

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 e spiegato

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

Spiegazione

Richiede che l'input sia riempito di spazi per formare un rettangolo.

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

Test


0

Powershell, 119 byte

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

Script di prova non golfato:

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

Produzione:

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

Gelatina , 38 byte

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

Provalo online!

L'helper è lì solo per facilitare l'input; questo è in realtà un programma completo. Assicurati di occuparti di :

  • La prima e l'ultima riga ( '''), così come le righe accanto (vuote, lì per chiarezza).
    • Il formato di input effettivo non ha la seconda e penultima riga vuota e la stringa inizia e termina direttamente accanto alle virgolette, senza una nuova linea di mezzo, in questo modo:
      '' '1 3 24
      0 1 2 7 8 
      57 6 8 '' '
      Puoi lasciare il piè di pagina mentre usi questo formato. Questa è davvero una stringa multilinea Python e le virgolette sono necessarie per alcuni input.
  • Riempi l'input con spazi finali! Qualsiasi output corretto senza input correttamente imbottito è del tutto casuale e non è approvato da me.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.