Barcodegolf: Generiere den UPC einer Zahl

12

Nahezu jedes Geschäft verwendet heutzutage UPC-Barcodes ( Universal Product Code ), um den Bestellvorgang zu vereinfachen. Wenn der Name Ihnen nichts bedeutet, werden Sie sicherlich erkennen, wie sie aussehen:

Beispiel für einen UPC-A-Barcode

Format

Das gebräuchlichste System ist UPC-A, bei dem jedes Produkt aus 12 Ziffern besteht. Jede Ziffer ist in eine Reihe von schwarzen und weißen Streifen codiert, damit Maschinen den Code lesen können, eine Länge von sieben Bits. Es gibt insgesamt Muster im Wert von 11 Bits, die den Anfang, die Mitte und das Ende des Barcodes angeben. Dies ergibt eine Gesamtlänge des Barcodes von 12 × 7 + 11 = 95 Bit. (Von nun an ist, wenn Binär zur Bezeichnung der Farbe jedes Bits verwendet wird, 0Weiß und 1Schwarz.)

Der Anfang und das Ende haben beide ein Muster von 101. Die Ziffern werden dann in 2 6er-Gruppen unterteilt und wie unten dargestellt mit einem Muster 01010zwischen der linken und der rechten Gruppe codiert . In dieser Tabelle ist das Muster für jede Nummer aufgeführt. Beachten Sie, dass das Muster unterschiedlich ist, je nachdem, ob sich die Ziffer auf der rechten oder der linken Seite befindet. (Dadurch kann der Barcode verkehrt herum gescannt werden.) Das Muster für die rechte Seite ist jedoch das Gegenteil (Schwarz gegen Weiß tauschen und umgekehrt) des Musters für die linke Seite.

UPC-Umrechnungstabelle

Wenn Sie das obige Bild nicht sehen können, ist dies das binäre Äquivalent jeder Zahl.

#   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

Beispiel

Angenommen, Sie haben den UPC 022000 125033. (Das sind keine Zufallszahlen. Hinterlassen Sie einen Kommentar, wenn Sie deren Bedeutung herausfinden.) Sie beginnen mit diesem Kesselschild, das in jedem Barcode gleich ist:

101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx01010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx101

Für die Ziffern ersetzen Sie jede durch die entsprechende Kodierung für die Seite (links oder rechts), auf der sie sich befindet. Wenn Sie immer noch verwirrt sind, sehen Sie sich das Bild unten an.

Aufschlüsselung der UPC-Codierung

Hier ist die Ausgabe in Binärform mit |Rohren, die die Teile trennen.

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

Herausforderung

Schreiben Sie ein Programm, das den UPC-A-Barcode für die Benutzereingabe ausgibt. Die Abmessungen des Bildes sollten 95 × 30 Pixel betragen, wobei jedes "Bit" ein Pixel breit und 30 Pixel hoch ist. Schwarze Streifen sind in rgb(0, 0, 0)und weiße Streifen sind durchgehend transparent oder rgb(255, 255, 255).

Anmerkungen

  • Nehmen Sie die Eingabe von stdin oder der Befehlszeile entgegen oder schreiben Sie eine Funktion, die einen String oder eine Ganzzahl annimmt (beachten Sie, dass die Eingabe führende Nullen haben kann und die meisten Sprachen diese entfernen oder die Zahl in Oktal konvertieren).
  • Geben Sie das Bild auf eine der folgenden Arten aus:
    • Speichern Sie es in einer Datei mit einem Namen und einem Format (PNG, PBM usw.) Ihrer Wahl.
    • Zeigen Sie es auf dem Bildschirm an.
    • Die Dateidaten werden an stdout ausgegeben.
  • Sie dürfen keine Bibliotheken oder eingebauten Elemente verwenden, die Barcodes generieren ( ich sehe Sie, Mathematica ), obwohl Sie möglicherweise Bild- oder Grafikbibliotheken verwenden.
  • Die letzte Ziffer eines UPC ist normalerweise eine Prüfziffer , aber für diese Zwecke müssen Sie sich keine Sorgen machen.

Beispiele

Hier sind einige weitere Beispiele, mit denen Sie Ihren Code testen können. Der Binärausgang ist auch der Einfachheit halber angegeben.

Eingang: 012345678910

Ausgabe:

10100011010011001001001101111010100011011000101010101000010001001001000111010011001101110010101

Eingang: 777777222222

Ausgabe:

10101110110111011011101101110110111011011101101010110110011011001101100110110011011001101100101

Wertung

Dies ist Codegolf , daher gewinnt die kürzeste Einreichung (in Bytes). Tiebreaker geht zum frühesten Beitrag.

NinjaBearMonkey
quelle
Mmm ... saftige Frucht.
Dennis
Kann die Eingabe als Array aufgenommen werden? zB["777777","222222"]
Downgoat
@vihan Hmm, ich denke das ist ein bisschen langwierig. Ich werde nein sagen.
NinjaBearMonkey
2
Erster gescannter UPC-Barcode aller Zeiten!
Dennis
1
Das ist brilliant. Barcodes haben mich schon immer fasziniert
Beta Decay

Antworten:

3

CJam, 58 57 Bytes

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

Druckt eine Portable BitMap (ASCII) nach STDOUT. Probieren Sie es online aus.

Wie es funktioniert

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

Rev 1 BBC BASIC, 155 ASCII-Zeichen, tokenisierte Dateigröße 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

Ein paar Bytes gespart, indem der Versatz von 43 in die iSchleife aufgenommen wurde. Um einen Bruch zu vermeiden, mussten MOD2zusätzlich 47 für insgesamt 90 hinzugefügt werden.

Dadurch wird der Barcode wie gezeigt weiter vom Ursprung entfernt, sofern dies akzeptabel ist:

Bildbeschreibung hier eingeben

Rev 0 BBC BASIC, 157 ASCII-Zeichen, tokenisierte Dateigröße 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

Laden Sie den Interpreter unter http://www.bbcbasic.co.uk/bbcwin/bbcwin.html herunter

Der Standardbildschirmmodus ist schwarzer Text auf weißem Hintergrund. Dies unterscheidet sich von Original BBC BASC.

Ungolfed-Version mit Probedruck

Die Berechnung eines Datenbalkens ist abhängig von IF j<42und muss in einer Zeile erfolgen. In der ungolfed Version erfolgt dies in drei Schritten. In der Golfversion werden die letzten beiden Schritte zu einem einzigen großen Ausdruck kombiniertp=...

Ich musste die Reihenfolge der Bitmaps umkehren, weil ich >>(j MOD 7)auf die Bits zugreife, was bedeutet, dass ich zuerst auf das niedrigstwertige Bit zugreife. Sobald dies erledigt ist, befinden sich alle linken Bitmaps bequemerweise im ASCII-Bereich.

  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

Typische Ausgabe, ungolfed Version, mit Testausgabe

Bildbeschreibung hier eingeben

Level River St
quelle
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)

Könnte mit ES7-Funktionen kürzer sein, aber ich bin mir nicht sicher, ob sie unterstützt werden, also bleibe ich bei ES6. Ich gehe auch von einer Eingabe als Array aus. Die Ausgabe ist eine PBN-Datei . Es gibt auch viel zu golfen.

Wenn ich etwas falsch gemacht habe, hinterlasse einen Kommentar und ich werde ihn mit Sicherheit reparieren

Downgoat
quelle
Ich denke, du meinst PBM-Datei ...
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

Kopieren Sie in eine Datei barcode.perl und führen Sie dann Folgendes aus:

perl barcode.perl > output.pbm

Geben Sie dann die Barcode-Nummer ein.

Erläuterung:

Die Bitmuster für die Barcode-Ziffern werden in einer Zeichenfolge gespeichert und durch die eingegebenen Ziffern mit dem Perl- y///Transliterationsoperator ersetzt. Zu jedem Wert in der Ersetzungszeichenfolge werden 48 (ASCII '0') hinzugefügt, um nicht druckbare Zeichen zu vermeiden. Die Ziffern in der zweiten Hälfte des Barcodes sind Umkehrwerte zu denen in der ersten Hälfte.

Das zentrale Muster wird auf 0000000 gesetzt (ein Muster, das sonst niemals erscheinen kann, codiert als 'A' und dann '0') und dann durch 01010 ersetzt, anstatt seine unterschiedliche Länge als Sonderfall zu behandeln sprint.

Samgak
quelle
1

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

Mehrzeilige Version:

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

nist das ASCII-Äquivalent der Zifferncodes auf der rechten Seite (sie waren einfacher einzugeben als auf der linken Seite, da sie alle anzeigbare Zeichen waren). Danach ändert sich eine gerade Dezimal-Binär-Konvertierung mit einigen ärgerlichen Typen von char zu numeric. verstellt die endgültige Binärzeichenfolge, und dann wiederholen wir sie 30 Mal und geben sie an die Konsole aus.

Beispielausgabe mit nur 2 der 30 Zeilen, die der Kürze halber angezeigt werden:

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

Komprimierte Ausgabe:

1010111011011101101110110111011011101101110110101110110011011001101100110110011011001101100101

Ich hatte ursprünglich vor, das Bild anzuzeigen, aber das Senden der Ausgabe an die Konsole sparte mir 9 Bytes. Sie können die Ergebnisse mit anzeigen imshow, sie werden jedoch 1weiß und 0schwarz angezeigt , sodass Sie zuerst die Daten invertieren müssen.

imshow(~v(ones(30,1),:));
Becherglas
quelle
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
quelle
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
quelle
msgstr "die kürzeste Einreichung (in Bytes gewinnt)". Sie müssen Ihren Code in Bytes zählen. Wenn Sie also Unicode verwenden, sind das, glaube ich, 2 Bytes pro Zeichen.
mbomb007
Bah, ja, ich denke meine Antwort ist kürzer
Dendrobium
0

Python 2, 174 Bytes

Ich weiß, dass man Golf spielen kann.

Die Saite s ist die Binärtabelle in der Frage, wobei die linke Hälfte der Tabelle die linke Hälfte der Zeichenfolge ist. Die Werte werden zuerst um 63 UND-verknüpft, wenn sie sich in der rechten Hälfte befinden (entfernen Sie zuerst 1), und dann um 63 verschoben, um druckbares ASCII zu erhalten.

BUG: Derzeit wird versucht, einen Fehler zu beheben. Die Ausgabe des ersten Beispiels ist um eine Stelle des Barcodes abgeschaltet. Wenn Sie es herausfinden, lassen Sie es mich bitte wissen.

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
quelle
Oder ich habe die Herausforderung komplett falsch gemacht. Lass es mich auch in diesem Fall wissen.
mbomb007