Barcodegolf: Wygeneruj UPC liczby

12

Prawie każdy sklep używa obecnie kodów kreskowych Universal Product Code (UPC), aby uprościć proces sprawdzania. Jeśli imię nic dla ciebie nie znaczy, na pewno rozpoznasz ich wygląd:

Przykładowy kod kreskowy UPC-A

Format

Najpopularniejszym systemem jest UPC-A, który używa 12 cyfr do przedstawienia każdego konkretnego produktu. Każda cyfra jest zakodowana w szereg czarno-białych pasków, aby umożliwić maszynom odczytanie kodu o długości siedmiu bitów. Istnieje w sumie 11 bitów wzorów, które wskazują początek, środek i koniec kodu kreskowego. Dochodzi do całkowitej długości kodu kreskowego 12 × 7 + 11 = 95 bitów. (Od teraz, gdy binarny jest używany do odniesienia do koloru każdego bitu, 0jest biały i 1jest czarny).

Zarówno początek, jak i koniec mają wzór 101. Cyfry są następnie dzielone na 2 grupy po 6 i kodowane, jak pokazano poniżej, wzorem 01010między grupami lewą i prawą. W tej tabeli wymieniono wzór dla każdej liczby. Należy pamiętać, że wzór różni się w zależności od tego, czy cyfra znajduje się po prawej czy lewej stronie (umożliwia to skanowanie kodu kreskowego do góry nogami). Jednak wzór dla prawej jest odwrotny (zamień czarny na biały i odwrotnie) dla lewego.

Tabela konwersji UPC

Jeśli nie widzisz powyższego obrazu, jest to binarny odpowiednik każdej liczby.

#   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

Przykład

Powiedz, że masz UPC 022000 125033. (To nie są liczby losowe. Zostaw komentarz, jeśli zrozumiesz ich znaczenie.) Zaczynasz od tej tablicy, która jest taka sama w każdym kodzie kreskowym:

101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx01010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx101

W przypadku cyfr każdy z nich zastępuje się odpowiednim kodowaniem dla strony (lewej lub prawej), na której jest włączony. Jeśli nadal jesteś zdezorientowany, zobacz poniższy obrazek.

Podział kodowania UPC

Oto wynik w postaci binarnej z |rurami oddzielającymi części.

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

Wyzwanie

Napisz program, który wyprowadza kod kreskowy UPC-A do wprowadzenia przez użytkownika. Wymiary obrazu powinny wynosić 95 × 30 pikseli, przy czym każdy „bit” ma szerokość jednego piksela i wysokość 30 pikseli. Czarne paski są w, rgb(0, 0, 0)a białe paski są konsekwentnie przezroczyste lub rgb(255, 255, 255).

Notatki

  • Weź dane wejściowe ze standardowego wiersza poleceń lub wiersza poleceń albo napisz funkcję, która pobiera ciąg lub liczbę całkowitą (zwróć uwagę, że dane wejściowe mogą mieć zera na początku, a większość języków je usuwa lub zamienia liczbę na ósemkową).
  • Wyjście obrazu w jeden z następujących sposobów:
    • Zapisz go do wybranego pliku o nazwie i formacie (PNG, PBM itp.).
    • Wyświetl go na ekranie.
    • Wyjście danych pliku na standardowe wyjście.
  • Nie możesz używać bibliotek lub wbudowanych kodów generujących kody kreskowe ( patrzę na ciebie, Mathematica ), chociaż możesz używać bibliotek graficznych lub graficznych.
  • Ostatnia cyfra UPC jest zwykle cyfrą kontrolną , ale w tych celach nie musisz się o to martwić.

Przykłady

Oto kilka przykładów testowania kodu. Wyjście binarne podano również dla wygody.

Wejście: 012345678910

Wynik:

10100011010011001001001101111010100011011000101010101000010001001001000111010011001101110010101

Wejście: 777777222222

Wynik:

10101110110111011011101101110110111011011101101010110110011011001101100110110011011001101100101

Punktacja

To jest kod golfowy , więc wygrywa najkrótsza przesyłka (w bajtach). Tiebreaker przechodzi do najwcześniejszego postu.

NinjaBearMonkey
źródło
Mmm ... soczyste owoce.
Dennis
Czy dane wejściowe można traktować jako tablicę? np.["777777","222222"]
Downgoat
@vihan Hmm, myślę, że to trochę skomplikowane. Powiem nie.
NinjaBearMonkey
2
Pierwszy zeskanowany kod kreskowy UPC w historii!
Dennis,
1
To jest genialne. Kody kreskowe zawsze mnie fascynowały
Beta Decay

Odpowiedzi:

3

CJam, 58 57 bajtów

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

Drukuje Portable BitMap (ASCII) do STDOUT. Wypróbuj online.

Jak to działa

'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.
Dennis
źródło
4

Rev 1 BBC BASIC, 155 znaków ascii, tokenizowane rozmiary plików 132 bajty

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

zaoszczędził kilka bajtów, wprowadzając przesunięcie 43 w ipętli. Aby uniknąć zerwania, MOD2konieczne było dodanie dodatkowych 47 w sumie 90.

To przesuwa kod kreskowy dalej od źródła, jak pokazano, jeśli jest to dopuszczalne:

wprowadź opis zdjęcia tutaj

Rev 0 BBC BASIC, 157 znaków ascii, tokenizowane rozmiary plików 137 bajtów

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

Pobierz tłumacza na http://www.bbcbasic.co.uk/bbcwin/bbcwin.html

Domyślnym trybem ekranu jest czarny tekst na białym tle. Różni się od oryginalnego BBC BASC.

Wersja bez golfa z nadrukiem testowym

Obliczanie paska danych zależy IF j<42i musi być wykonane w jednym wierszu. W wersji bez golfa odbywa się to w trzech krokach. W wersji golfowej dwa ostatnie kroki są połączone w jedną wielką ekspresjęp=...

Musiałem odwrócić kolejność map bitowych, ponieważ używam >>(j MOD 7)do uzyskania dostępu do bitów, co oznacza, że ​​najpierw uzyskuję dostęp do najmniej znaczącego bitu. Po zakończeniu wszystkie lewe mapy bitowe są dogodnie w zakresie 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

Typowe wyjście, wersja bez golfa, z wyjściem testowym

wprowadź opis zdjęcia tutaj

Level River St
źródło
2

JavaScript ES6, 225 bajtów

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)

Mogło być krótsze z funkcjami ES7, ale nie jestem pewien ich obsługi, więc trzymam się ES6. Przyjmuję również dane wejściowe jako tablicę. Dane wyjściowe to plik PBN . Jest też wiele do gry w golfa.

Jeśli zrobiłem coś złego, zostaw komentarz i na pewno to naprawię

Downgoat
źródło
Myślę, że masz na myśli plik PBM ...
sergiol,
2

Perl, 153 bajty

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

Skopiuj do pliku barcode.perl, a następnie uruchom w następujący sposób:

perl barcode.perl > output.pbm

następnie wprowadź numer kodu kreskowego.

Wyjaśnienie:

Wzory bitów dla cyfr kodu kreskowego są przechowywane w ciągu i zastępowane cyframi wejściowymi za pomocą y///operatora transliteracji Perl . Każda wartość w ciągu podstawiania ma 48 (ASCII „0”), aby uniknąć znaków niedrukowalnych. Cyfry w drugiej połowie kodu kreskowego są odwrotnymi do tych z pierwszej połowy.

Centralny wzorzec jest ustawiony na 0000000 (wzorzec, który inaczej nie mógłby się pojawić, zakodowany jako „A”, a następnie „0”), a następnie zastąpiony 01010 zamiast obsługiwać jego inną długość jako specjalny przypadek podczas sprinting.

samgak
źródło
1

Oktawa, 115 bajtów

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),:)

Wersja wieloliniowa:

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),:)

njest odpowiednikiem ASCII kodów cyfr po prawej stronie (były łatwiejsze do wprowadzenia niż lewa strona, ponieważ wszystkie były znakami wyświetlanymi). Następnie prosta konwersja dziesiętna na dwójkową z pewnymi irytującymi typami zmienia się z char na numeryczną. vbuduje końcowy ciąg binarny, a następnie powtarzamy go 30 razy i wysyłamy do konsoli.

Przykładowe dane wyjściowe zawierające tylko 2 z 30 wierszy pokazanych w celu skrócenia:

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

Skompresowana moc wyjściowa:

1010111011011101101110110111011011101101110110101110110011011001101100110110011011001101100101

Początkowo zamierzałem wyświetlić obraz, ale wysłanie danych wyjściowych do konsoli pozwoliło mi zaoszczędzić 9 bajtów. Możesz wyświetlić wyniki za pomocą imshow, ale wyświetla się 1jako biały i 0czarny, więc najpierw musisz odwrócić dane.

imshow(~v(ones(30,1),:));
zlewka
źródło
1

Kobra - 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)
Obrzydliwe
źródło
1

JavaScript ES6, 199 bajtów

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)
Dendrobium
źródło
„najkrótsze przesłanie (w bajtach wygrywa)”. Musisz policzyć swój kod w bajtach, więc myślę, że jeśli używasz Unicode, to 2 bajty na znak.
mbomb007,
Ach, tak, chyba moja jednoznaczna odpowiedź jest krótsza
Dendrobium,
0

Python 2, 174 bajty

Wiem, że można grać w golfa.

Ciąg sjest tabelą binarną w pytaniu z lewą połową stołu jako lewą połową ciągu. Wartości są najpierw ANDowane przez 63, jeśli znajdują się w prawej połowie (usuń pierwszy 1), a następnie są przesuwane o 63, aby nadawać się do wydruku ASCII.

BŁĄD: Aktualnie próbuję naprawić błąd. Wyjście pierwszego przykładu jest wyłączone przez jedną cyfrę kodu kreskowego. Jeśli to wymyślisz, daj mi znać.

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
źródło
Albo zrobiłem wyzwanie całkowicie źle. Daj mi znać również w tym przypadku.
mbomb007,