Разбор посылки

24

Благодаря вашей помощи в конкурсе « Пометить мою почту» PPCG-Post успешно проштамповала все свои посылки сгенерированными штрих-кодами!

Теперь пришло время расшифровать их.

В этом задании ваша программа с учетом штрих-кода, сгенерированного из задания « Пометьте мою почту» , расшифрует его и вернет закодированное целое число.

Но будь осторожен! Штрих-код может быть вверх ногами ...


Штрих-коды 4 штатов

В случае, если вы пропустили проблему кодирования, вам нужно знать, о каких штрих-кодах мы говорим. Штрих-код с 4 состояниями - это ряд столбцов с четырьмя возможными состояниями, каждое из которых представляет целое число с основанием 4:

            |       |
Bar:    |   |   |   |
                |   |

Digit:  0   1   2   3

Отрисованные в ASCII штрих-коды будут занимать три строки текста, используя |символ pipe ( ) для представления части строки и пробел ( ) для представления пустого раздела. Между каждым баром будет один пробел. Пример штрих-кода может выглядеть следующим образом:

| | | | | | | | | |
| | | | | | | | | | | | | | | | |
    | | | | | | | |

Чтобы преобразовать штрих-код обратно в целое число, которое он кодирует, сопоставьте каждую полосу с соответствующей ей цифрой base-4, объедините их и преобразуйте в десятичную.

Поскольку каждый штрих-код будет также представлять различный штрих-код в перевернутом положении, мы реализуем последовательность запуска / остановки, чтобы можно было рассчитать ориентацию. Для этой задачи мы будем использовать последовательность запуска / остановки, указанную Австралийской почтой: каждый штрих-код начинается и заканчивается 1 0последовательностью.


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

Ваша задача состоит в том, чтобы, учитывая штрих-код ASCII с 4 состояниями, проанализировать его и вернуть целое число, которое он кодирует - по сути, это обратная функция Mark My Mail .

Но, чтобы оживить ситуацию, есть загвоздка - штрих-код может быть перевернут. Как и в реальном мире, он будет предоставлен считывателю штрих-кода (вашей программе) для определения правильной ориентации с использованием последовательности запуска / остановки.

Пример:

Учитывая следующий штрих-код:

    | | | |
| | | | | | | | | | |
  | | | | |

Мы можем четко видеть, что первая и последняя пары цифр есть 0, 2и нет 1, 0. Это означает, что штрих-код перевернут вверх дном, поэтому мы должны повернуть его на 180 градусов (а не просто перевернуть каждую полосу), чтобы получить правильную ориентацию:

| | | | |  
| | | | | | | | | | |
    | | | |    

Теперь мы можем начать декодирование. Мы сопоставляем каждый столбец с соответствующей ему цифрой base-4, игнорируя последовательности запуска / остановки, поскольку они не кодируют данные.

| | | | |  
| | | | | | | | | | |
    | | | |    

- - 2 1 0 3 0 2 3 - -

Мы соединяем это с целым числом 4 2103023, а затем преобразуем в десятичное представление 9419для конечного результата.


правила

  • На входе всегда будет действительный штрих-код из 4 состояний, отображаемый в ASCII, как описано выше, с описанной последовательностью запуска / остановки.
    • Вы можете запросить завершающие пробелы или зачеркнутые строки, а также завершающий перевод новой строки - в зависимости от того, какой формат вам подходит.
    • Он может или не может быть в правильной ориентации - ваша программа должна определить, читать ли ее вверх ногами, используя последовательность запуска / остановки.
    • Он не будет кодировать первые нулевые цифры в целых числах от 4 до 4.
  • Вы можете принять входные данные в виде списка строк или строки с символами новой строки.
  • Выходными данными должно быть целое число в стандартной базе целых чисел вашего языка, представляющее данные, которые были закодированы штрих-кодом.
  • Поскольку почтовые марки маленькие и могут вместить в себя очень мало кода, ваш код должен быть как можно короче: это - поэтому выигрывает самая короткая (в байтах) программа!

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

| | | | | | | | | | |
  | | |

= 4096 (перевернуто)

      | | | | | | | |
| | | | | | | | | | | | | | | |
  | | | | | | | | | |

= 7313145 (перевернуто)

    | | | |
| | | | | | | | | | |
  | | | | |

= 9419 (перевернуто)

| | | | | |   
| | | | | | | | |
    | | | |     

= 990 (не перевернуто)

| | | | |   
| | | | | | | | | | |
    | | |       

= 12345 (не перевернуто)

FlipTack
источник
-1 заголовки на двух постах имеют разный формат. («P the P» против «M my M», выберите «the» или «my»: p)
R
1
Будет ли «список строк» быть любой из [String], [{#Char}], [{Char}], [[Char]]?, Учитывая , что Stringэквивалентно{#Char}
Οurous
3
@Ouros Что это за нотация? Я сильно подозреваю, что ответ «да», потому что типы данных очень разные в разных языках, поэтому проблемы кодирования обычно принимают «какой бы эквивалент ни был в вашем языке», но я понятия не имею, какие разные представления вы пытаетесь представить.
IMSoP
1
Что дальше? Отправить электронное письмо? Передать телеграмму? Обработать сообщение?
Санчиз
1
@ Да, тип данных очень гибкий, как описано в IMSoP.
FlipTack

Ответы:

5

Шелуха , 16 байт

ḋṁẊ=hhttĊ2T§▼↔m↔

Попробуйте онлайн!

Ввод - это список строк (для ясности ссылка TIO использует многострочную строку). Строки должны иметь одинаковую длину, и не должно быть дополнительных пробелов.

объяснение

ḋṁẊ=hhttĊ2T§▼↔m↔  Input is a list of strings x.
           §▼     Lexicographic minimum of
             ↔    x reversed and
              m↔  x with each line reversed.
          T       Transpose. Now we have a list of columns.
        Ċ2        Get every second column, removing the blank ones.
    hhtt          Remove first 2 and last 2 (the orientation markers).
 ṁ                Map and concatenate
  Ẋ=              equality of adjacent pairs.
                  This turns a column like "|| " into [1,0], and these pairs are concatenated.
ḋ                 Convert from binary to integer.
Zgarb
источник
2

Сетчатка , 71 байт

(.).
$1
sO$^`^\|.*|.

^..|..¶.*¶..|..$
¶
\|
 |
+`\| 
 ||||
.*¶$
$&$&
\|

Попробуйте онлайн! Ссылка включает в себя меньшие контрольные примеры. Требуется, чтобы первая и последняя строки были дополнены пробелами по длине средней линии. Объяснение:

(.).
$1

Удалите ненужные пробелы.

sO$^`^\|.*|.

Поменяйте местами символы в коде, но если штрих-код начинается с символа a |, выберите весь код, в противном случае разделите его на символы. Затем поменяйте их местами. Это переворачивает код, если он начинается с 0.

^..|..¶.*¶..|..$
¶

Удалите последовательность запуска / остановки и средний ряд (который нам не нужен).

\|
 |
+`\| 
 ||||

Преобразовать пробелы и |s из базы 4 в одинарные.

.*¶$
$&$&

Удвойте последнюю строчку.

\|

Преобразовать в десятичную.

Нил
источник
2

Java (OpenJDK 8) , 181 160 байт

Не слишком потрепанный для решения Java, я уверен, что есть оптимизация, которую я могу сделать, но я уже слишком долго смотрел на это.

Сократите несколько байтов, сокращая цикл, а не используя подстроку.

Golfed

c->{String r="";Integer i,j,l=c[0].length;for(i=4;i<l-4;i+=2){j=c[0][0]>32?i:l-1-i;r+=c[0][j]%8/4*(j==i?1:2)+c[2][j]%8/4*(j==i?2:1)+"";}return l.parseInt(r,4);}

Попробуйте онлайн!

Ungolfed

String r = "";
Integer i, j, l = c[0].length;
for(i=4; i<l-4; i+=2){
    j = c[0][0]>32 ? i : l-1-i;
    r += c[0][j]%8/4 * (j==i?1:2) + c[2][j]%8/4 * (j==i?2:1) + "";
}
return l.parseInt(r, 4);
Люк Стивенс
источник
Только что попробовал ваш код, но с обратным штрих-кодом примера "| | |" "| | | | | | | | | | |" и дайте мне 1024, хорошо, я не могу отформатировать это, но тот, что на примере, но попробуйте пример, который у вас есть, но не обращая его, может быть, я сделал неправильный ввод :)
Java Gonzar
@JavaGonzalezArribas Я попробовал первый пример (без переворота), и, кажется, работает нормально. Может быть, вы поставили слишком мало пробелов в первой строке ввода?
Люк Стивенс
Это, вероятно, проблема, отличный ответ :)
Java Gonzar
Предлагаю l+~iвместоl-1-i
floorcat
2

Java 8 , 208 166 157 151 байт

Попытка сделать это, вероятно, может быть лучше: 42 из-за ненужных проверок, -9 удаление переменных, -6 благодаря Люку Стивенсу

Вход является char[][3]

(a)->{int i=2,c,s=0;c=(a[0][0]>32)?1:-1;for(;i<a.length-2;i++){s+=((a[i][1-c]>32?1:0)+(a[i][1+c]>32?2:0))*Math.pow(4,c==1?a.length-i-3:i-2);}return s;}

ungolfed:

int b(char[][] a) {
    int i=2,c,s=0;                      //i for looping, c to check if it's reversed, s is the sum, n the number
    c=(a[0][0]>32)?1:-1; //Check if must be reversed

    for(;i<a.length-2;i++){         //Looping elements

            //(Checking value for 1 + Checking value for 2) * Power, if reversed increasing, else decreasing
        s+=((a[i][1-c]>32?1:0)+(a[i][1+c]>32?2:0))*Math.pow(4,c==1?a.length-i-3:i-2);   
    }
    return s;
}
Ява Гонсар
источник
1
Если вы используете массив символов, а не строки, вы можете проверить наличие | используя> 32 вместо == "|" что экономит 2 байта для каждого использования (всего 6). Вы также можете убрать квадратные скобки при объявлении лямбды еще для двух байтов.
Люк Стивенс
1

Пип , 46 43 42 байта

IsQ@@gg:RV*RVgY^gR'|1(J@UW2*y@2+@y)TM2FB:4

Принимает строки штрих-кода как три аргумента командной строки. Первая и третья строки должны быть дополнены до длины второй строки пробелами. Попробуйте онлайн!

объяснение

Сначала некоторые подготовительные работы:

IsQ@@gg:RV*RVg Y^gR'|1

                        g is cmdline args; s is space (implicit)
IsQ                     If space equals
   @@g                  the first character of the first line, then:
           RVg           Reverse the order of the rows in g
        RV*              then reverse the characters in each row
      g:                 and assign the result back to g
                 gR'|1  In g, replace pipe character with 1
                ^       Split each row into a list of characters
               Y        Yank the result into y

Теперь обратите внимание, что если мы игнорируем среднюю строку и рассматриваем |как 1 и как 0, каждый столбец - это просто 2-битное двоичное число:

(J@UW2*y@2+@y)TM2FB:4

       y@2             Third row
     2*                Multiply by 2, turning 1 into 2 and space into 0
           @y          First row
          +            Add
   UW                  Unweave: creates a list of two lists, the first containing all
                       even-indexed elements (in our case, the actual data), the second
                       containing all odd-indexed elements (the space separators)
  @                    First item of that list
 J                     Join the list of digits into a string
(            )TM2      Trim 2 characters from the beginning and end
                 FB:4  Convert from base 4 (: makes the precedence lower than TM)
                       Autoprint
DLosc
источник
1

Шелуха , 39 38 байт

B4ththmȯ%4+3%5f≠192Ḟz+zṀ·*cN?↔m↔(='|←←

Вводит в виде списка строк: попробуйте онлайн или попробуйте набор тестов!

объяснение

B4ththm(%4+3%5)f≠192Ḟz+zṀ·*cN?↔m↔(='|←←)
                             ?   (='|←←)  -- if the very first character == '|'
                              ↔           --   reverse the lines
                                          -- else
                               m↔         --   reverse each line
                       zṀ·*cN             -- zip the lines with [1,2,3..] under..
                        Ṁ·*c              --   convert each character to its codepoint and multiply by one of [1,2,3]
                    Ḟz+                   -- reduce the lines under zipWith(+) (this sums the columns)

               f≠192                      -- only keep elements ≠ 192 (gets rid of the separating lines)

-- for the example from the challenge we would now have:
--   [652,376,468,652,376,744,376,468,744,652,376]

      m(      )                           -- map the following function
        %4+3%5                            --   λx . ((x % 5) + 3) % 4
-- this gives us: [1,0,2,1,0,3,0,2,3,1,0]
    th                                    -- remove first & last element
  th                                      -- remove first & last element
B4                                        -- interpret as base4 number
ბიმო
источник
0

Октава , 80 75 68 байт

@(b)bi2de({rot90(t=~~(b-32)([3,1],[1:2:end]),2),t}{2-t(2)}(5:end-4))

Попробуйте онлайн!

Любопытно, bi2deчто по умолчанию MSB справа, а не слева, что приводит к некоторым головным болям, пока я делал это ... Я думаю, что у меня должен быть оптимальный способ перевернуть массив перед его индексацией, но есть очень много способов сделать это ( либо в первой индексации, или flipud, fliplr, rot90, '(транспонирование), окончательная индексация ...). Принимает прямоугольный массив с пробелами и |s (поэтому, требуются конечные пробелы)

@(b)                    % Define anonymous function taking input b

t=                      % Inline-define t,
~~(b-32)                % which is the input, converted to 1's and 0's,
([3 1],[1:2:end])       % but only keep the relevant rows (1 and 3 flipped vertically) and columns (only odd) 

{rot90(t,2),t}          % Flip 180 degrees
{2-t(2)                 % depending on whether the second element of t is 1 or 0.}

(5:end-4)               % Flatten array, discarding control bits
bi2de( ... )            % and convert from binary to decimal,
Sanchises
источник
0

JavaScript (ES6), 184 181 байт

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

Функция fпринимает список строк с необходимыми конечными пробелами. Новые строки добавлены в код ниже для ясности (не включены в число байтов).

f=t=>((o=[[...t[0]],[...t[2]]])[0][0]=='|'?o:(z=a=>a.reverse())(o.map(z)))
.map((a,r)=>a.filter((_,i)=>~i%2).map(e=>(1+r)*(e=='|')).slice(2,-2))
.reduce((a,b)=>a+parseInt(b.join``,4),0)

использование

t=['                     ','| | | | | | | | | | |','  |             |   |']
console.log(f(t)) // 4096

Неуправляемая версия с объяснением

// take list of strings, t, as input:
f = t => ( 

  // create output variable o, discard middle row, turn other rows into lists:
  ( o = [ [...t[0]], [...t[2]] ] )

  // if top-left position isn't a pipe, rotate 180 degrees.
  // Alias [].reverse to save 3 bytes :D
  [0][0] == '|' ? o : ( z = a=> a.reverse() )( o.map(z) )

).map( (a,r) => 

  // remove even-numbered positions (non-encoding spaces):
  a.filter( (_,i) => ~i%2 )

  // convert non-pipes into zeros, and pipes into 1 or 2;
  // top row becomes the base4 1-component, bottom row is 2:
  .map( e => (1+r) * (e=='|') ).slice(2,-2)

// convert rows to base4 component strings, then decimal, then sum them:
).reduce( (a,b) => a + parseInt(b.join``,4),0)
Крис М
источник