Analisar o pacote

24

Graças à sua ajuda no desafio Marcar meu e-mail , o PPCG-Post carimbou com sucesso todos os seus pacotes com os códigos de barras gerados!

Agora, é hora de decodificá-los.

Nesse desafio, seu programa, com um código de barras gerado a partir do desafio Mark My Mail , decodificará e retornará o número inteiro codificado.

Mas cuidado! O código de barras pode estar de cabeça para baixo ...


Códigos de barras de 4 estados

No caso de você ter perdido o desafio da codificação, precisará saber de que tipo de código de barras estamos falando. Um código de barras de 4 estados é uma linha de barras com quatro estados possíveis, cada um representando um número inteiro de base 4:

            |       |
Bar:    |   |   |   |
                |   |

Digit:  0   1   2   3

Renderizados em ASCII, os códigos de barras ocupam três linhas de texto, usando o |caractere pipe ( ) para representar parte de uma barra e um espaço ( ) para representar uma seção vazia. Haverá um espaço único entre cada barra. Um exemplo de código de barras pode ser assim:

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

Para converter um código de barras de volta no número inteiro que codifica, mapeie cada barra para o dígito base-4 correspondente, concatene-os e converta-o em decimal.

Como cada código de barras também representa um código de barras diferente quando invertido, implementamos uma sequência de início / parada para que a orientação possa ser calculada. Para o objetivo deste desafio, usaremos a sequência de início / parada especificada pelo Australia Post: cada código de barras começa e termina com uma 1 0sequência.


O desafio

Sua tarefa é, dado um código de barras ASCII de 4 estados, analisá-lo e retornar o número inteiro que ele codifica - essencialmente o inverso do Mark My Mail .

Mas, para apimentar as coisas, há um problema - o código de barras pode ser dado de cabeça para baixo. Como no mundo real, ele será deixado ao leitor de código de barras (seu programa) para determinar a orientação correta usando a sequência de início / parada.

Exemplo:

Dado o seguinte código de barras:

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

Podemos ver claramente que o primeiro e o último par de dígitos são 0, 2e não 1, 0. Isso significa que o código de barras está de cabeça para baixo - portanto, devemos rotacioná-lo 180 graus (não apenas virar cada barra) para obter a orientação correta:

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

Agora, podemos começar a decodificação. Mapeamos cada barra para o dígito base-4 correspondente, ignorando as seqüências de início / parada, pois elas não codificam os dados.

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

- - 2 1 0 3 0 2 3 - -

Concatenamos isso no número inteiro base-4 2103023e depois o convertemos em sua representação decimal 9419para o resultado final.


Regras

  • A entrada sempre será um código de barras válido de quatro estados, renderizado em ASCII, conforme definido acima, com a sequência de início / parada descrita.
    • Você pode solicitar espaços à direita ou linhas despojadas, bem como uma nova linha à direita - o que for mais adequado ao seu formato de golfe.
    • Pode ou não estar na orientação correta - seu programa deve determinar se deve lê-lo de cabeça para baixo, usando a sequência de início / parada.
    • Ele não codificará os dígitos zero iniciais no número inteiro base-4.
  • Você pode considerar a entrada como uma lista de linhas ou uma string com novas linhas.
  • A saída deve ser um número inteiro na base inteira padrão do seu idioma, representando os dados que foram codificados pelo código de barras.
  • Como os selos postais são pequenos e podem caber muito pouco código neles, seu código precisará ser o mais curto possível: este é um - para que o programa mais curto (em bytes) vença!

Casos de teste

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

= 4096 (invertido)

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

= 7313145 (invertida)

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

= 9419 (invertido)

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

= 990 (não invertido)

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

= 12345 (não invertido)

FlipTack
fonte
-1 os títulos nas duas postagens não têm o mesmo formato. ( "P o P" vs "M minha M", quer escolher 'a' ou 'meu': p)
Rɪᴋᴇʀ
11
Seria "lista de linhas de" ser qualquer um [String], [{#Char}], [{Char}], [[Char]]?, Dado que Stringé equivalente a{#Char}
Οurous
3
@Ouros Que notação é essa? Eu suspeito fortemente que a resposta seja "sim", porque os tipos de dados são muito diferentes entre os idiomas; portanto, os desafios de codificação geralmente aceitam "qualquer que seja o equivalente no seu idioma", mas não tenho idéia de quais representações diferentes você está tentando representar.
IMSOP
11
Qual é o próximo? Emitir o email? Transmitir o telegrama? Processar a postagem?
Sanchises
11
@Ourous sim, o tipo de dados é flexível, como o IMSoP descreveu.
FlipTack

Respostas:

5

Casca , 16 bytes

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

Experimente online!

Entrada é uma lista de linhas (o link TIO usa uma sequência de linhas múltiplas para maior clareza). As linhas devem ter comprimentos iguais e não deve haver espaços extras à direita.

Explicação

ḋṁẊ=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
fonte
3

Python 2 , 113 105 bytes

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

Experimente online!

Cajado
fonte
2

Retina , 71 bytes

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

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

Experimente online! O link inclui casos de teste menores. Requer que a primeira e a última linhas sejam preenchidas com espaço ao comprimento da linha do meio. Explicação:

(.).
$1

Exclua os espaços desnecessários.

sO$^`^\|.*|.

Inverta os caracteres no código, mas se o código de barras começar com a |, selecione o código inteiro, caso contrário, divida-o em caracteres. Então, inverta-os. Isso inverte o código se começar com a 0.

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

Exclua a sequência de início / parada e a linha do meio (que não nos serve).

\|
 |
+`\| 
 ||||

Converta os espaços |es da base 4 em unário.

.*¶$
$&$&

Duplique a última linha.

\|

Converta para decimal.

Neil
fonte
2

Java (OpenJDK 8) , 181 160 bytes

Não é tão ruim para uma solução java, tenho certeza de que há otimizações que posso fazer, mas já estou encarando isso há muito tempo.

Corte alguns bytes encurtando o loop em vez de usar substring.

Golfe

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);}

Experimente online!

Ungolfed

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
fonte
Apenas tentei seu código, mas com o código de barras invertido do exemplo "| | |" "| | | | | | | | |" " e dá-me 1024, Ok eu não posso formatar isso, mas o que está no exemplo, mas, tente o exmple você tem, mas sem reverter isso, talvez eu fiz uma entrada ruim :)
Java Gonzar
@JavaGonzalezArribas Tentei o primeiro exemplo (não invertido) e parece que funciona bem. Poderia ser você colocar muito poucos espaços na primeira linha da entrada?
Luke Stevens
Isso provavelmente é o problema, grande resposta :)
Java Gonzar
Sugerir em l+~ivez del-1-i
ceilingcat 8/11
2

Java 8 , 208 166 157 151 bytes

Tentá-lo, provavelmente pode ser melhor, reduziu 42 devido a verificações desnecessárias, -9 removendo variáveis, -6 graças a Luke Stevens

Entrada é um 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;}

ungolfed:

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
fonte
11
Se você usar uma matriz de caracteres em vez de Strings, poderá verificar | usando> 32 em vez de == "|" que economiza 2 bytes para cada uso (6 no total). Você também pode remover os colchetes ao redor de um ao declarar o lambda por mais dois bytes.
Luke Stevens
2

Limpo , 191 ... 161 144 bytes

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

Experimente online!

Furioso
fonte
1

Pip , 46 43 42 bytes

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

Toma as linhas do código de barras como três argumentos da linha de comando. A primeira e a terceira linhas devem ser preenchidas com o comprimento da segunda linha com espaços. Experimente online!

Explicação

Primeiro um pouco de preparação:

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

Agora observe que, se ignorarmos a linha do meio e tratarmos |1 e 0, cada barra será apenas um número binário 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
fonte
1

Casca , 39 38 bytes

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

Aceita entrada como uma lista de strings: Experimente on-line ou tente a suíte de testes!

Explicação

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
ბიმო
fonte
1

Perl 5 , 152 + 2 ( -F) bytes

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$\

Experimente online!

Xcali
fonte
0

Oitava , 80 75 68 bytes

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

Experimente online!

Curiosamente, bi2deé MSB padrão à direita em vez da esquerda, levando a algumas dores de cabeça enquanto eu fiz isso ... Eu acho que eu deveria ter a melhor maneira de lançar a matriz antes de indexando-lo, mas há muito muitas maneiras de fazê-lo ( seja no primeiro indexação, ou com flipud, fliplr, rot90, '(transposição), a indexação final, ...). Toma uma matriz retangular com espaços |es (portanto, são necessários espaços à direita)

@(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
fonte
0

JavaScript (ES6), 184 181 bytes

Não sou um jogador experiente - tenho certeza de que isso pode ser melhorado, mas adorei esse desafio! Eu sempre me perguntei sobre essas marcas.

A função fobtém uma lista de cadeias de caracteres com espaços à direita necessários. Novas linhas adicionadas ao código abaixo para maior clareza (não incluídas na contagem de bytes).

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)

Uso

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

Versão ungolfed com explicação

// 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
fonte