Штрихкогольф: генерировать UPC номера


12

Почти каждый магазин в настоящее время использует штрих-коды универсального кода продукта (UPC), чтобы упростить процесс оформления заказа. Если имя ничего не значит для вас, вы наверняка узнаете, как они выглядят:

Образец штрих-кода UPC-A

Формат

Наиболее распространенной системой является UPC-A, которая использует 12 цифр для обозначения каждого конкретного продукта. Каждая цифра закодирована в серию черно-белых полос, чтобы машины могли читать код длиной семь битов. Всего имеется 11 шаблонов, которые указывают начало, середину и конец штрих-кода. Это дает общую длину штрих-кода 12 × 7 + 11 = 95 бит. (Отныне, когда двоичный файл используется для обозначения цвета каждого бита, 0он белый и 1черный.)

Начало и конец имеют шаблон 101. Затем цифры делятся на 2 группы по 6 и кодируются, как показано ниже, с шаблоном 01010между левой и правой группами. В этой таблице перечислены шаблоны для каждого номера. Обратите внимание, что шаблон отличается в зависимости от того, находится ли цифра справа или слева (это позволяет сканировать штрих-код вверх ногами). Тем не менее, шаблон для правой стороны противоположен (поменять местами черный на белый и наоборот) от левого.

UPC таблица перевода

Если вы не видите изображение выше, это двоичный эквивалент каждого числа.

#   Left    Right
0   0001101 1110010
1   0011001 1100110
2   0010011 1101100
3   0111101 1000010
4   0100011 1011100
5   0110001 1001110
6   0101111 1010000
7   0111011 1000100
8   0110111 1001000
9   0001011 1110100

пример

Скажем, у вас есть СКП 022000 125033. (Это не случайные числа. Оставьте комментарий, если вы выясните их значимость.) Вы начинаете с этого шаблона, который одинаков в каждом штрих-коде:

101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx01010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx101

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

Разбивка кодировки UPC

Вот вывод в двоичном виде с |трубами, разделяющими части.

101|0001101|0010011|0010011|0001101|0001101|0001101|01010|1100110|1101100|1001110|1110010|1000010|1000010|101

Вызов

Напишите программу, которая выводит штрих-код UPC-A для пользовательского ввода. Размеры изображения должны составлять 95 × 30 пикселей, причем каждый «бит» имеет ширину в один пиксель и высоту 30 пикселей. Черные полосы rgb(0, 0, 0)и белые полосы постоянно прозрачны или rgb(255, 255, 255).

Примечания

  • Возьмите ввод из stdin или командной строки, или напишите функцию, которая принимает строку или целое число (обратите внимание, что ввод может иметь начальные нули, и большинство языков удаляют их или преобразуют число в восьмеричное).
  • Выведите изображение одним из следующих способов:
    • Сохраните его в файл с именем и форматом (PNG, PBM и т. Д.) По вашему выбору.
    • Покажите это на экране.
    • Вывести данные своего файла на стандартный вывод.
  • Вы не можете использовать библиотеки или встроенные программы, которые генерируют штрих-коды ( я смотрю на вас, Mathematica ), хотя вы можете использовать библиотеки изображений или графики.
  • Последняя цифра UPC обычно является контрольной цифрой , но для этих целей вам не нужно беспокоиться об этом.

Примеры

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

Входные данные: 012345678910

Выход:

10100011010011001001001101111010100011011000101010101000010001001001000111010011001101110010101

Входные данные: 777777222222

Выход:

10101110110111011011101101110110111011011101101010110110011011001101100110110011011001101100101

счет

Это код гольфа , поэтому самая короткая подача (в байтах выигрывает). Tiebreaker отправляется на самый ранний пост.


Ммм ... сочные фрукты.
Деннис

Можно ли считать входные данные массивом? например["777777","222222"]
Downgoat

@vihan Хм, я думаю, это немного натянуто. Я собираюсь сказать нет.
NinjaBearMonkey

2
Первый в мире отсканированный штрих-код UPC!
Деннис

1
Это великолепно. Штрих-коды всегда очаровывали меня
Beta Decay

Ответы:


3

CJam, 58 57 байт

'P1N95S30N[A1r:~"rflB\NPDHt":i2fbf=:R6<::!0AAR6>A1]s30*S*

Печатает переносную битовую карту (ASCII) в STDOUT. Попробуйте онлайн.

Как это устроено

'P1N95S30N     e# Push 'P', 1, '\n', 95, ' ', 30 and '\n'.

[              e#
  A1           e#   Push 10 and 1.
  r            e#   Read a token from STDIN.
  :~           e#   Caluate each character ('0' -> 0).
  "rflB\NPDHt" e#   Push that string.
  :i           e#   Cast each character to integer.
               e#   This pushes [114 102 108 66 92 78 80 68 72 116].
  2fb          e#   Convert each integer to base 2.
               e#   This pushes the representations for the right side.
  f=           e#   Select the proper representation of each digit in the input.
  :R           e#   Save the result in R.
  6<           e#   Keep the representations of the first six digits.
  ::!          e#   Negate each binary digit to obtain the "left" representation.
  0AA          e#   Push 0, 10, 10.
  R6>          e#   Push the representations of the last six digits.
  A1           e#   Push 10, 1.
]s             e# Collect in an array and cast to string.

30*            e# Repeat the resulting string 30 times.
S*             e# Join it, using spaces as separators.

4

Ред. 1 BBC BASIC, 155 символов, размер файла 132 байта

INPUTn$
FORi=91TO185p=i MOD2j=i MOD47IFj<42j+=i DIV141*42p=(j>41EORASC(MID$("XLd^bFznvh",VAL(MID$(n$,j/7+1,1))+1)))>>(j MOD7)AND1
IFp LINEi*2,60,i*2,0
NEXT

сэкономил несколько байтов, включив смещение 43 в iцикл. Чтобы избежать взлома, MOD2нужно было добавить еще 47, всего 90.

Это перемещает штрих-код дальше от источника, как показано, если это приемлемо:

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

Версия 0 BBC BASIC, 157 символов ascii, токенизированный размер файла 137 байт

INPUTn$
FORi=1TO95p=i MOD2j=(i+43)MOD47IFj<42j+=i DIV51*42p=(i>50EORASC(MID$("XLd^bFznvh",VAL(MID$(n$,j/7+1,1))+1)))>>(j MOD7)AND1
IFp LINEi*2,0,i*2,60
NEXT

Скачать переводчик можно по адресу http://www.bbcbasic.co.uk/bbcwin/bbcwin.html.

Режим экрана по умолчанию - черный текст на белом фоне. Это отличается от оригинального BBC BASC.

Безголовая версия с тестовой печатью

Расчет строки данных зависит IF j<42и должен быть выполнен в одной строке. В негольфированной версии это делается в три этапа. В версии для гольфа последние два шага объединены в одно огромное выражениеp=...

Мне пришлось изменить порядок битовых карт, потому что я использую >>(j MOD 7)для доступа к битам, что означает, что я сначала получаю доступ к младшему значащему биту. Как только это сделано, все левые растровые изображения удобно находятся в диапазоне ASCII.

  INPUTn$
  FOR i=1TO95                            :REM iterate through 95 bars
    p=i MOD2                             :REM calculate colour of format bar 1=black
    j=(i+43)MOD47                        :REM repetition is 42 data bars + 5 format bars. offset and modulo. if j<42 it is a data bar and we must change p.

    REM if i DIV 51=1 we are in the second half, so add 42 to j. Find the bitmap for left hand value, from character j/7 of the input.
    REM i>50 evaluates to false=0 true=-1. XOR this with p to invert bitmap for right hand side. Shift and AND with 1.  
    IF j<42 j+=i DIV51*42:p=ASC(MID$("XLd^bFznvh",  VAL(MID$(n$,j/7+1,1))+1  )) :p=(i>50EORp)>>(j MOD7) AND 1

    IF j MOD 7 = 0 PRINT                  :REM format test output
    PRINT ;p;                             :REM print test output
    IF p LINEi*2-2,0,i*2-2,60             :REM if p=1 plot bar. there are 2 logical units for each pixel.
  NEXT

Типичный вывод, версия без присмотра, с тестовым выводом

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


2

JavaScript ES6, 225 байт

s=>`P1
30 90
`+([...`101${(f=(z,j)=>[...j].map(i=>`000${z[+i].toString(2)}`.slice(-7)).join``)([13,25,19,61,35,49,47,59,55,11],s[0])}01010${f([114,102,108,66,92,78,80,68,72,116],s[1])}101`].join` `+`
`).repeat(30).slice(0,-1)

Может быть, короче с функциями ES7, но я не уверен насчет их поддержки, поэтому я придерживаюсь ES6. Я также предполагаю ввод в виде массива. Вывод представляет собой файл PBN . Есть также много игры в гольф.

Если я что-то сделал не так, оставьте комментарий, и я обязательно исправлю


Я думаю, что вы имеете в виду файл PBM ...
sergiol

2

Perl, 153 байта

substr($_=<>,6,0)=A;y/0-9A/=ICmSa_kg;0/;$s.=sprintf("%07b",-48+ord$1^($k++>6?127:0))while/(.)/g;$s=~s/0{7}/01010/;print"P1
95 30
".('101'.$s.'101'.$/)x30

Скопируйте в файл barcode.perl и запустите так:

perl barcode.perl > output.pbm

затем введите номер штрих-кода.

Объяснение:

Битовые комбинации для цифр штрих-кода хранятся в строке и заменяются входными цифрами с помощью y///оператора транслитерации Perl . Каждое значение в строке подстановки имеет 48 (ASCII '0'), добавленных из него, чтобы избежать непечатаемых символов. Цифры во второй половине штрих-кода являются обратными цифрам в первой половине.

Центральный шаблон установлен на 0000000 (шаблон, который в противном случае никогда не появится, кодируется как «A», а затем «0»), а затем заменяется 01010 вместо обработки его другой длины в качестве особого случая при использовании sprint.


1

Октава, 115 байт

function b(s)
n='rflB\MPDHt'-0;r=dec2bin(n(s-47)',7)'(:)-48;v=[a=[1 0 1] ~r(1:42)' 0 a r(43:84)' a];v(ones(30,1),:)

Многострочная версия:

function b(s)
   n='rflB\MPDHt'-0;
   r=dec2bin(n(s-47)',7)'(:)-48;
   v=[a=[1 0 1] ~r(1:42)' 0 a r(43:84)' a];
   v(ones(30,1),:)

nявляется ASCII-эквивалентом цифровых кодов с правой стороны (их было легче ввести, чем с левой стороны, поскольку все они были отображаемыми символами). После этого прямое десятичное преобразование в двоичное с некоторым раздражающим типом меняется с char на numeric. vстроит окончательную двоичную строку, а затем мы повторяем ее 30 раз и выводим на консоль.

Пример выходных данных только для 2 из 30 строк, показанных для краткости:

s = '777777222222';
ans =

 Columns 1 through 30:

   1   0   1   0   1   1   1   0   1   1   0   1   1   1   0   1   1   0   1   1   1   0   1   1   0   1   1   1   0   1
   1   0   1   0   1   1   1   0   1   1   0   1   1   1   0   1   1   0   1   1   1   0   1   1   0   1   1   1   0   1
...

 Columns 31 through 60:

   1   0   1   1   1   0   1   1   0   1   1   1   0   1   1   0   1   0   1   1   1   0   1   1   0   0   1   1   0   1
   1   0   1   1   1   0   1   1   0   1   1   1   0   1   1   0   1   0   1   1   1   0   1   1   0   0   1   1   0   1
...

 Columns 61 through 90:

   1   0   0   1   1   0   1   1   0   0   1   1   0   1   1   0   0   1   1   0   1   1   0   0   1   1   0   1   1   0
   1   0   0   1   1   0   1   1   0   0   1   1   0   1   1   0   0   1   1   0   1   1   0   0   1   1   0   1   1   0
...

 Columns 91 through 94:

   0   1   0   1
   0   1   0   1
...

Сжатый выход:

1010111011011101101110110111011011101101110110101110110011011001101100110110011011001101100101

Первоначально я намеревался отобразить изображение, но отправка вывода на консоль сэкономила мне 9 байт. Вы можете отобразить результаты, используя imshow, но они отображаются 1белым и 0черным, поэтому вам нужно сначала инвертировать данные.

imshow(~v(ones(30,1),:));

1

Кобра - 218

do(s='')
    print'P1\n95 30'+('\n'+('101'+(for n in 12get Convert.toString(if((t=139+[2,14,8,50,24,38,36,48,44,0][s[n]to int-48])and n<6,t,~t),2)[-7:]+if(n-5,'','01010')).join('')+'101').toCharArray.join(' ')).repeat(30)

1

Javascript ES6, 199 байт

n=>`P1 95 30 `+(101+(g=(a,...s)=>(``+1e12+n).slice(...s,-6).split``.map(m=>(1e3+a[m].toString(2)).slice(-7)).join``)(a=[13,25,19,61,35,49,47,59,55,11],-12)+`01010`+g(a.map(i=>~i&127))+101).repeat(30)

msgstr "самая короткая подача (в байтах выигрывает)". Вам нужно посчитать ваш код в байтах, поэтому, если я использую Unicode, я думаю, это 2 байта на символ.
mbomb007

Бах, да, я думаю, что мой нешифрованный ответ короче
Дендробиум

0

Python 2, 174 байта

Я знаю, это можно сыграть в гольф.

Строка s- это двоичная таблица в вопросе с левой половиной таблицы в качестве левой половины строки. Сначала значения И делятся на 63, если они находятся в правой половине (сначала удалите 1), а затем сдвигаются на 63 для печати в формате ASCII.

BUG: в настоящее время пытаюсь исправить ошибку. Вывод первого примера отключен на одну цифру штрих-кода. Если вы поймете, дайте мне знать, пожалуйста.

I=raw_input()
s="LXR|bpnzvJcekA[MOCGs"
x="".join(format(ord(s[int(I[i])+10*(i>5)])-63|1+63*(i>5),'07b')for i in range(len(I)))
L=len(x)/2
print"101%s01010%s101"%(x[:L],x[L:])

Или я сделал вызов совершенно неправильно. Дайте мне знать в этом случае тоже.
mbomb007
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.