Barcodegolf: genera un UPC di un numero


12

Oggi quasi tutti i negozi utilizzano codici a barre UPC ( Universal Product Code ) per semplificare il processo di checkout. Se il nome non significa nulla per te, riconoscerai sicuramente come sono:

Codice a barre UPC-A di esempio

Formato

Il sistema più comune è UPC-A, che utilizza 12 cifre per rappresentare ciascun prodotto specifico. Ogni cifra è codificata in una serie di strisce bianche e nere per consentire alle macchine di leggere il codice, una lunghezza di sette bit. Ci sono un totale di 11 bit di pattern che indicano l'inizio, la metà e la fine del codice a barre. Questo arriva a una lunghezza totale del codice a barre di 12 × 7 + 11 = 95 bit. (D'ora in poi, quando binario viene utilizzato per fare riferimento al colore di ciascun bit, 0è bianco ed 1è nero.)

L'inizio e la fine hanno entrambi uno schema di 101. Le cifre vengono quindi divise in 2 gruppi di 6 e codificate come mostrato di seguito, con uno schema 01010tra i gruppi sinistro e destro. Questa tabella elenca il modello per ciascun numero. Si noti che il motivo è diverso a seconda che la cifra si trovi sul lato destro o sinistro (ciò consente di scansionare il codice a barre sottosopra). Tuttavia, il motivo per la destra è l'opposto (scambia il nero per il bianco e viceversa) di quello della sinistra.

Tabella di conversione UPC

Se non riesci a vedere l'immagine sopra, questo è l'equivalente binario di ogni numero.

#   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

Esempio

Supponi di avere l'UPC 022000 125033. (Questi non sono numeri casuali. Lascia un commento se ne capisci il significato.) Inizi con questa piastra della caldaia che è la stessa in ogni codice a barre:

101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx01010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx101

Per le cifre, si sostituisce ciascuna con la codifica corrispondente per il lato (sinistro o destro) che è attivo. Se sei ancora confuso, vedi l'immagine qui sotto.

Analisi della codifica UPC

Ecco l'output in binario con |tubi che separano le parti.

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

Sfida

Scrivi un programma che emette il codice a barre UPC-A per l'input dell'utente. Le dimensioni dell'immagine dovrebbero essere 95 × 30 pixel, con ogni "bit" largo 1 pixel e alto 30 pixel. Le strisce nere sono dentro rgb(0, 0, 0)e le strisce bianche sono costantemente trasparenti o rgb(255, 255, 255).

Appunti

  • Prendi l'input da stdin o dalla riga di comando o scrivi una funzione che accetta una stringa o un numero intero (nota che l'input può avere zero iniziali e la maggior parte delle lingue li rimuove o converte il numero in ottale).
  • Stampa l'immagine in uno dei seguenti modi:
    • Salvalo in un file con un nome e un formato (PNG, PBM, ecc.) A tua scelta.
    • Visualizzalo sullo schermo.
    • Emette i dati del suo file su stdout.
  • Non puoi usare librerie o builtin che generano codici a barre ( ti sto guardando, Mathematica ), sebbene tu possa usare librerie di immagini o grafiche.
  • L'ultima cifra di un UPC è di solito una cifra di controllo , ma per questi scopi non devi preoccuparti.

Esempi

Ecco alcuni altri esempi con cui testare il tuo codice. L'output binario viene anche fornito per comodità.

Ingresso: 012345678910

Produzione:

10100011010011001001001101111010100011011000101010101000010001001001000111010011001101110010101

Ingresso: 777777222222

Produzione:

10101110110111011011101101110110111011011101101010110110011011001101100110110011011001101100101

punteggio

Questo è il golf del codice , quindi l'invio più breve (in byte vince). Tiebreaker arriva al primo post.


Mmm ... frutto succoso.
Dennis,

L'ingresso può essere preso come un array? ad es.["777777","222222"]
Downgoat,

@vihan Hmm, penso che sia un po 'allungato. Sto per dire di no.
NinjaBearMonkey il

2
Il primo codice a barre UPC scansionato di sempre!
Dennis,

1
È brillante. I codici a barre mi hanno sempre affascinato
decadimento della beta il

Risposte:


3

CJam, 58 57 byte

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

Stampa una BitMap portatile (ASCII) su STDOUT. Provalo online.

Come funziona

'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

Rev 1 BBC BASIC, 155 caratteri ASCII, dimensione file tokenizzata 132 byte

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

salvato alcuni byte incorporando l'offset di 43 nel iloop. Al fine di evitare la rottura, è MOD2stato aggiunto un ulteriore 47 per un totale di 90.

Questo sposta il codice a barre più lontano dall'origine, come mostrato, se questo è accettabile:

inserisci qui la descrizione dell'immagine

Rev 0 BBC BASIC, 157 caratteri ASCII, dimensione file tokenizzata 137 byte

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

Scarica l'interprete su http://www.bbcbasic.co.uk/bbcwin/bbcwin.html

La modalità schermo predefinita è testo nero su sfondo bianco. Ciò differisce dall'originale BBC BASC.

Versione non golfata con stampa di prova

Il calcolo di una barra dei dati dipende IF j<42e deve essere eseguito su una riga. Nella versione non golfata si fa in tre passaggi. Nella versione golfata gli ultimi due passaggi sono combinati in un'unica grande espressionep=...

Ho dovuto invertire l'ordine delle bitmap, perché utilizzo >>(j MOD 7)per accedere ai bit, il che significa che accedo prima al bit meno significativo. Fatto ciò, tutte le bitmap di sinistra sono comodamente nell'intervallo 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

Uscita tipica, versione non modificata, con uscita di prova

inserisci qui la descrizione dell'immagine


2

JavaScript ES6, 225 byte

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)

Potrebbe essere stato più breve con le funzionalità di ES7, ma non sono sicuro del loro supporto, quindi sto con ES6. Sto anche assumendo un input come un array. L'output è un file PBN . C'è anche un sacco di golf da fare.

Se ho fatto qualcosa di sbagliato, lascia un commento e sarò sicuro di risolverlo


Penso che intendi il file PBM ...
sergiol,

2

Perl, 153 byte

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

Copia in un file barcode.perl e quindi esegui in questo modo:

perl barcode.perl > output.pbm

quindi inserire il numero del codice a barre.

Spiegazione:

I modelli di bit per le cifre del codice a barre sono memorizzati in una stringa e sostituiti con le cifre di input utilizzando l' y///operatore di traslitterazione Perl . Ogni valore nella stringa di sostituzione ha 48 (ASCII '0') aggiunti per evitare caratteri non stampabili. Le cifre nella seconda metà del codice a barre sono inverse di quelle nella prima metà.

Il modello centrale è impostato su 0000000 (un modello che altrimenti non può mai apparire, codificato come 'A' e quindi '0') e quindi sostituito con 01010 anziché gestirne la diversa lunghezza come caso speciale durante l' sprinting.


1

Ottava, 115 byte

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

Versione multilinea:

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è l'equivalente ASCII dei codici delle cifre sul lato destro (erano più facili da inserire rispetto al lato sinistro in quanto erano tutti caratteri visualizzabili). Dopodiché, una conversione decimale-binaria diretta con alcuni tipi fastidiosi passa da char a numerico. vcostruisce la stringa binaria finale e quindi la ripetiamo 30 volte e l'output sulla console.

Esempio di output con solo 2 delle 30 righe visualizzate per brevità:

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

Uscita compressa:

1010111011011101101110110111011011101101110110101110110011011001101100110110011011001101100101

Inizialmente avevo intenzione di visualizzare l'immagine, ma l'invio di output alla console mi ha salvato 9 byte. Puoi visualizzare i risultati usando imshow, ma viene visualizzato 1come bianco e 0nero, quindi devi prima invertire i dati.

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

1

Cobra - 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 byte

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)

"l'invio più breve (in byte vince)". Devi contare il tuo codice in byte, quindi penso che se usi Unicode sono 2 byte per carattere.
mbomb007,

Bah, sì, immagino che la mia risposta non codificata sia più breve di allora
Dendrobium

0

Python 2, 174 byte

So che può essere giocato a golf.

La stringa sè la tabella binaria nella domanda con la metà sinistra della tabella come metà sinistra della stringa. I valori sono ANDed di 63 prima se nella metà destra (rimuovi la prima 1), quindi spostati di 63 per essere ASCII stampabile.

ERRORE: Attualmente sto cercando di correggere un bug. L'output del primo esempio è disattivato di una cifra del codice a barre. Se lo capisci, fammi sapere per favore.

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

Oppure, ho fatto la sfida completamente sbagliata. Fammi sapere anche in quel caso.
mbomb007,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.