Barcodegolf: Générez l'UPC d'un numéro

12

Aujourd'hui, presque tous les magasins utilisent des codes-barres UPC ( Universal Product Code ) pour simplifier le processus de vérification. Si le nom ne vous dit rien, vous reconnaîtrez sûrement à quoi il ressemble:

Exemple de code-barres UPC-A

Format

Le système le plus courant est UPC-A, qui utilise 12 chiffres pour représenter chaque produit spécifique. Chaque chiffre est codé en une série de bandes noires et blanches pour permettre aux machines de lire le code, une longueur de sept bits. Il existe un total de 11 bits de motifs qui indiquent le début, le milieu et la fin du code-barres. Cela donne une longueur totale de code-barres de 12 × 7 + 11 = 95 bits. (Désormais, lorsque binaire est utilisé pour faire référence à la couleur de chaque bit, il 0est blanc et 1noir.)

Le début et la fin ont tous deux un motif de 101. Les chiffres sont ensuite divisés en 2 groupes de 6 et codés comme indiqué ci-dessous, avec un motif 01010entre les groupes gauche et droit. Ce tableau répertorie le modèle de chaque numéro. Notez que le motif est différent selon que le chiffre se trouve à droite ou à gauche (cela permet de scanner le code-barres à l'envers). Cependant, le motif pour la droite est l'opposé (permuter le noir pour le blanc et vice versa) de celui de la gauche.

Table de conversion UPC

Si vous ne voyez pas l'image ci-dessus, c'est l'équivalent binaire de chaque numéro.

#   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

Exemple

Disons que vous avez l'UPC 022000 125033. (Ce ne sont pas des nombres aléatoires. Laissez un commentaire si vous comprenez leur signification.) Vous commencez avec ce passe-partout qui est le même dans chaque code-barres:

101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx01010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx101

Pour les chiffres, vous remplacez chacun par le codage correspondant pour le côté (gauche ou droit) sur lequel il est activé. Si vous êtes toujours confus, voyez l'image ci-dessous.

Répartition du codage UPC

Voici la sortie en binaire avec des |tuyaux séparant les pièces.

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

Défi

Écrivez un programme qui sort le code-barres UPC-A pour l'entrée utilisateur. Les dimensions de l'image doivent être de 95 × 30 pixels, chaque "bit" ayant une largeur d'un pixel et une hauteur de 30 pixels. Les rayures noires sont dedans rgb(0, 0, 0)et les rayures blanches sont toujours transparentes ou rgb(255, 255, 255).

Remarques

  • Prenez l'entrée de stdin ou de la ligne de commande, ou écrivez une fonction qui prend une chaîne ou un entier (notez que l'entrée peut avoir des zéros en tête, et la plupart des langues les suppriment ou convertissent le nombre en octal).
  • Générez l'image de l'une des manières suivantes:
    • Enregistrez-le dans un fichier avec un nom et un format (PNG, PBM, etc.) de votre choix.
    • Affichez-le à l'écran.
    • Exporte ses données de fichier vers stdout.
  • Vous ne pouvez pas utiliser de bibliothèques ou de commandes intégrées qui génèrent des codes-barres ( je vous regarde, Mathematica ), bien que vous puissiez utiliser des bibliothèques d'images ou de graphiques.
  • Le dernier chiffre d'un CUP est généralement un chiffre de contrôle , mais à ces fins, vous n'avez pas à vous en soucier.

Exemples

Voici quelques exemples supplémentaires pour tester votre code. La sortie binaire est également donnée pour plus de commodité.

Contribution: 012345678910

Production:

10100011010011001001001101111010100011011000101010101000010001001001000111010011001101110010101

Contribution: 777777222222

Production:

10101110110111011011101101110110111011011101101010110110011011001101100110110011011001101100101

Notation

Il s'agit du code golf , donc la soumission la plus courte (en octets gagne). Tiebreaker va au premier poste.

NinjaBearMonkey
la source
Mmm ... des fruits juteux.
Dennis
L'entrée peut-elle être prise en tant que tableau? par exemple["777777","222222"]
Downgoat
@vihan Hmm, je pense que c'est un peu exagéré. Je vais dire non.
NinjaBearMonkey
2
Le premier code-barres UPC scanné jamais!
Dennis
1
C'est génial. Les codes-barres m'ont toujours fasciné
Beta Decay

Réponses:

3

CJam, 58 57 octets

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

Imprime un BitMap portable (ASCII) sur STDOUT. Essayez-le en ligne.

Comment ça fonctionne

'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
la source
4

Rev 1 BBC BASIC, 155 caractères ascii, taille de fichier à jetons 132 octets

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

enregistré quelques octets en incorporant le décalage de 43 dans la iboucle. Afin d'éviter de casser le MOD247 supplémentaires ont dû être ajoutés pour un total de 90.

Cela déplace le code-barres plus loin de l'origine, comme indiqué, si cela est acceptable:

entrez la description de l'image ici

Rév 0 BBC BASIC, 157 caractères ascii, taille de fichier à jetons 137 octets

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

Téléchargez l'interprète sur http://www.bbcbasic.co.uk/bbcwin/bbcwin.html

Le mode d'écran par défaut est du texte noir sur fond blanc. Cela diffère de la BBC BASC d'origine.

Version non golfée avec impression test

Le calcul d'une barre de données dépend de IF j<42et doit être effectué sur une seule ligne. Dans la version non golfée, cela se fait en trois étapes. Dans la version golfée, les deux dernières étapes sont combinées en une seule expression énormep=...

J'ai dû inverser l'ordre des bitmaps, car j'utilise >>(j MOD 7)pour accéder aux bits, ce qui signifie que j'accède d'abord au bit le moins significatif. Une fois cela fait, tous les bitmaps de gauche sont commodément dans la plage 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

Sortie typique, version non golfée, avec sortie de test

entrez la description de l'image ici

Level River St
la source
2

JavaScript ES6, 225 octets

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)

Cela aurait pu être plus court avec les fonctionnalités d'ES7, mais je ne suis pas sûr de leur prise en charge, donc je m'en tiens à ES6. Je suppose également une entrée sous forme de tableau. La sortie est un fichier PBN . Il y a aussi beaucoup de golf à faire.

Si j'ai fait quelque chose de mal, laissez un commentaire et je serai sûr de le réparer

Downgoat
la source
Je pense que vous voulez dire le fichier PBM ...
sergiol
2

Perl, 153 octets

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

Copiez dans un fichier barcode.perl puis exécutez comme ceci:

perl barcode.perl > output.pbm

puis saisissez le numéro de code-barres.

Explication:

Les modèles de bits pour les chiffres du code-barres sont stockés dans une chaîne et substitués aux chiffres d'entrée à l'aide de l' y///opérateur de translittération Perl . Chaque valeur de la chaîne de substitution contient 48 (ASCII '0') ajoutées pour éviter les caractères non imprimables. Les chiffres de la seconde moitié du code-barres sont inverses de ceux de la première moitié.

Le modèle central est défini sur 0000000 (un modèle qui ne pourrait autrement jamais apparaître, codé comme 'A' puis '0'), puis remplacé par 01010 plutôt que de gérer sa longueur différente comme un cas spécial lors de l' sprinting.

samgak
la source
1

Octave, 115 octets

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

Version multiligne:

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

nest l'équivalent ASCII des codes numériques du côté droit (ils étaient plus faciles à saisir que le côté gauche car ils étaient tous des caractères affichables). Après cela, une conversion directe décimale en binaire avec un type gênant passe de char à numérique. vconstruit la chaîne binaire finale, puis nous la répétons 30 fois et sortie sur la console.

Exemple de sortie avec seulement 2 des 30 lignes affichées par souci de concision:

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

Sortie compressée:

1010111011011101101110110111011011101101110110101110110011011001101100110110011011001101100101

J'avais initialement l'intention d'afficher l'image, mais l'envoi de la sortie à la console m'a fait économiser 9 octets. Vous pouvez afficher les résultats à l'aide de imshow, mais il s'affiche 1en blanc et 0en noir, vous devez donc inverser les données en premier.

imshow(~v(ones(30,1),:));
gobelet
la source
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
la source
1

Javascript ES6, 199 octets

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
la source
msgstr "la soumission la plus courte (en octets gagne)". Vous devez compter votre code en octets, donc si vous utilisez Unicode, c'est 2 octets par caractère, je pense.
mbomb007
Bah, oui, je suppose que ma réponse non unicodée est plus courte que
Dendrobium
0

Python 2, 174 octets

Je sais que ça peut être joué au golf.

La chaîne sest le tableau binaire de la question avec la moitié gauche du tableau comme moitié gauche de la chaîne. Les valeurs sont ET par 63 en premier si dans la moitié droite (supprimer le premier 1), puis décalées de 63 pour être ASCII imprimable.

BOGUE: essaye actuellement de corriger un bogue. La sortie du premier exemple est désactivée par un chiffre du code-barres. Si vous le comprenez, faites-le moi savoir s'il vous plaît.

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
la source
Ou, j'ai fait relever le défi complètement mal. Faites-moi savoir dans ce cas aussi.
mbomb007