Encodeur code-barres Code 39

16

Écrivez une fonction ou un programme qui code une chaîne dans un code- barres au format Code 39 , où chaque caractère est codé en cinq barres séparées par quatre espaces. Soit deux des barres et l'un des espaces sont larges et les autres sont étroits (codes 10 * 4), soit trois des espaces sont larges et aucune des barres n'est (4 codes). Cela donne 44 codes différents, dont l'un est un code réservé qui est utilisé pour désigner le début et la fin de la chaîne codée.

Le défi

L'entrée est une chaîne contenant uniquement des caractères de l'ensemble

1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ-. +/$%

La sortie est la chaîne codée sous forme de chaîne de code-barres. L'espace étroit et les espaces intercaractères sont un espace unique et un espace large est de trois espaces. La barre étroite est la séquence d'octets UTF-8 pour le caractère Unicode "Bloc complet", █, c'est 0xE2 0x96 0x88-à- dire que la barre large représente trois séquences / caractères de ce type ( ███). La liste complète des codes est la suivante:

      Spaces
      0100 0010 0001 1000 1011 1101 1110 0111
Bars
00000                       +    /    $   %
10001   1    A    K    U
01001   2    B    L    V
11000   3    C    M    W
00101   4    D    N    X
10100   5    E    O    Y
01100   6    F    P    Z
00011   7    G    Q    -
10010   8    H    R    .
01010   9    I    S  space          1=wide
00110   0    J    T  start/end      0=narrow

Les barres et les espaces sont entrelacés, en commençant par une barre, donc par exemple Q est

bar   0 0 0  1     1 
code  █ █ █ ███   ███
space  0 0 0    1

Après avoir codé tous les caractères, la chaîne est délimitée aux deux extrémités avec █ █ ███ ███ █. L'espace intercaractère, un espace unique, est inséré entre chaque lettre. Votre solution peut générer des espaces de fin et une nouvelle ligne de fin (dans cet ordre).

Exemples

""     → "█   █ ███ ███ █ █   █ ███ ███ █"

"A"    → "█   █ ███ ███ █ ███ █ █   █ ███ █   █ ███ ███ █"

"C++"  → "█   █ ███ ███ █ ███ ███ █   █ █ █   █ █   █   █ █   █ █   █   █ █   █ ███ ███ █"

"GOLF" → "█   █ ███ ███ █ █ █ █   ███ ███ ███ █ ███ █   █ █ ███ █ █   ███ █ ███ ███   █ █ █   █ ███ ███ █"

Les formats d'entrée / sortie standard sont autorisés et les failles standard sont interdites. C'est le , donc le code le plus court mesuré en octets gagne!

Angs
la source
1
Pouvons-nous utiliser un caractère ASCII imprimable (vous pouvez choisir lequel autoriser) au lieu de █?
Erik the Outgolfer
Pour un langage comme BrainFuck, qu'est-ce qui compte comme "un usage"?
l4m2
1
@Angs que je voulais dire sur la sortie, pas dans le code. Il n'est pas très juste de sanctionner les utilisations du #personnage, car, par exemple, ce "#"n'est pas la seule raison pour laquelle il pourrait être utilisé dans une langue.
Erik the Outgolfer
@EriktheOutgolfer Ce que je voulais dire était dans les littéraux à cordes et autres, mais compte tenu du point de l4m2, il pourrait être préférable de le refuser. Après tout, y a-t-il des langues qui ne peuvent pas produire trois octets?
Angs

Réponses:

7

JavaScript (ES6), 225 212 octets

4 octets enregistrés grâce à @ l4m2

s=>`#${s}#`.replace(/./g,c=>'0202020202'.replace(/./g,(j,k)=>[C='█',C+C+C,' ','   '][(i="%+/$U1AKV2BLW3CMX4DNY5EOZ6FP-7GQ.8HR 9IS#0JT".indexOf(c),[170,257,260,5,272,17,20,320,65,68,80][i>>2]^2<<i%4*2)>>k&1|j]))

Essayez-le en ligne!

Comment?

Le tableau peut être réorganisé de sorte que le masque binaire 9 bits du caractère soit rapidement déduit de sa ligne et de sa colonne à l'aide de la formule suivante:

n = m XOR (2 << k)

avec:

  m  | k: 0   2   4   6
-----+------------------      Examples:
 170 |    %   +   /   $
 257 |    U   1   A   K         'G' = 320 XOR (2 << 4) = 320 XOR 32 = 352
 260 |    V   2   B   L
   5 |    W   3   C   M         '+' = 170 XOR (2 << 2) = 170 XOR 8  = 162
 272 |    X   4   D   N
  17 |    Y   5   E   O
  20 |    Z   6   F   P
 320 |    -   7   G   Q
  65 |    .   8   H   R
  68 |   spc  9   I   S
  80 |    #   0   J   T
Arnauld
la source
s=>`#${s}#`.replace(/./g,c=>'0202020202'.replace(/./g,(j,k)=>[C='#',C+C+C,' ',' '][(i="%+/$U1AKV2BLW3CMX4DNY5EOZ6FP-7GQ.8HR 9IS#0JT".indexOf(c),[,257,260,5,272,17,20,320,65,68,80][i>>2]|(2<<i%4*2^(i<4)*170))>>k&1|j]))(221)
l4m2
@ l4m2 Cela ne semble pas être valable. Cependant, j'ai réussi à trouver un correctif pour 221 octets .
Erik the Outgolfer
@EriktheOutgolfer Je pense que c'est essentiellement ce que l4m2 a soumis avec un bloc complet au lieu de '#'. Ou est-ce que je manque quelque chose?
Arnauld
@Arnauld Leur original ne s'espace pas correctement.
Erik the Outgolfer
3

Rouge , 452 445 octets

func[s][q: func[x y z][append/dup x y z]append insert s"*""*"b:
func[n][v: copy[]until[append v n % 2 * 2 + 1
1 > n: n / 2]q v 1 5 - length? v
reverse v]a: q":1234567890:ABCDEFGHIJ:KLMNOPQRST:UVWXYZ-. *"" "44
a/45: #"+"a/56: #"/"a/67: #"$"a/78: #"%"foreach t s[i: index? find a t
k: b pick[0 17 9 24 5 20 12 3 18 10 6]either 0 = j: i % 11[11][j]m:
b pick[8 4 2 16 22 26 28 14]i - 1 / 11 + 1 z: copy""repeat n 5[q z"█"k/(n)
q z" "m/(n)]prin z]]

Essayez-le en ligne!

J'essaierai de jouer au golf plus loin, mais je n'attends pas grand-chose de cette solution naïve.

Galen Ivanov
la source
2

Java 10, 455 octets

s->{String r="",R=r;for(var c:("~"+s+"~").split(""))r+=r.format("%9s",Long.toString(new int[]{148,289,97,352,49,304,112,37,292,100,52,265,73,328,25,280,88,13,268,76,28,259,67,322,19,274,82,7,262,70,22,385,193,448,145,400,208,133,388,196,138,162,168,42}["~1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ-. +/$%".indexOf(c)],2)).replace(' ','0');for(int l=r.length(),i=0,c;i<l;R+=""+(i%9%2<1?c<49?"█":"███":c<49?" ":"   ")+(i%9>7&++i<l?" ":""))c=r.charAt(i);return R;}

Essayez-le en ligne.

Explication:

s->{                     // Method with String as both parameter and return-type
  String r="",           //  Temp-String, staring empty
         R=r;            //  Result-String, starting empty as well
  for(var c:("~"+s+"~")  //  Prepend and append "~" to the input
            .split(""))  //  And loop over each character
    r+=r.format("%9s",Long.toString( 
                         //   Convert the following integer to a 9-bit binary String:
       new int[]{148,289,97,352,49,304,112,37,292,100,52,
                 265,73,328,25,280,88,13,268,76,28,259,67,322,
                 19,274,82,7,262,70,22,385,193,448,145,400,208,
                 133,388,196,138,162,168,42}
                         //    Array containing all decimal values of the binary Strings
       ["~1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ-. +/$%".indexOf(c)]
                         //    with the index based on the current character
   ,2)).replace(' ','0');
                         //   (also part of the integer to 9-bit binary String conversion)
  for(int l=r.length(),i=0,c;i<l;
                         //  Loop `i` over the temp-String
      R+=                //    After every iteration: append the following to the result:
         ""+(i%9%2<1?    //     If `i` modulo-9 modulo-2 is 0:
              c<49?      //      And `c` is '0':
               "█"       //       Append a single block
              :          //      Else:
               "███"     //       Append three blocks
             :c<49?      //     Else-if `c` is '0':
              " "        //      Append a single space
             :           //     Else:
              "   ")     //      Append three spaces
         +(i%9>7         //     If `i` modulo-9 is 8,
           &++i<l?       //     and this is not the very last character
            " "          //      Append a space delimiter
           :             //     Else:
            ""))         //      Append nothing more
    c=r.charAt(i);       //   Set `c` to the current character in `r`
  return R;}             //  Return the result
Kevin Cruijssen
la source
2

C (gcc) , 311 , 303 octets

(*P)()=printf;i;j;w;m[]={170,257,260,5,272,17,20,320,65,68,80};char*b=" \0\xE2\x96\x88",*t="%+/$U1AKV2BLW3CMX4DNY5EOZ6FP-7GQ.8HR 9IS#0JT",*c;p(x){j=256;w=2;while(j){P(b+w);if(x&1){P(b+w);P(b+w);}x/=2;j>>=1;w=2*!w;}P(" ");}f(char*_){p(82);for(c=_;*c;c++){i=strchr(t,*c)-t;p(m[i>>2]^(2<<(i&3)*2));}p(82);}

Essayez-le en ligne!

-8 grâce au plafond

Utilise la stratégie d'encodage de la réponse d'Arnauld. La liaison TIO comprend un -winterrupteur et un passe-partout pour supprimer les avertissements, ceux-ci sont inutiles et ne sont donc pas inclus dans le score.

Hormis le schéma de codage expliqué par Arnauld, l'autre astuce ici est de maintenir la wvariable comme basculant entre 2 et 0 ( w=2*!w). Cela me permet de choisir entre la première et la deuxième chaîne b. Le premier est un espace, le second est le rectangle rempli.

LambdaBeta
la source
intelligent, vous devriez le poster :)
LambdaBeta
2

C (gcc) , 241 239 227 213 207 octets

#define P printf(i%2?" ":"█")
i;p(x){for(i=9;i--;x/=2)P,x&1&&P+P;P;}f(char*_){p(82);for(char*t="%+/$U1AKV2BLW3CMX4DNY5EOZ6FP-7GQ.8HR 9IS#0JT";*_;p(L"ªāĄ\5Đ\21\24ŀADP"[i/4]^2<<i%4*2))i=index(t,*_++)-t;p(82);}

Essayez-le en ligne!

Basé sur l'implémentation de @ LambdaBeta .

Un peu moins golfé:

#define P printf(i%2?" ":"█")
i;
p(x){
 for(i=9;i--;x/=2)
  P,
  x&1&&
   P+
   P;
 P;
}
f(char*_){
 p(82);
 for(char*t="%+/$U1AKV2BLW3CMX4DNY5EOZ6FP-7GQ.8HR 9IS#0JT";*_;p(L"ªāĄ\5Đ\21\24ŀADP"[i/4]^2<<i%4*2))
  i=index(t,*_++)-t;
 p(82);
}
plafond
la source
1

Charbon de bois , 90 octets

⪫EE⪫**S⌕⁺⁺⭆…αχ﹪⊕μχα-. *+/$%ι⪫E⁵⁺⎇μ× ∨⁼›ι³⁹⁼²﹪⁻÷ι∨›ι³⁹χμ⁴¦³ω×█∨›ι³⁹∨§↨℅§.6':+3<-59ι²⊕μ³ω 

Essayez-le en ligne! Remarque: Espace de fin. Le lien est vers la version détaillée du code. Explication:

⪫EE⪫**S...⪫E⁵⁺...ω 

Enveloppez la chaîne d'entrée dans *s, puis mappez dessus deux fois, pour finalement joindre le résultat avec des espaces. Pour la deuxième carte, il existe alors une carte supplémentaire sur la plage implicite 0..4, où deux sous-chaînes sont concaténées, et ces résultats sont ensuite joints à la constante de chaîne vide prédéfinie.

⌕⁺⁺⭆…αχ﹪⊕μχα-. *+/$%ι

Pour la première carte intérieure, créez une chaîne formée en prenant les chiffres incrémentés, l'alphabet majuscule et les symboles -. *+/$%, et recherchez la position du caractère d'entrée mappé. Par exemple, C++correspondrait à [12, 40, 40].

⎇μ× ∨⁼›ι³⁹⁼²﹪⁻÷ι∨›ι³⁹χμ⁴¦³ω

La première sous-chaîne représente les espaces avant les barres. Il n'y a rien avant la première barre, mais les autres barres dépendent de la position du caractère d'entrée mappé: s'il est supérieur à 39, alors un seul endroit a un seul espace, tandis que s'il est inférieur à 40, alors un seul endroit en a trois espaces, et la position est également convertie en une colonne en la divisant par 10. Si la colonne et l'indice de boucle diffèrent par 2 (modulo 4), c'est l'endroit impair.

×█∨›ι³⁹∨§↨℅§.6':+3<-59ι²⊕μ³

La deuxième sous-chaîne représente les barres. Si la position est supérieure à 39, il y a toujours une barre, sinon la position est recherchée dans un tableau de bits mappés sur des caractères. Par exemple, si la position est 12, celle-ci est indexée de façon circulaire au caractère ', qui est 100111en binaire, indiquant des barres larges dans les colonnes 1 et 2. (Le début 1est ignoré, il garantit simplement un nombre de bits cohérent.)

Neil
la source
1

Perl 5 , 244 octets

$l="{ ,   ,...,.........}"x9;@h{$",qw($ % + - . /),0..9,'',A..Z}=(<"$l">)[q{..=9...Z.>>...J=9..j.%r1...=).[.>=-..Ux?V.^=8.>.6o+ax_.=(..B=,..Yx6..b=(..#r'p.^...G.<=,..Sx5B.\=(.V.It..z:..-z.=<6.}=~s/./ord$&/gre=~/.{6}/g];s/^|./$h{$&} /g;$\=$h{''}

Essayez-le en ligne!

Contient de nombreux caractères non imprimables et des caractères à octets élevés, le lien TIO fournit une xxdreprésentation. J'avais espéré que cela aurait fini par être plus petit, et je pourrais peut-être encore emballer les données de manière plus efficace, donc je vais voir comment je vais. Cela " "," ","█","███"accumule toutes les permutations de , puis mappe les indices de la liste aux caractères correspondants.

Dom Hastings
la source
1

Haskell , 275 270 octets

z=0:z
x!0=[]
x!n=mod n x:x!div n x
e c|Just a<-lookup c.zip"W3YZ56C$EF. 89*HM/ORU1QGNTDJ7%40LSBIP2-+XVKA".((++)<*>(reverse<$>))$take 9.(++z).(2!)<$>scanl(+)7(67!0x117CDBC49F9EEEF11C3A659CACB31236)=zipWith(\l c->c<$[1..2*l+1])(a++[0])(cycle"█ ")>>=id
f s='*':s++"*">>=e

Essayez-le en ligne!

L'opérateur x!nqui calcule les chiffres de base x de n, est utilisé deux fois pour décompresser les codes. Les codes sont d'abord compressés sous forme de chaînes binaires avec large = 1 et étroit = ​​0, sans égard à la couleur, par exemple R↔10000110↔262. Ces nombres sont ensuite triés et différenciés pour obtenir des nombres dans la plage [3,66], qui sont compressés à l'inverse de l'algorithme de chiffre binaire comme 0x117CDBC49F9EEEF11C3A659CACB31236. Celui-ci ne contient que la moitié des codes, le reste en est l'inverse.

Non golfé:

z=0:z                       -- infinite zeroes for padding
x!0=[]                      -- digits of n in base x, recursion base case
x!n=mod n x:x!div n x       -- digits of n in base x
e c | Just a                -- read upwards from (*)
  <-lookup c                -- lookup code, given letter
  . zip"W3YZ56C$EF. 89*HM/ORU1QGNTDJ7%40LSBIP2-+XVKA" 
                            -- combine codes with correct letters
  . ((++)<*>(reverse<$>))   -- concatenate list and list with reverse codes
  $ take 9                  -- take nine
  . (++z)                   -- pad with infinite zeroes on right
  . (2!)                    -- convert to binary digits – [[1,1,1],[1,0,1,1]…]
  <$> scanl (+) 7           -- cumulative sum starting from 7 – [7,13,19,22,25…]
        (67!0x117CDBC49F9EEEF11C3A659CACB31236)       
                            -- (*) digits in base 67 – [6,6,3,3,3,9,5,7…]
  = zipWith
      (\l c->c<$[1..2*l+1]) -- combine width and color, length is 2*l+1
      (a++[0])              -- list of widths as 0/1, 0 added for interchar gap
      (cycle"█ ")           -- infinite list of bar colors, leftovers are unused
  >>=id                     -- concatenate
f s='*':s++"*">>=e          -- surround string with delimiters, map e and concat
Angs
la source