Преобразовать дату в нотацию xkcd


26

В своем xkcd о стандартном формате даты ISO 8601 Рэндалл вырвался в довольно любопытной альтернативной записи:

введите описание изображения здесь

Большие числа - это все цифры, которые появляются в текущей дате в их обычном порядке, а маленькие цифры - это индексы, основанные на 1, вхождения этой цифры. Таким образом, приведенный выше пример представляет 2013-02-27.

Давайте определим представление ASCII для такой даты. Первая строка содержит индексы с 1 по 4. Вторая строка содержит «большие» цифры. Третья строка содержит индексы с 5 по 8. Если в одном слоте несколько индексов, они перечислены рядом друг с другом от наименьшего к наибольшему. Если mв одном слоте имеется не более индексов (т.е. в одной цифре и в одной строке), то каждый столбец должен иметь m+1ширину символов и выравниваться по левому краю:

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

Смотрите также сопутствующий вызов для обратного преобразования.

Соревнование

Учитывая дату ISO 8601 ( YYYY-MM-DD), выведите соответствующую запись даты xkcd.

Вы можете написать программу или функцию, принимая ввод через STDIN (или ближайшую альтернативу), аргумент командной строки или аргумент функции и выводя результат через STDOUT (или ближайшую альтернативу), возвращаемое значение функции или параметр функции (out).

Любой год от 0000до 9999является действительным вкладом.

Пробелы в конце разрешены, пробелы в начале - нет. При желании вы можете вывести один завершающий символ новой строки.

Применяются стандартные правила .

Тестовые случаи

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

Ответы:


1

Pyth, 86 78 байт

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

Я постараюсь сыграть в эту игру, как только мой мозг восстановится. Я был счастлив просто увидеть, как это работает.


5

JavaScript (ES6), 168 173

Как анонимная функция. Используя строки шаблона, в конце есть новая строка, которая является существенной и включена в число байтов.

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

Меньше гольфа

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
)   

Тестовый фрагмент

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>


О, хороший дополнительный контрольный пример. Я добавлю это к обеим задачам.
Мартин Эндер

4

Рубин, 200 195 189 178 162 157 знаков

(Опция из 156 символов + 1 символ командной строки)

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}*' '}

Образец прогона:

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 байт

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)

Ничего себе, его исправление стоило всего 2 байта!

Дата не должна быть разделена, дата может быть любой длины, она не должна быть датой, это может быть любая строка (но дефисы удаляются). Средняя часть выглядит довольно играбельно для меня.


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 байт

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

Неутолкнутый (слегка)

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 байт

Я исследую способы определения, прежде чем собирать верхнюю и нижнюю строки, какова будет максимальная ширина любого столбца. Как только я это получу, я смогу встраивать пробелы в строки напрямую, а не использовать все эти joinфункции.

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
Не могли бы вы сохранить ''.joinв переменную?
Деннис

@ Денис: Да. Интересно, почему я никогда не думал об этом. Возможно, потому что я подсознательно рассматривал ''.join(...)как join('',...), что вместо этого нужно было бы «сохранить» как функцию.
Тим Педерик

1
Я думаю, что +=[i]может быть +=i,.
Джонатан Фрех

1
return '\n'-> return'\n'.
Джонатан Фрех

1
@TimPederick Ты уверен ? (Обратите внимание на запятую!)
Джонатан Фрех

0

Powershell, 174 170 168 167 байт

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

Менее гольф тестовый скрипт:

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

Вывод (только вертикальные бары, чтобы увидеть конечные и ведущие пробелы):

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 |
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.