Analizza il pacco


24

Grazie al tuo aiuto nella sfida Mark My Mail , PPCG-Post ha timbrato con successo tutti i suoi pacchi con i codici a barre generati!

Ora è il momento di decodificarli.

In questa sfida, il tuo programma, dato un codice a barre generato dalla sfida Mark My Mail , lo decodificherà e restituirà il numero intero codificato.

Ma attenzione! Il codice a barre potrebbe essere capovolto ...


Codici a barre a 4 stati

Nel caso in cui tu abbia perso la sfida della codifica, dovrai sapere di che tipo di codici a barre stiamo parlando. Un codice a barre a 4 stati è una riga di barre con quattro possibili stati, ognuno dei quali rappresenta un numero intero di base 4:

            |       |
Bar:    |   |   |   |
                |   |

Digit:  0   1   2   3

Resi in ASCII, i codici a barre occuperanno tre righe di testo, usando il carattere pipe ( |) per rappresentare parte di una barra e uno spazio ( ) per rappresentare una sezione vuota. Ci sarà un singolo spazio tra ogni barra. Un codice a barre di esempio potrebbe essere simile al seguente:

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

Per riconvertire un codice a barre nell'intero che codifica, mappare ogni barra sulla corrispondente cifra di base 4, concatenarli e convertirli in decimali.

Poiché ogni codice a barre rappresenterà anche un codice a barre diverso quando capovolto, implementiamo una sequenza di avvio / arresto in modo da poter calcolare l'ordine. Ai fini di questa sfida, utilizzeremo la sequenza di avvio / arresto specificata da Australia Post: ogni codice a barre inizia e termina con una 1 0sequenza.


La sfida

Il tuo compito è, dato un codice a barre ASCII a 4 stati, analizzarlo e restituire l'intero che codifica, essenzialmente il contrario di Mark My Mail .

Ma per rendere le cose più interessanti, c'è un problema: il codice a barre può essere fornito capovolto. Come nel mondo reale, sarà lasciato al lettore di codici a barre (il tuo programma) per determinare l'orientamento corretto usando la sequenza di avvio / arresto.

Esempio:

Dato il seguente codice a barre:

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

Possiamo vedere chiaramente che la prima e l'ultima coppia di cifre sono 0, 2e non 1, 0. Ciò significa che il codice a barre è capovolto, quindi dobbiamo ruotarlo di 180 gradi (non solo capovolgere ogni barra) per ottenere l'orientamento corretto:

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

Ora possiamo iniziare la decodifica. Mappiamo ogni barra sulla corrispondente cifra di base 4, ignorando le sequenze di avvio / arresto in quanto non codificano i dati.

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

- - 2 1 0 3 0 2 3 - -

Lo concateniamo all'intero base-4 2103023, quindi lo convertiamo nella sua rappresentazione decimale 9419per il risultato finale.


Regole

  • L'ingresso sarà sempre un codice a barre valido a 4 stati, reso in ASCII come indicato sopra, con la sequenza di avvio / arresto descritta.
    • È possibile richiedere spazi finali o linee spogliate, nonché una nuova riga finale, qualunque sia il formato adatto al proprio golf.
    • Potrebbe essere o meno nell'orientamento corretto: il programma deve determinare se leggerlo sottosopra, utilizzando la sequenza di avvio / arresto.
    • Non codificherà le cifre zero iniziali nell'intero di base 4.
  • È possibile prendere l'input come un elenco di righe o una stringa con newline.
  • L'output deve essere un numero intero nella base di numeri interi standard della tua lingua, che rappresenta i dati codificati dal codice a barre.
  • Poiché i francobolli sono piccoli e possono contenere pochissimo codice, il codice dovrà essere il più corto possibile: si tratta di un - quindi vince il programma più breve (in byte)!

Casi test

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

= 4096 (capovolto)

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

= 7313145 (capovolto)

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

= 9419 (capovolto)

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

= 990 (non capovolto)

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

= 12345 (non capovolto)


-1 i titoli dei due post non sono dello stesso formato. ("P the P" vs "M my M", scegli "the" o "my": p)
Rɪᴋᴇʀ

1
Sarebbe "elenco delle linee di" essere una qualsiasi delle [String], [{#Char}], [{Char}], [[Char]]?, Visto che Stringè equivalente a{#Char}
Οurous

3
@Ouros Che notazione è quella? Sospetto fortemente che la risposta sia "sì", perché i tipi di dati sono molto diversi tra le lingue, quindi le sfide di codifica generalmente accettano "qualunque sia l'equivalente nella tua lingua", ma non ho idea di quali rappresentazioni diverse stai cercando di rappresentare.
IMSoP

1
Qual'è il prossimo? Emetti l'e-mail? Trasmettere il Telegram? Elaborare la posta?
Sanchises,

1
@Ourous sì, il tipo di dati è flessibile, come descritto da IMSoP.
FlipTack

Risposte:



5

Buccia , 16 byte

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

Provalo online!

L'input è un elenco di righe (il collegamento TIO utilizza una stringa multilinea per chiarezza). Le linee devono avere uguale lunghezza e non devono esserci spazi finali aggiuntivi.

Spiegazione

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




2

Retina , 71 byte

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

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

Provalo online! Il collegamento include casi di test più piccoli. Richiede che la prima e l'ultima riga siano riempite di spazio per la lunghezza della linea mediana. Spiegazione:

(.).
$1

Elimina gli spazi non necessari.

sO$^`^\|.*|.

Invertire i caratteri nel codice, ma se il codice a barre inizia con un |, quindi selezionare l'intero codice, altrimenti dividerlo in caratteri. Quindi, invertili. Questo lancia il codice se inizia con a 0.

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

Elimina la sequenza di avvio / arresto e la riga centrale (che non ci è utile).

\|
 |
+`\| 
 ||||

Converti gli spazi e la |s dalla base 4 in unario.

.*¶$
$&$&

Raddoppia l'ultima riga.

\|

Converti in decimale.


2

Java (OpenJDK 8) , 181 160 byte

Non troppo malandato per una soluzione Java, sono sicuro che ci sono ottimizzazioni che posso fare, ma lo sto già fissando da troppo tempo.

Ridurre alcuni byte accorciando il ciclo anziché utilizzare la sottostringa.

golfed

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

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

Ho appena provato il tuo codice ma con il codice a barre invertito dell'esempio "| | |" "| | | | | | | | | | |" e dammi 1024, Ok non posso formattarlo, ma quello sull'esempio ma, prova l'esempio che hai ma senza invertirlo, forse ho fatto un input
errato

@JavaGonzalezArribas Ho provato il primo esempio (non capovolto) e sembra funzionare bene. Potrebbe essere che tu abbia inserito uno spazio in troppo pochi nella prima riga dell'input?
Luke Stevens,

Questo è probabilmente il problema, ottima risposta :)
Java Gonzar,

Suggerisci l+~iinvece dil-1-i
ceilingcat l'

2

Java 8 , 208 166 157 151 byte

Provandolo, probabilmente può essere migliore, ridotto 42 a causa di controlli non necessari, -9 rimozione delle variabili, -6 grazie a Luke Stevens

L'input è a 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;
}

1
Se si utilizza una matrice di caratteri anziché String, è possibile verificare la presenza di | utilizzando> 32 anziché == "|" che consente di risparmiare 2 byte per ogni utilizzo (6 in totale). È anche possibile rimuovere le parentesi attorno a a quando si dichiara lambda per altri due byte.
Luke Stevens,

2

Pulito , 191 ... 161 144 byte

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

Provalo online!


1

Pip , 46 43 42 byte

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

Prende le righe del codice a barre come tre argomenti della riga di comando. La prima e la terza riga devono essere riempite con spazi per la lunghezza della seconda riga. Provalo online!

Spiegazione

Prima alcuni lavori preliminari:

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

Ora osserva che se ignoriamo la riga centrale e trattiamo |come 1 e come 0, ogni barra è solo un numero binario a 2 bit:

(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

1

Buccia , 39 38 byte

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

Accetta input come un elenco di stringhe: provalo online o prova la suite di test!

Spiegazione

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

1

Perl 5 , 152 + 2 ( -F) byte

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

Provalo online!


0

Ottava , 80 75 68 byte

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

Provalo online!

Curiosamente, bi2deè di default MSB a destra piuttosto che a sinistra, che porta a qualche mal di testa, mentre ho fatto questo ... penso che dovrei avere il modo ottimale di lanciare la matrice prima indicizzazione, ma ci sono estremamente molti modi per farlo ( sia nel primo indicizzazione, o con flipud, fliplr, rot90, '(transpose), l'indicizzazione finale ...). Prende una matrice rettangolare con spazi |es (quindi, sono richiesti spazi finali)

@(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,

0

JavaScript (ES6), 184 181 byte

Non sono un golfista esperto - Sono sicuro che questo può essere migliorato, ma ho adorato questa sfida! Mi sono sempre chiesto di quei segni.

La funzione fprende un elenco di stringhe con spazi finali richiesti. Newline aggiunti al codice seguente per chiarezza (non inclusi nel conteggio dei byte).

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

Versione non golfata con spiegazione

// 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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.