Barcodegolf: generar un UPC de un número

12

En la actualidad, casi todas las tiendas utilizan códigos de barras del Código de producto universal (UPC) para simplificar el proceso de pago. Si el nombre no significa nada para ti, seguramente reconocerás cómo se ven:

Muestra de código de barras UPC-A

Formato

El sistema más común es UPC-A, que utiliza 12 dígitos para representar cada producto específico. Cada dígito se codifica en una serie de franjas en blanco y negro para permitir que las máquinas lean el código, una longitud de siete bits. Hay un total de 11 bits de patrones que indican el comienzo, el medio y el final del código de barras. Esto llega a una longitud total de código de barras de 12 × 7 + 11 = 95 bits. (De ahora en adelante, cuando el binario se usa para referirse al color de cada bit, 0es blanco y 1es negro).

El principio y el final tienen un patrón de 101. Los dígitos se dividen en 2 grupos de 6 y se codifican como se muestra a continuación, con un patrón 01010entre los grupos izquierdo y derecho. Esta tabla enumera el patrón para cada número. Tenga en cuenta que el patrón es diferente dependiendo de si el dígito está en el lado derecho o izquierdo (esto permite escanear el código de barras al revés). Sin embargo, el patrón de la derecha es el opuesto (cambiar negro por blanco y viceversa) del de la izquierda.

Tabla de conversión UPC

Si no puede ver la imagen de arriba, este es el equivalente binario de cada número.

#   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

Ejemplo

Digamos que tienes la UPC 022000 125033. (Esos no son números aleatorios. Deja un comentario si descubres su importancia). Empiezas con este repetitivo que es el mismo en cada código de barras:

101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx01010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx101

Para los dígitos, reemplaza cada uno con la codificación correspondiente para el lado (izquierdo o derecho) en el que está activado. Si aún estás confundido, mira la imagen a continuación.

Desglose de la codificación UPC

Aquí está la salida en binario con |tuberías que separan las partes.

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

Desafío

Escriba un programa que genere el código de barras UPC-A para la entrada del usuario. Las dimensiones de la imagen deben ser 95 × 30 píxeles, con cada "bit" de un píxel de ancho y 30 píxeles de alto. Las rayas negras están adentro rgb(0, 0, 0)y las rayas blancas son consistentemente transparentes o rgb(255, 255, 255).

Notas

  • Tome la entrada de stdin o la línea de comando, o escriba una función que tome una cadena o un entero (tenga en cuenta que la entrada puede tener ceros a la izquierda, y la mayoría de los idiomas los eliminan o convierten el número a octal).
  • Imprima la imagen de una de las siguientes maneras:
    • Guárdelo en un archivo con un nombre y formato (PNG, PBM, etc.) de su elección.
    • Visualízalo en la pantalla.
    • Salida de sus datos de archivo a stdout.
  • No puede usar bibliotecas o archivos integrados que generen códigos de barras ( lo estoy mirando a usted, Mathematica ), aunque puede usar bibliotecas de imágenes o gráficos.
  • El último dígito de un UPC suele ser un dígito de verificación , pero para estos fines no tiene que preocuparse por ello.

Ejemplos

Aquí hay algunos ejemplos más para probar su código. La salida binaria también se proporciona por conveniencia.

Entrada: 012345678910

Salida:

10100011010011001001001101111010100011011000101010101000010001001001000111010011001101110010101

Entrada: 777777222222

Salida:

10101110110111011011101101110110111011011101101010110110011011001101100110110011011001101100101

Puntuación

Este es el código de golf , por lo que el envío más corto (en bytes gana). Tiebreaker va al primer mensaje.

NinjaOsoMono
fuente
Mmm ... fruta jugosa.
Dennis
¿Se puede tomar la entrada como una matriz? Por ejemplo["777777","222222"]
Downgoat
@vihan Hmm, creo que es un poco exagerado. Voy a decir que no
NinjaBearMonkey
2
Primer código de barras UPC escaneado
Dennis
1
Esto es brillante. Los códigos de barras siempre me han fascinado
Beta Decay

Respuestas:

3

CJam, 58 57 bytes

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

Imprime un mapa de bits portátil (ASCII) en STDOUT. Pruébalo en línea.

Cómo funciona

'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
fuente
4

Rev 1 BBC BASIC, 155 caracteres ascii, tamaño de archivo tokenizado 132 bytes

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

ahorró algunos bytes al incorporar el desplazamiento de 43 en el ibucle. Para evitar la ruptura, se MOD2tuvieron que agregar 47 adicionales para un total de 90.

Esto mueve el código de barras más lejos del origen, como se muestra, si eso es aceptable:

ingrese la descripción de la imagen aquí

Rev 0 BBC BASIC, 157 caracteres ascii, tamaño de archivo tokenizado 137 bytes

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

Descargue el intérprete en http://www.bbcbasic.co.uk/bbcwin/bbcwin.html

El modo de pantalla predeterminado es texto negro sobre un fondo blanco. Esto difiere de la BBC BASC original.

Versión sin golf con impresión de prueba

El cálculo de una barra de datos depende IF j<42y debe hacerse todo en una línea. En la versión sin golf, se realiza en tres pasos. En la versión de golf, los dos últimos pasos se combinan en una sola gran expresión.p=...

Tuve que invertir el orden de los mapas de bits, porque uso >>(j MOD 7)para acceder a los bits, lo que significa que primero accedo al bit menos significativo. Una vez hecho esto, todos los mapas de bits izquierdos están convenientemente en el rango 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

Salida típica, versión no protegida, con salida de prueba

ingrese la descripción de la imagen aquí

Level River St
fuente
2

JavaScript ES6, 225 bytes

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)

Podría haber sido más corto con las características de ES7, pero no estoy seguro de su soporte, así que me quedo con ES6. También estoy asumiendo una entrada como una matriz. La salida es un archivo PBN . También hay mucho golf para hacer.

Si hice algo mal, deje un comentario y me aseguraré de arreglarlo

Downgoat
fuente
Creo que te refieres al archivo PBM ...
sergiol
2

Perl, 153 bytes

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

Copie a un archivo barcode.perl y luego ejecútelo así:

perl barcode.perl > output.pbm

luego ingrese el número del código de barras.

Explicación:

Los patrones de bits para los dígitos del código de barras se almacenan en una cadena y se sustituyen por los dígitos de entrada utilizando el y///operador de transliteración Perl . Cada valor en la cadena de sustitución tiene 48 (ASCII '0') agregado para evitar caracteres no imprimibles. Los dígitos en la segunda mitad del código de barras son inversos de los de la primera mitad.

El patrón central se establece en 0000000 (un patrón que de otra manera nunca podría aparecer, codificado como 'A' y luego '0') y luego sustituido con 01010 en lugar de manejar su longitud diferente como un caso especial cuando sprinting.

samgak
fuente
1

Octava, 115 bytes

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

Versión multilínea:

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

nes el equivalente ASCII de los códigos de dígitos del lado derecho (eran más fáciles de ingresar que el lado izquierdo, ya que todos eran caracteres que se pueden mostrar). Después de eso, una conversión directa de decimal a binario con algunos tipos molestos cambia de char a numérico. vconstruye la cadena binaria final y luego la repetimos 30 veces y la enviamos a la consola.

Ejemplo de salida con solo 2 de las 30 filas que se muestran por brevedad:

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

Salida comprimida:

1010111011011101101110110111011011101101110110101110110011011001101100110110011011001101100101

Originalmente tenía la intención de mostrar la imagen, pero el envío de resultados a la consola me ahorró 9 bytes. Puede mostrar los resultados usando imshow, pero se muestra 1en blanco y 0en negro, por lo que primero debe invertir los datos.

imshow(~v(ones(30,1),:));
cubilete
fuente
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)
Οurous
fuente
1

Javascript ES6, 199 bytes

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
fuente
"el envío más corto (en bytes gana)". Debe contar su código en bytes, por lo que si usa Unicode, creo que son 2 bytes por carácter.
mbomb007
Bah, sí, supongo que mi respuesta sin codificar es más corta que entonces
Dendrobium
0

Python 2, 174 bytes

Sé que se puede jugar al golf.

La cadena ses la tabla binaria en la pregunta con la mitad izquierda de la tabla como la mitad izquierda de la cadena. Los valores son AND por 63 primero si están en la mitad derecha (elimine primero 1), luego se desplazan por 63 para ser ASCII imprimible.

ERROR: Actualmente estoy tratando de corregir un error. La salida del primer ejemplo está desactivada por un dígito del código de barras. Si lo resuelves, avísame por favor.

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
fuente
O bien, he hecho el desafío completamente mal. Déjame saber en ese caso también.
mbomb007