Converti una data in notazione xkcd


26

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 rappresenta2013-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 ISO 8601 (YYYY-MM-DD ), emette la corrispondente notazione della data xkcd.

È 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).

Ogni anno da 0000a 9999è un input valido.

Gli spazi finali sono consentiti, gli spazi iniziali no. Se lo si desidera, è possibile generare una nuova riga finale finale.

Si applicano le regole standard del .

Casi test

2013-02-27
2  3  1  4
0  1  2  3  7
5     67    8

2015-12-24
2  3  1     4
0  1  2  4  5
   5  67 8

2222-11-11
     1234
1    2
5678

1878-02-08
   1     3  24
0  1  2  7  8
57    6     8

2061-02-22
2   4   1   3
0   1   2   6
5       678

3564-10-28
      1 4 2 3
0 1 2 3 4 5 6 8
6 5 7         8

1111-11-11
1234
1
5678

0123-12-30
1 2 3 4
0 1 2 3
8 5 6 7

Risposte:


1

Pyth, 86 78 byte

JS{K-z\-=GheS.nmmlkd=N,mf<T5d=ZmmhkxdcK1Jmf>T4dZjbmjkmj"".[|k\ \ Gd[hNm]dcJ1eN

Proverò a giocare a golf non appena il mio cervello si sarà ripreso. Sono stato felice solo di vederlo funzionare.


5

JavaScript (ES6), 168 173

Come una funzione anonima. Usando le stringhe di modello, c'è una nuova riga vicino alla fine che è significativa e inclusa nel conteggio dei byte.

d=>d.replace(/\d/g,c=>m=(l=((o[c]=o[c]||[b,c,b])[p/2&~1]+=++p).length)>m?l:m,t=[m=p=b='',b,b],o=[])&o.map(x=>x&&x.map((x,i)=>t[i]+=(x+'     ').slice(0,m+1)))||t.join`
`

Meno golf

f=d=>(
  // get the indices in o and the columns width in m
  m=0,
  p=0,
  o=[],
  d.replace(/\d/g,c=>(
    o[c] = o[c]||['',c,''], // for each found digit :array with top indices, digit, bottom indices
    o[c][p/2 & ~1] += ++p, // (p/2 and not 1) maps 0..3 to 0, 4..7 to 2
    l = o[c].length,
    m = l>m ? l : m // max indices string length in m 
  )),
  // build the output in t
  t=['','',''],
  o.map(x=> x && x.map(
    (x,i) => t[i]+=(x+'     ').slice(0,m+1)) // left justify, max value of m is 4
  ),
  t.join`\n` // return output as a newline separated string
)   

Test snippet

f=d=>
  d.replace(/\d/g,c=>m=(l=((o[c]=o[c]||[b,c,b])[p/2&~1]+=++p).length)>m?l:m,t=[m=p=b='',b,b],o=[])&
  o.map(x=>x&&x.map((x,i)=>t[i]+=(x+'     ').slice(0,m+1)))
  ||t.join`\n`


console.log=x=>O.textContent+=x+'\n'

;['2013-02-27','2015-12-24','2222-11-11','1878-02-08','2061-02-22','3564-10-28','1111-11-11']
.forEach(t=>console.log(t+'\n'+f(t)+'\n'))
<pre id=O></pre>


Oh, buon caso di test aggiuntivo. Lo aggiungerò ad entrambe le sfide.
Martin Ender,

4

Rubino, 200 195 189 178 162 157 caratteri

(Codice 156 caratteri + opzione riga comandi 1 carattere)

o={}
i=0
$_.gsub(/\d/){o[$&]||=['','']
o[$&][i/4]+="#{i+=1}"}
o=o.sort.map &:flatten
puts [1,0,2].map{|i|o.map{|c|c[i].ljust o.flatten.map(&:size).max}*' '}

Esecuzione di esempio:

bash-4.3$ ruby -n xkcd-date.rb <<< '2013-02-27'
2  3  1  4    
0  1  2  3  7 
5     67    8 

bash-4.3$ ruby -n xkcd-date.rb <<< '2222-11-11'
     1234
1    2   
5678     

bash-4.3$ ruby -n xkcd-date.rb <<< '3564-10-28'
      1 4 2 3  
0 1 2 3 4 5 6 8
6 5 7         8

2

Python 2.7, 308 310 byte

i=raw_input().replace("-","")
s,w=sorted(set(i)),len
x,m={},0
for c in s:
    q,v=i,[""]*2
    while c in q:a=str(-~q.index(c)+(w(i)-w(q)));v[int(a)>4]+=a;q=q[q.index(c)+1:]
    m,x[c]=max(m,max(map(w,v))),v
for l in[0,1]:print"".join((lambda x:x+(-~m-w(x))*" ")("".join(x[n][l]))for n in s)+"\n"+(" "*m).join(s)*(-l+1)

Caspita, risolverlo costava solo 2 byte!

La data non deve essere separata, la data può essere di qualsiasi lunghezza, non deve essere una data, potrebbe essere qualsiasi stringa (ma i trattini vengono rimossi). La parte centrale mi sembra piuttosto golfabile.


1

C #, 456

golfed:

string  x(string p){string s=p.Replace("-", ""),a="",d="",e="";var u=new Dictionary<char,List<int>>();for(int i=0;i<s.Length;i++)if(u.ContainsKey(s[i]))u[s[i]].Add(i+1);else u.Add(s[i],new List<int>{i+1});foreach (var c in u.Keys.OrderBy(k=>k)){var t=String.Join("",u[c].Where(i=>i<5));var b=String.Join("",u[c].Where(i=>i>4));var l=Math.Max(t.Length,b.Length);var m=c+"".PadRight(l);a+=t.PadRight(l)+" ";e+=m;d+=b.PadRight(l)+" ";}return a+"\n"+e+"\n"+d;}

Ungolfed:

string  x(string p)
    {
        string s = p.Replace("-", ""),a = "", d = "", e = "";;
        var u = new Dictionary<char, List<int>>();
        for (int i = 0; i < s.Length; i++) if (u.ContainsKey(s[i])) u[s[i]].Add(i + 1); else u.Add(s[i], new List<int>{ i + 1 });            
        foreach (var c in u.Keys.OrderBy(k => k))
        {
            var t = String.Join("", u[c].Where(i => i < 5));
            var b = String.Join("", u[c].Where(i => i > 4));
            var l = Math.Max(t.Length, b.Length);
            var m = c + "".PadRight(l);
            a += t.PadRight(l) + " ";
            e += m;
            d += b.PadRight(l) + " ";
        }
        return a + "\n" + e + "\n" + d;            
    }

1

Perl6, 265 byte

golfed

my$i=get;$i~~s:g/\-//;my@b=$i.comb.unique.sort;my$f={$i.comb[$_[1]-1]eq$_[0]??$_[1]!!''};my$g={[~] .map: $f};my$h={(@b X @^a).rotor(4).map: $g}my@a=$h(1..4);my@c=$h(5..8);my$s=max(|@a».chars,|@c».chars)+1;my$x='%-'~$s~'s';for @a,@b,@c {say [~] @_.map: *.fmt($x)}

Ungolfed (leggermente)

my $i = get;
$i ~~ s:g/\-//;
my @b = $i.comb.unique.sort;
my $f = { $i.comb[$_[1]-1] eq $_[0] ?? $_[1] !! '' };
my $g = { [~] .map: $f };
my $h = { (@b X @^a).rotor(4).map: $g }
my @a = $h(1..4);
my @c = $h(5..8);
my $s = max(|@a».chars, |@c».chars)+1;
my $x = '%-'~$s~'s';
for @a,@b,@c { say [~] @_.map: *.fmt($x) }

1

Python 3, 306 byte

Sto studiando i modi per determinare, prima di assemblare le linee superiore e inferiore, quale sarà la larghezza massima di una determinata colonna. Una volta ottenuto ciò, dovrei essere in grado di costruire direttamente gli spazi nelle linee invece di utilizzare tutte quelle joinfunzioni.

j=''.join
def t(d):
 c,*l={},;i,*n=0,
 for e in d.replace('-',''):
  i+=1
  try:c[e]+=[i]
  except:c[e]=i,
 m=sorted(c)
 for x in m:
  l+=[j(str(p)for p in c[x]if p<5)]
  n+=[j(str(p)for p in c[x]if p>4)]
 f='<'+str(max(map(len,l+n)))
 return'\n'.join(map(lambda o:' '.join(format(i,f)for i in o),(l,m,n)))

1
Non potresti salvare ''.joinin una variabile?
Dennis,

@Dennis: Huh. Mi chiedo perché non ci abbia mai pensato. Forse perché stavo inconsciamente trattando ''.join(...)come join('',...), che invece avrebbe dovuto essere "salvato" come una funzione.
Tim Pederick,

1
Penso che +=[i]possa essere +=i,.
Jonathan Frech,

1
return '\n'-> return'\n'.
Jonathan Frech,

1
@TimPederick Sei sicuro ? (Nota la virgola!)
Jonathan Frech,

0

Powershell, 174 170 168 167 byte

$a=@{}
$args|% t*y|?{$_-45}|%{if(!$a.$_){$a.$_="","","$_"}$a.$_[++$i-gt4]+=$i}
0,2,1|%{$r=$_
-join($a.Keys|sort|%{$a.$_[$r]}|% p*ht(1+($a|% v*|%{$_|% l*h}|sort)[-1]))}

Script di test meno golfato:

$f = {

$a=@{}                              # a hash table for a result
$args|% toCharArray|?{$_-45}|%{     # for each digit from argument strings except a '-'
    if(!$a.$_){$a.$_="","","$_"}    #   create an array if there are no values for the current digit
    $a.$_[++$i-gt4]+=$i             #   append the character to the relative row (0 - top, 1 - bottom) and increment position number
}                                   # the result is a hash table in which the key is a char of a digit and the value is an array of string
                                    # for example, first lines for the first test case:
                                    # @{
                                    #     [char]48: ("2","5","0")
                                    #     [char]49: ("3","","1")
                                    #     [char]50: ("1","67","2")
                                    #     ...
                                    # }
$l=1+($a|% Values|%{$_|% Length}|sort)[-1]      # calc the maximum width of strings
0,2,1|%{                            # for each number 0,2,1
    $r=$_                           # store it as row number
    -join(
        $a.Keys|sort|               # for each keys (digit of the dates) in the sorted order
            %{$a.$_[$r]}|           # push to pipe the relative string
            % padRight $l           # for which to execute the 'padright' method to pad with spaces
    )                               # and finally join the row
}

}

@(

,("2013-02-27",
"2  3  1  4   ",
"0  1  2  3  7",
"5     67    8")

,("2015-12-24",
"2  3  1     4",
"0  1  2  4  5",
"   5  67 8   ")

,("2222-11-11",
"     1234 ",
"1    2    ",
"5678      ")

,("1878-02-08",
"   1     3  24 ",
"0  1  2  7  8  ",
"57    6     8  ")

,("2061-02-22",
"2   4   1   3 ",
"0   1   2   6 ",
"5       678   ")

,("3564-10-28",
"      1 4 2 3   ",
"0 1 2 3 4 5 6 8 ",
"6 5 7         8 ")

,("1111-11-11",
"1234 ",
"1    ",
"5678 ")

,("0123-12-30",
"1 2 3 4 ",
"0 1 2 3 ",
"8 5 6 7 ")

) | % {
    $d, $expected = $_
    $result = &$f $d

    $d
    $j=0
    $result|%{
        "$($_.trimEnd() -eq $expected[$j].TrimEnd()): |$_|"   # Vertical bars only to see trailing and leading spaces
        $j++
    }
}

Output (solo barre verticali per vedere gli spazi finali e iniziali):

2013-02-27
True: |2  3  1  4     |
True: |0  1  2  3  7  |
True: |5     67    8  |
2015-12-24
True: |2  3  1     4  |
True: |0  1  2  4  5  |
True: |   5  67 8     |
2222-11-11
True: |     1234 |
True: |1    2    |
True: |5678      |
1878-02-08
True: |   1     3  24 |
True: |0  1  2  7  8  |
True: |57    6     8  |
2061-02-22
True: |2   4   1   3   |
True: |0   1   2   6   |
True: |5       678     |
3564-10-28
True: |      1 4 2 3   |
True: |0 1 2 3 4 5 6 8 |
True: |6 5 7         8 |
1111-11-11
True: |1234 |
True: |1    |
True: |5678 |
0123-12-30
True: |1 2 3 4 |
True: |0 1 2 3 |
True: |8 5 6 7 |
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.