Прочитайте дату в нотації xkcd


49

У своєму 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

Дивіться також супровід виклику для протилежного перетворення.

Змагання

Дано дату в xkcd-notation, виведіть відповідну дату ISO 8601 ( YYYY-MM-DD).

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

Ви можете припустити, що вхід - це будь-яка дійсна дата між роками 0000та 9999включно.

Вхідних пробілів не буде, але ви можете припустити, що рядки прокладені пробілами до прямокутника, який містить щонайменше один стовпчик пробілів.

Діють стандартні правила .

Випробування

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
Люди, які записують дату у форматі «чорна кішка», є основою мого існування.
Carcigenicate

1
Пробачте за моє незнання, але як саме дивний формат відповідає даті? Не можу за життя мене розробити схему.
Том Карпентер

2
@TomCarpenter Нижній і верхній рядки вказують, де в даті відображаються цифри в середньому рядку. Напр. 1Вище 2, тому перша цифра - це 2. 2вище 0, тому друга цифра - 0. 3є вище 1, 4вище 3, тому ми отримуємо 2013як перші чотири цифри. Тепер 5знизу 0, тому п'ята цифра є 0, 6і 7обидві внизу 2, тому обидві ці цифри є 2. І нарешті, 8внизу 7, тому остання цифра є 8, і ми закінчуємо 2013-02-27. (Дефіси неявні в позначеннях xkcd, оскільки ми знаємо, на яких позиціях вони з'являються.)
Мартін Ендер

Відповіді:


8

CJam, 35 байт

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

Спробуйте тут . Він очікує, що рядки вводу будуть прокладені пробілами.

Пояснення

llзчитує два рядки введення та {1$e>}*виконує "сканування" на другому: він бере всі префікси свого введення та обчислює максимум кожного префікса. Для вхідного рядка "0 1 2 7 8"це натискання "0001112227778". Наш стек зараз виглядає так:

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

Нам потрібно повторно зафіксувати значення в списку самостійно за допомогою ]; це також захоплює наш перший рядок, тому ми вискакуємо його назад, використовуючи (, щоб отримати

"0001112227778" "first line"

як і очікувалося.

eelee+ перераховує цей рядок, потім робить те ж саме для третього рядка введення та об'єднує результати, залишаючи щось подібне у верхній частині стеку:

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

Тепер наш стек , ["0001112227778" X]де Xзнаходиться нумерований список вище.

Перевертаємо кожну пару в X( Wf%), сортуємо пари лексикографічно ( $) і залишаємо останні 8 пар -8>. Це дає нам щось на кшталт:

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

Це працює, тому що сортування розміщує всі пари з ключем '(пробіл) перед усіма цифрами у порядку зростання.

Це " x -позиції" символів 12345678у першому та третьому рядках: нам потрібно лише знайти символів з нашого (модифікованого) другого рядка, який вертикально вирівняний з ними.

Для цього беремо кожну позицію ( Wf=), вказуємо на рядок, який ми зробили раніше ( \f=). Тепер у нас є "20610222"стек: щоб додати тире, спочатку розділимо на відрізки довжиною два ( 2/), надрукуємо перший сегмент без нового рядка ( (o) і з'єднаємо решта сегментів з тире ( '-*).

EDIT : класний сканування, Мартіне! Збережено чотири байти.

EDIT 2 : заощадив два байта, замінивши eelee+з l+ee; це працює, тому що лінії мають однакові довжини, і список індексація в CJam автоматично по модулю довжині списку, так що індекси n+0, n+1, n+2... красиво карти з 0, 1, 2...

EDIT 3 : Мартін врятував ще один байт на останньому етапі процесу. Приємно!


6

Піта, 48 43

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

Тестовий сюїт

Потрібна прокладка з пробілами в прямокутник.

Я не думаю, що це найкращий підхід, але в основному він записує середнє значення до індексу в рядку, вказаному на верхнє або нижнє значення. Ну я здогадуюсь, я мав достатньо часу, щоб пограти в гольф більшість очевидних речей, які я бачив. : P


4

JavaScript (ES7), 115

Анонімна функція. Використовуючи рядки шаблону, є новий рядок, який є значущим і включений у кількість байтів.

Вимога: середній рядок введення не може бути коротшим, ніж перший або останній. Цю вимогу задовольняють, коли на вкладі є пробіли, щоб утворити прямокутник.

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 версії 117, використовуючи .map замість розуміння масиву

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

Менше гольфу

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

Фрагмент тесту

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>


Вітаю, що першим вирішив обидва завдання. :)
Мартін Ендер

3

Haskell, 125 106 103 байт

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]

Потрібна прокладка з пробілами до повного прямокутника.

Приклад використання: f " 1 3 24\n0 1 2 7 8 \n57 6 8 "-> "1878-02-08".

Як це працює:

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


1

Perl, 154 байти

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 & пояснив

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

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

Пояснення

Для формування прямокутника потрібен вклад з пробілами.

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

Тест


0

Powershell, 119 байт

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

Невикористаний сценарій тесту:

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

Вихід:

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

Желе , 38 байт

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

Спробуйте в Інтернеті!

Помічник є лише для полегшення введення інформації; це насправді повна програма. Обов’язково дбайте про :

  • Перший і останній рядки ( '''), а також рядки поруч (порожні, там для наочності).
    • Фактичний формат введення не містить другого та передостаннього порожніх рядків, і рядок починається та закінчується безпосередньо біля лапок, без проміжку між такими рядками:
      '' '1 3 24
      0 1 2 7 8 
      57 6 8 '' '
      Ви можете залишити колонтитул, використовуючи цей формат. Це дійсно багаторядковий рядок Python, і лапки необхідні для деяких входів.
  • Прокладіть вхід з пробілами! Будь-який правильний вихід без правильно вкладеного вводу є цілком випадковим і не схвалюється мною.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.