Analyser le colis

24

Grâce à votre aide dans le défi Mark My Mail , PPCG-Post a réussi à tamponner tous ses colis avec les codes-barres générés!

Maintenant, il est temps de les décoder.

Dans ce défi, votre programme, étant donné un code-barres généré à partir du défi Mark My Mail , le décodera et renverra l'entier codé.

Mais attention! Le code-barres est peut-être à l'envers ...


Codes à barres à 4 états

Dans le cas où vous avez manqué le défi d'encodage, vous devrez savoir de quel type de code-barres nous parlons. Un code à barres à 4 états est une rangée de barres avec quatre états possibles, chacun représentant un entier de base 4:

            |       |
Bar:    |   |   |   |
                |   |

Digit:  0   1   2   3

Rendu en ASCII, les codes-barres prendront trois lignes de texte, en utilisant le caractère pipe ( |) pour représenter une partie d'une barre, et un espace ( ) pour représenter une section vide. Il y aura un seul espace entre chaque barre. Un exemple de code-barres peut ressembler à ceci:

| | | | | | | | | |
| | | | | | | | | | | | | | | | |
    | | | | | | | |

Pour reconvertir un code à barres en l'entier qu'il code, mappez chaque barre à son chiffre de base 4 correspondant, concaténez-les et convertissez-le en décimal.

Étant donné que chaque code à barres représentera également un code à barres différent lorsqu'il est à l'envers, nous implémentons une séquence de démarrage / arrêt afin de pouvoir calculer l'orienation. Aux fins de ce défi, nous utiliserons la séquence de démarrage / d'arrêt spécifiée par Australia Post: chaque code-barres commence et se termine par une 1 0séquence.


Le défi

Votre tâche consiste à, étant donné un code-barres ASCII à 4 états, l'analyser et renvoyer l'entier qu'il code - essentiellement l'inverse de Mark My Mail .

Mais pour pimenter les choses, il y a un hic - le code-barres peut être donné à l'envers. Comme dans le monde réel, il appartiendra au lecteur de code-barres (votre programme) de déterminer l'orientation correcte à l'aide de la séquence de démarrage / arrêt.

Exemple:

Étant donné le code-barres suivant:

    | | | |
| | | | | | | | | | |
  | | | | |

Nous pouvons clairement voir que les première et dernière paires de chiffres le sont 0, 2et non 1, 0. Cela signifie que le code-barres est à l'envers - nous devons donc le faire pivoter de 180 degrés (et pas seulement retourner chaque barre) pour obtenir l'orientation correcte:

| | | | |  
| | | | | | | | | | |
    | | | |    

Maintenant, nous pouvons commencer le décodage. Nous mappons chaque barre à son chiffre de base 4 correspondant, en ignorant les séquences de démarrage / d'arrêt car elles ne codent pas les données.

| | | | |  
| | | | | | | | | | |
    | | | |    

- - 2 1 0 3 0 2 3 - -

Nous concaténons cela à l'entier en base 4 2103023, puis le convertissons en sa représentation décimale 9419pour le résultat final.


Règles

  • L'entrée sera toujours un code-barres à 4 états valide, rendu en ASCII comme indiqué ci-dessus, avec la séquence de démarrage / arrêt décrite.
    • Vous pouvez demander des espaces de fin, ou des lignes dépouillées, ainsi qu'une nouvelle ligne de fin - quel que soit le format qui convient à votre golf.
    • Il peut ou non être dans la bonne orientation - votre programme doit déterminer s'il faut le lire à l'envers, en utilisant la séquence de démarrage / arrêt.
    • Il ne codera pas les premiers chiffres de zéro dans l'entier de base 4.
  • Vous pouvez prendre l'entrée comme une liste de lignes ou une chaîne avec des retours à la ligne.
  • La sortie doit être un entier dans la base d'entiers standard de votre langue, représentant les données qui ont été encodées par le code-barres.
  • Comme les timbres-poste sont petits et peuvent contenir très peu de code, votre code devra être aussi court que possible: c'est un - donc le programme le plus court (en octets) gagne!

Cas de test

| | | | | | | | | | |
  | | |

= 4096 (retourné)

      | | | | | | | |
| | | | | | | | | | | | | | | |
  | | | | | | | | | |

= 7313145 (retourné)

    | | | |
| | | | | | | | | | |
  | | | | |

= 9419 (retourné)

| | | | | |   
| | | | | | | | |
    | | | |     

= 990 (non retourné)

| | | | |   
| | | | | | | | | | |
    | | |       

= 12345 (non retourné)

FlipTack
la source
-1 les titres des deux articles ne sont pas du même format. ("P the P" vs "M my M", choisissez 'the' ou 'my': p)
Rɪᴋᴇʀ
1
Est-ce que « la liste des lignes » est l' une des [String], [{#Char}], [{Char}], [[Char]]?, Étant donné que Stringéquivaut à{#Char}
Οurous
3
@Ouros Quelle notation est-ce? Je soupçonne fortement que la réponse est "oui", car les types de données sont très différents entre les langues, donc les défis de codage acceptent généralement "quel que soit l'équivalent dans votre langue", mais je n'ai aucune idée des différentes représentations que vous essayez de représenter.
IMSoP
1
Et après? Emettre l'email? Transmettre le télégramme? Traiter le message?
Sanchises
1
@Ourous yes, le type de données est flexible, comme le décrit IMSoP.
FlipTack

Réponses:

5

Husk , 16 octets

ḋṁẊ=hhttĊ2T§▼↔m↔

Essayez-le en ligne!

L'entrée est une liste de lignes (le lien TIO utilise une chaîne multiligne pour plus de clarté). Les lignes doivent avoir des longueurs égales et il ne doit pas y avoir d'espaces de fin supplémentaires.

Explication

ḋṁẊ=hhttĊ2T§▼↔m↔  Input is a list of strings x.
           §▼     Lexicographic minimum of
             ↔    x reversed and
              m↔  x with each line reversed.
          T       Transpose. Now we have a list of columns.
        Ċ2        Get every second column, removing the blank ones.
    hhtt          Remove first 2 and last 2 (the orientation markers).
 ṁ                Map and concatenate
  Ẋ=              equality of adjacent pairs.
                  This turns a column like "|| " into [1,0], and these pairs are concatenated.
ḋ                 Convert from binary to integer.
Zgarb
la source
3

Python 2 , 113 105 octets

lambda x:int(''.join([`2*(c>'#')+(a>'#')`for a,b,c in zip(*x[::1-2*(x[-1]>'#')].split('\n'))][4:-4:2]),4)

Essayez-le en ligne!

Barre
la source
2

Rétine , 71 octets

(.).
$1
sO$^`^\|.*|.

^..|..¶.*¶..|..$
¶
\|
 |
+`\| 
 ||||
.*¶$
$&$&
\|

Essayez-le en ligne! Le lien inclut des cas de test plus petits. Nécessite que la première et la dernière ligne soient remplies d'espace jusqu'à la longueur de la ligne médiane. Explication:

(.).
$1

Supprimez les espaces inutiles.

sO$^`^\|.*|.

Inversez les caractères du code, mais si le code à barres commence par un |, sélectionnez le code entier, sinon divisez-le en caractères. Ensuite, inversez-les. Cela retourne le code s'il commence par un 0.

^..|..¶.*¶..|..$
¶

Supprimez la séquence de démarrage / d'arrêt et la ligne du milieu (qui ne nous sont d'aucune utilité).

\|
 |
+`\| 
 ||||

Convertissez les espaces et les |s de la base 4 en unaires.

.*¶$
$&$&

Doublez la dernière ligne.

\|

Convertissez en décimal.

Neil
la source
2

Java (OpenJDK 8) , 181 160 octets

Pas trop mal pour une solution java, je suis sûr qu'il y a des optimisations que je peux faire, mais je le regarde déjà depuis trop longtemps.

Réduisez quelques octets en raccourcissant la boucle plutôt qu'en utilisant une sous-chaîne.

Golfé

c->{String r="";Integer i,j,l=c[0].length;for(i=4;i<l-4;i+=2){j=c[0][0]>32?i:l-1-i;r+=c[0][j]%8/4*(j==i?1:2)+c[2][j]%8/4*(j==i?2:1)+"";}return l.parseInt(r,4);}

Essayez-le en ligne!

Non golfé

String r = "";
Integer i, j, l = c[0].length;
for(i=4; i<l-4; i+=2){
    j = c[0][0]>32 ? i : l-1-i;
    r += c[0][j]%8/4 * (j==i?1:2) + c[2][j]%8/4 * (j==i?2:1) + "";
}
return l.parseInt(r, 4);
Luke Stevens
la source
Je viens d'essayer votre code mais avec le code-barres inversé de l'exemple "| | |" "| | | | | | | | | | |" et donnez-moi 1024, ok je ne peux pas formater ceci, mais celui de l'exemple mais, essayez l'exemple que vous avez mais sans l'inverser, j'ai peut-être fait une mauvaise entrée :)
Java Gonzar
@JavaGonzalezArribas J'ai essayé le premier exemple (non retourné) et il semble bien fonctionner. Serait-ce que vous mettez un trop peu d'espaces dans la première ligne de l'entrée?
Luke Stevens
C'est probablement le problème, excellente réponse :)
Java Gonzar
Suggérer l+~i place del-1-i
plafondcat
2

Java 8 , 208 166 157 157 151 octets

L'essayer, peut être mieux, réduit 42 en raison de vérifications inutiles, -9 suppression de variables, -6 grâce à Luke Stevens

L'entrée est un char[][3]

(a)->{int i=2,c,s=0;c=(a[0][0]>32)?1:-1;for(;i<a.length-2;i++){s+=((a[i][1-c]>32?1:0)+(a[i][1+c]>32?2:0))*Math.pow(4,c==1?a.length-i-3:i-2);}return s;}

non golfé:

int b(char[][] a) {
    int i=2,c,s=0;                      //i for looping, c to check if it's reversed, s is the sum, n the number
    c=(a[0][0]>32)?1:-1; //Check if must be reversed

    for(;i<a.length-2;i++){         //Looping elements

            //(Checking value for 1 + Checking value for 2) * Power, if reversed increasing, else decreasing
        s+=((a[i][1-c]>32?1:0)+(a[i][1+c]>32?2:0))*Math.pow(4,c==1?a.length-i-3:i-2);   
    }
    return s;
}
Java Gonzar
la source
1
Si vous utilisez un tableau de caractères plutôt que des chaînes, vous pouvez vérifier | en utilisant> 32 plutôt que == "|" ce qui économise 2 octets pour chaque utilisation (6 au total). Vous pouvez également supprimer les crochets autour de a lors de la déclaration du lambda pour deux autres octets.
Luke Stevens
2

Propre , 191 ... 161 144 octets

import StdEnv
?' '=0;?_=1
r=reverse
$a b|hd a<'|'= $(r b)(r a)=[?(b!!n)*2+ ?(a!!n)\\n<-[4,6..length b-4]]
@[a,_,b]=sum[d*4^p\\d<- $a b&p<-[0..]]

Essayez-le en ligne!

Οurous
la source
1

Pip , 46 43 42 octets

IsQ@@gg:RV*RVgY^gR'|1(J@UW2*y@2+@y)TM2FB:4

Prend les lignes du code-barres comme trois arguments de ligne de commande. Les première et troisième lignes doivent être complétées à la longueur de la deuxième ligne avec des espaces. Essayez-le en ligne!

Explication

D'abord quelques préparatifs:

IsQ@@gg:RV*RVg Y^gR'|1

                        g is cmdline args; s is space (implicit)
IsQ                     If space equals
   @@g                  the first character of the first line, then:
           RVg           Reverse the order of the rows in g
        RV*              then reverse the characters in each row
      g:                 and assign the result back to g
                 gR'|1  In g, replace pipe character with 1
                ^       Split each row into a list of characters
               Y        Yank the result into y

Observez maintenant que si nous ignorons la ligne du milieu et traitons |comme 1 et comme 0, chaque barre n'est qu'un nombre binaire de 2 bits:

(J@UW2*y@2+@y)TM2FB:4

       y@2             Third row
     2*                Multiply by 2, turning 1 into 2 and space into 0
           @y          First row
          +            Add
   UW                  Unweave: creates a list of two lists, the first containing all
                       even-indexed elements (in our case, the actual data), the second
                       containing all odd-indexed elements (the space separators)
  @                    First item of that list
 J                     Join the list of digits into a string
(            )TM2      Trim 2 characters from the beginning and end
                 FB:4  Convert from base 4 (: makes the precedence lower than TM)
                       Autoprint
DLosc
la source
1

Husk , 39 38 octets

B4ththmȯ%4+3%5f≠192Ḟz+zṀ·*cN?↔m↔(='|←←

Prend des entrées sous forme de liste de chaînes: essayez-le en ligne ou essayez la suite de tests!

Explication

B4ththm(%4+3%5)f≠192Ḟz+zṀ·*cN?↔m↔(='|←←)
                             ?   (='|←←)  -- if the very first character == '|'
                              ↔           --   reverse the lines
                                          -- else
                               m↔         --   reverse each line
                       zṀ·*cN             -- zip the lines with [1,2,3..] under..
                        Ṁ·*c              --   convert each character to its codepoint and multiply by one of [1,2,3]
                    Ḟz+                   -- reduce the lines under zipWith(+) (this sums the columns)

               f≠192                      -- only keep elements ≠ 192 (gets rid of the separating lines)

-- for the example from the challenge we would now have:
--   [652,376,468,652,376,744,376,468,744,652,376]

      m(      )                           -- map the following function
        %4+3%5                            --   λx . ((x % 5) + 3) % 4
-- this gives us: [1,0,2,1,0,3,0,2,3,1,0]
    th                                    -- remove first & last element
  th                                      -- remove first & last element
B4                                        -- interpret as base4 number
ბიმო
la source
1

Perl 5 , 152 + 2 ( -F) octets

push@a,[@F]}{for$i(0..$#{$a[1]}){$_.=($a[0][$i]eq'|')+2*($a[2][$i]eq'|')}$_=reverse y/12/21/r if/^0/;s/^0*1000|10*$//g;s/.\K0//g;$\=$_+$\*4for/./g;say$\

Essayez-le en ligne!

Xcali
la source
0

Octave , 80 75 68 octets

@(b)bi2de({rot90(t=~~(b-32)([3,1],[1:2:end]),2),t}{2-t(2)}(5:end-4))

Essayez-le en ligne!

Curieusement, bi2dele MSB par défaut est à droite plutôt qu'à gauche, ce qui entraîne des maux de tête pendant que je faisais cela ... Je pense que je devrais avoir la façon optimale de retourner le tableau avant de l'indexer, mais il y a extrêmement de façons de le faire ( soit dans la première indexation, ou avec flipud, fliplr, rot90, '(transposition), l'indexation finale ...). Prend un tableau rectangulaire avec des espaces et des |s (donc, des espaces de fin requis)

@(b)                    % Define anonymous function taking input b

t=                      % Inline-define t,
~~(b-32)                % which is the input, converted to 1's and 0's,
([3 1],[1:2:end])       % but only keep the relevant rows (1 and 3 flipped vertically) and columns (only odd) 

{rot90(t,2),t}          % Flip 180 degrees
{2-t(2)                 % depending on whether the second element of t is 1 or 0.}

(5:end-4)               % Flatten array, discarding control bits
bi2de( ... )            % and convert from binary to decimal,
Sanchises
la source
0

JavaScript (ES6), 184 181 octets

Je ne suis pas un golfeur expérimenté - je suis sûr que cela peut être amélioré, mais j'ai adoré ce défi! Je me suis toujours interrogé sur ces marques.

La fonction fprend une liste de chaînes avec les espaces de fin requis. Ajout de nouvelles lignes au code ci-dessous pour plus de clarté (non inclus dans le nombre d'octets).

f=t=>((o=[[...t[0]],[...t[2]]])[0][0]=='|'?o:(z=a=>a.reverse())(o.map(z)))
.map((a,r)=>a.filter((_,i)=>~i%2).map(e=>(1+r)*(e=='|')).slice(2,-2))
.reduce((a,b)=>a+parseInt(b.join``,4),0)

Usage

t=['                     ','| | | | | | | | | | |','  |             |   |']
console.log(f(t)) // 4096

Version non golfée avec explication

// take list of strings, t, as input:
f = t => ( 

  // create output variable o, discard middle row, turn other rows into lists:
  ( o = [ [...t[0]], [...t[2]] ] )

  // if top-left position isn't a pipe, rotate 180 degrees.
  // Alias [].reverse to save 3 bytes :D
  [0][0] == '|' ? o : ( z = a=> a.reverse() )( o.map(z) )

).map( (a,r) => 

  // remove even-numbered positions (non-encoding spaces):
  a.filter( (_,i) => ~i%2 )

  // convert non-pipes into zeros, and pipes into 1 or 2;
  // top row becomes the base4 1-component, bottom row is 2:
  .map( e => (1+r) * (e=='|') ).slice(2,-2)

// convert rows to base4 component strings, then decimal, then sum them:
).reduce( (a,b) => a + parseInt(b.join``,4),0)
Chris M
la source