Lire une date en notation xkcd


49

Dans son xkcd sur le format de date standard ISO 8601, Randall s'est fié à une notation alternative plutôt curieuse:

entrez la description de l'image ici

Les grands nombres sont tous les chiffres qui apparaissent dans la date du jour dans leur ordre habituel, et les petits nombres sont des index basés sur 1 des occurrences de ce chiffre. Donc, l'exemple ci-dessus représente 2013-02-27.

Définissons une représentation ASCII pour une telle date. La première ligne contient les index 1 à 4. La seconde ligne contient les "gros" chiffres. La troisième ligne contient les index 5 à 8. S'il existe plusieurs index dans un seul emplacement, ils sont énumérés les uns à côté des autres, du plus petit au plus grand. S'il y a au plus des mindex dans un seul emplacement (c'est-à-dire sur le même chiffre et dans la même ligne), chaque colonne doit alors comporter des m+1caractères larges et alignés à gauche:

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

Voir aussi le défi associé à la conversion opposée.

Le défi

Avec une date en notation xkcd, éditez la date ISO 8601 correspondante ( YYYY-MM-DD).

Vous pouvez écrire un programme ou une fonction en prenant l’entrée via STDIN (ou l’alternative la plus proche), un argument de ligne de commande ou une argumentation de fonction et en générant le résultat via STDOUT (ou l’alternative la plus proche), une valeur de retour de fonction ou un paramètre de fonction (out).

Vous pouvez supposer que la saisie est une date valide comprise entre années 0000et 9999inclus.

Il n'y aura pas d'espaces de début dans l'entrée, mais vous pouvez supposer que les lignes sont complétées d'espaces par un rectangle, qui contient au plus une colonne d'espaces de fin.

Les règles standard de s'appliquent.

Cas de 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
Les personnes qui écrivent la date au format "chat noir" sont le fléau de mon existence.
Carcigenicate

1
Pardonnez mon ignorance, mais comment le format étrange correspond-il exactement à la date? Je ne peux pas pour la vie de travailler sur le modèle.
Tom Carpenter

2
@TomCarpenter Les lignes du bas et du haut indiquent l'emplacement des numéros de la ligne du milieu dans la date. Eg 1est au-dessus 2, le premier chiffre est donc 2. 2est au-dessus 0, donc le deuxième chiffre est 0. 3est au-dessus 1, 4est au-dessus 3, nous obtenons donc 2013comme les quatre premiers chiffres. Maintenant 5est en dessous 0, donc le cinquième chiffre est 0, 6et 7les deux sont en dessous 2, donc ces deux chiffres sont 2. Et enfin, 8est en dessous 7, donc le dernier chiffre est 8, et nous nous retrouvons avec 2013-02-27. (Les traits d'union sont implicites dans la notation xkcd car nous savons à quelles positions ils apparaissent.)
Martin Ender

Réponses:


8

CJam, 35 octets

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

Essayez ici . Il s'attend à ce que les lignes d'entrée soient complétées par des espaces.

Explication

lllit deux lignes d’entrée et {1$e>}*effectue un "balayage" sur la seconde: il prend tous les préfixes de son entrée et calcule le maximum de chaque préfixe. Pour la ligne d'entrée "0 1 2 7 8", cela pousse "0001112227778". Notre pile ressemble maintenant à ceci:

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

Nous devons re-capturer les valeurs dans une liste que nous utilisons nous-mêmes ]; cela capture aussi notre première ligne, donc nous le repassons en utilisant (, pour obtenir

"0001112227778" "first line"

comme prévu.

eelee+ énumère cette ligne, puis fait la même chose pour une troisième ligne d'entrée et concatène les résultats, en laissant quelque chose comme ceci au sommet de la pile:

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

Maintenant, notre pile est ["0001112227778" X]Xest la liste énumérée ci-dessus.

Nous retournons chaque paire entre X( Wf%), trions les paires lexicographiquement ( $) et quittons les 8 dernières paires -8>. Cela nous donne quelque chose comme:

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

Cela fonctionne car le tri place toutes les paires avec la clé '(espace) avant tous les chiffres dans l'ordre croissant.

Ce sont les " x -positions" des caractères 12345678sur les première et troisième lignes: il suffit de récupérer les caractères de notre deuxième ligne (modifiée) qui sont alignés verticalement avec eux.

Pour ce faire, nous prenons chaque position ( Wf=), index dans la chaîne que nous avons créée précédemment ( \f=). Nous avons "20610222"maintenant la pile: pour ajouter les tirets, nous divisons d’abord en segments de longueur deux ( 2/), imprimons le premier segment sans nouvelle ligne ( (o) et joignons les segments restants à des tirets ( '-*).

EDIT : bon truc d'analyse, Martin! Sauvegardé quatre octets.

EDIT 2 : sauvegardé deux octets supplémentaires en remplaçant eelee+par l+ee; cela fonctionne, parce que les lignes ont toutes les mêmes longueurs, et l' indexation de la liste dans CJAM est modulo automatiquement la longueur de la liste, de sorte que les indices n+0, n+1, n+2... carte bien à 0, 1, 2...

EDIT 3 : Martin a enregistré un autre octet dans la dernière étape du processus. Agréable!


6

Pyth, 48 43

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

Suite de tests

Requiert un remplissage avec des espaces dans un rectangle.

Je ne pense pas que ce soit la meilleure approche, mais fondamentalement, il écrit la valeur du milieu dans l'index dans une chaîne pointée par la valeur supérieure ou inférieure. Eh bien, je suppose que j’ai eu assez de temps pour jouer au golf la plupart des choses évidentes que j’ai vues. : P


4

JavaScript (ES7), 115

Fonction anonyme. À l'aide de chaînes de modèle, il existe une nouvelle ligne significative et incluse dans le nombre d'octets.

Condition requise: la ligne d'entrée du milieu ne doit pas être plus courte que la première ou la dernière. Cette exigence est satisfaite lorsque l'entrée est complétée d'espaces pour former un 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 utilisant .map au lieu de la compréhension de tableau

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

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

Extrait de test

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>


Félicitations pour avoir été le premier à résoudre ces deux problèmes. :)
Martin Ender

3

Haskell, 125 106 103 octets

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]

Nécessite un remplissage avec des espaces par rapport à un rectangle complet.

Exemple d'utilisation: f " 1 3 24\n0 1 2 7 8 \n57 6 8 "-> "1878-02-08".

Comment ça fonctionne:

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

Cas de test .


1

Perl, 154 octets

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 & expliqué

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 octets

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

Explication

Requiert que l’entrée soit complétée par des espaces pour former un rectangle.

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

Tester


0

Powershell, 119 octets

$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 de test non-golfé:

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

Sortie:

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

Gelée , 38 octets

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

Essayez-le en ligne!

L'assistant n'est là que pour faciliter la saisie; c'est en fait un programme complet. Assurez-vous de prendre soin de :

  • Les première et dernière lignes ( '''), ainsi que les lignes suivantes (vides, pour plus de clarté).
    • Le format d'entrée actuel ne comporte pas la deuxième et l'avant-dernière lignes vides, et la chaîne commence et se termine directement à côté des guillemets, sans nouvelle ligne entre les deux, comme ceci:
      '' '1 3 24
      0 1 2 7 8 
      57 6 8 '' '
      Vous pouvez laisser le pied de page lorsque vous utilisez ce format. Il s'agit en réalité d'une chaîne multiligne Python, et les guillemets sont nécessaires pour certaines entrées.
  • Tapez l'entrée avec des espaces de fin! Toute sortie correcte sans entrée correctement rembourrée est entièrement une coïncidence et n’est pas approuvée par moi.
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.