Parsuj paczkę

24

Dzięki Twojej pomocy w wyzwaniu Oznacz moją pocztę , PPCG-Post pomyślnie stempluje wszystkie swoje paczki wygenerowanymi kodami kreskowymi!

Czas je rozszyfrować.

W tym wyzwaniu Twój program, biorąc pod uwagę kod kreskowy wygenerowany z wyzwania Mark My Mail , dekoduje go i zwraca zakodowaną liczbę całkowitą.

Ale uważaj! Kod kreskowy może być odwrócony ...


4-stanowe kody kreskowe

W przypadku pominięcia wyzwania kodowania musisz wiedzieć, o jakich kodach kreskowych mówimy. 4-stanowy kod kreskowy to rząd pasków z czterema możliwymi stanami, z których każdy reprezentuje liczbę całkowitą base-4:

            |       |
Bar:    |   |   |   |
                |   |

Digit:  0   1   2   3

Renderowane w ASCII, kody kreskowe zajmą trzy linie tekstu, używając |znaku potoku ( ) do reprezentacji części paska oraz spacji ( ) do reprezentacji pustej sekcji. Pomiędzy każdym taktem będzie jedna spacja. Przykładowy kod kreskowy może wyglądać następująco:

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

Aby przekonwertować kod kreskowy z powrotem na liczbę całkowitą, którą koduje, zamapuj każdy słupek na odpowiadającą mu 4 cyfrę podstawową, połącz je i przekonwertuj na dziesiętny.

Ponieważ każdy kod kreskowy będzie również reprezentował inny kod kreskowy, odwrócone do góry nogami, implementujemy sekwencję start / stop, aby można było obliczyć orientację. Do celów tego wyzwania wykorzystamy sekwencję start / stop określoną przez Australia Post: każdy kod kreskowy zaczyna się i kończy 1 0sekwencją.


Wyzwanie

Twoim zadaniem jest, biorąc pod uwagę 4-stanowy kod kreskowy ASCII, parsować go i zwracać liczbę całkowitą, którą koduje - zasadniczo odwrotność Mark My Mail .

Ale aby urozmaicić wszystko, jest pewien haczyk - kod kreskowy może zostać podany do góry nogami. Podobnie jak w prawdziwym świecie, pozostawienie czytnika kodów kreskowych (twojego programu) ustalenie prawidłowej orientacji za pomocą sekwencji start / stop będzie pozostawione .

Przykład:

Biorąc pod uwagę następujący kod kreskowy:

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

Widzimy wyraźnie, że pierwsza i ostatnia para cyfr są, 0, 2a nie są 1, 0. Oznacza to, że kod kreskowy jest odwrócony - więc musimy go obrócić o 180 stopni (nie tylko odwrócić każdy pasek), aby uzyskać prawidłową orientację:

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

Teraz możemy rozpocząć dekodowanie. Mapujemy każdy słupek na odpowiadającą mu cyfrę podstawową 4, ignorując sekwencje start / stop, ponieważ nie kodują danych.

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

- - 2 1 0 3 0 2 3 - -

Łączymy to z liczbą całkowitą base-4 2103023, a następnie przekształcamy do postaci dziesiętnej w 9419celu uzyskania ostatecznego wyniku.


Zasady

  • Dane wejściowe zawsze będą prawidłowym, 4-stanowym kodem kreskowym, renderowanym w ASCII, jak określono powyżej, z opisaną sekwencją start / stop.
    • Możesz poprosić o końcowe spacje lub linie rozebrane, a także o spację nowej linii - w zależności od tego, który format pasuje do gry w golfa.
    • Może, ale nie musi być w prawidłowej orientacji - twój program musi ustalić, czy odczytać go do góry nogami, używając sekwencji start / stop.
    • Nie koduje wiodących cyfr zerowych w liczbie całkowitej base-4.
  • Możesz wziąć dane wejściowe jako listę linii lub ciąg znaków z nowymi liniami.
  • Dane wyjściowe powinny być liczbą całkowitą w standardowej podstawie liczb całkowitych w języku użytkownika, reprezentującą dane zakodowane przez kod kreskowy.
  • Ponieważ znaczki pocztowe są małe i mogą na nich zmieścić bardzo mało kodu, twój kod musi być możliwie jak najkrótszy: to jest gra w - więc wygrywa najkrótszy program (w bajtach)!

Przypadki testowe

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

= 4096 (odwrócony)

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

= 7313145 (odwrócony)

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

= 9419 (odwrócony)

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

= 990 (bez odwrócenia)

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

= 12345 (nieodwrócone)

FlipTack
źródło
-1 tytuły na dwóch postach nie są tego samego formatu. („P the P” vs „M my M”, wybierz „the” lub „my”: p)
Rɪᴋᴇʀ
1
Czy „lista linii” być dowolny [String], [{#Char}], [{Char}], [[Char]]?, Zważywszy, że Stringjest równoważna{#Char}
Οurous
3
@Ouros Co to za zapis? Podejrzewam, że odpowiedź brzmi „tak”, ponieważ typy danych są bardzo różne w różnych językach, więc wyzwania w zakresie kodowania ogólnie akceptują „niezależnie od tego, jaki ekwiwalent występuje w twoim języku”, ale nie mam pojęcia, jakie różne reprezentacje próbujesz reprezentować.
IMSoP,
1
Co dalej? Czy wysłać e-mail? Przesłać telegram? Przetworzyć pocztę?
Sanchises,
1
@Ourous tak, typ danych jest elastyczny, jak opisano w IMSoP.
FlipTack,

Odpowiedzi:

5

Łuska , 16 bajtów

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

Wypróbuj online!

Dane wejściowe to lista wierszy (łącze TIO używa łańcucha wielowierszowego dla zachowania przejrzystości). Linie muszą mieć równe długości i nie mogą być dodatkowe spacje końcowe.

Wyjaśnienie

ḋṁẊ=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
źródło
3

Python 2 , 113 105 bajtów

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

Wypróbuj online!

Pręt
źródło
2

Retina , 71 bajtów

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

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

Wypróbuj online! Link zawiera mniejsze przypadki testowe. Wymaga, aby pierwsza i ostatnia linia była wypełniona spacją do długości linii środkowej. Wyjaśnienie:

(.).
$1

Usuń niepotrzebne spacje.

sO$^`^\|.*|.

Odwróć znaki w kodzie, ale jeśli kod paskowy zaczyna się od a |, wybierz cały kod, w przeciwnym razie podziel go na znaki. Następnie odwróć je. Spowoduje to odwrócenie kodu, jeśli zaczyna się od 0.

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

Usuń sekwencję start / stop i środkowy wiersz (który nie jest dla nas przydatny).

\|
 |
+`\| 
 ||||

Konwertuj spacje |is z bazy 4 na unary.

.*¶$
$&$&

Podwój ostatnią linię.

\|

Konwertuj na dziesiętny.

Neil
źródło
2

Java (OpenJDK 8) , 181 160 bajtów

Nie jestem zbyt odrażający jak na rozwiązanie Java, jestem pewien, że mogę dokonać optymalizacji, ale już na to gapiłem się zbyt długo.

Zmniejsz kilka bajtów, skracając pętlę zamiast używając podciągów.

Grał w golfa

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

Wypróbuj online!

Bez golfa

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
źródło
Właśnie wypróbowałem swój kod, ale z odwróconym kodem kreskowym z przykładu „| | |” „| | | | | | | | | | | |” i daj mi 1024, Ok, nie mogę sformatować tego, ale ten na przykładzie, ale wypróbuj przykład, który masz, ale bez cofania go, może zrobiłem zły wpis :)
Java Gonzar
@JavaGonzalezArribas Próbowałem pierwszego przykładu (bez odwrócenia) i wydaje się, że działa dobrze. Czy to możliwe, że umieściłeś jedną za mało spacji w pierwszym wierszu danych wejściowych?
Luke Stevens,
To prawdopodobnie jest problem, świetna odpowiedź :)
Java Gonzar
Zaproponuj l+~izamiastl-1-i
ceilingcat
2

Java 8 , 208 166 157 151 bajtów

Wypróbowanie go, prawdopodobnie może być lepsze, zmniejszyło 42 z powodu niepotrzebnych kontroli, -9 usunięcie zmiennych, -6 dzięki Luke Stevens

Dane wejściowe to 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;}

bez golfa:

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
źródło
1
Jeśli używasz tablicy znaków, a nie Ciągów, możesz sprawdzić | używając> 32 zamiast == "|" co oszczędza 2 bajty na każde użycie (ogółem 6). Możesz również usunąć nawiasy kwadratowe wokół a, kiedy deklarujesz lambda dla kolejnych dwóch bajtów.
Luke Stevens,
2

Czysty , 191 ... 161 144 bajtów

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

Wypróbuj online!

Obrzydliwe
źródło
1

Pip , 46 43 42 bajty

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

Pobiera wiersze kodu kreskowego jako trzy argumenty wiersza poleceń. Pierwsza i trzecia linia muszą być wypełnione do długości drugiej linii spacjami. Wypróbuj online!

Wyjaśnienie

Najpierw trochę przygotowań:

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

Teraz zauważ, że jeśli zignorujemy środkowy wiersz i traktujemy |jako 1 i jako 0, każdy słupek jest tylko 2-bitową liczbą binarną:

(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
źródło
1

Łuska , 39 38 bajtów

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

Pobiera dane wejściowe jako listę ciągów: Wypróbuj online lub wypróbuj pakiet testowy!

Wyjaśnienie

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
ბიმო
źródło
1

Perl 5 , 152 + 2 (-F ) bajtów

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

Wypróbuj online!

Xcali
źródło
0

Oktawa , 80 75 68 bajtów

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

Wypróbuj online!

Co ciekawe, bi2dedomyślny MSB jest po prawej stronie, a nie po lewej stronie, co prowadzi do pewnych bólów głowy podczas jego tworzenia ... Myślę, że powinienem mieć optymalny sposób odwrócenia tablicy przed jej zindeksowaniem, ale istnieje bardzo wiele sposobów na zrobienie tego ( zarówno w pierwszej indeksacji lub z flipud, fliplr, rot90, '(transpozycji), ostateczna indeksowanie ...). Pobiera prostokątny układ ze spacjami |is (wymagane są spacje końcowe)

@(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
źródło
0

JavaScript (ES6), 184 181 bajtów

Nie jestem doświadczonym golfistą - jestem pewien, że można to poprawić, ale uwielbiałem to wyzwanie! Zawsze zastanawiałem się nad tymi znakami.

Funkcja fprzyjmuje listę ciągów znaków z wymaganymi końcowymi spacjami. Nowe wiersze dodane do kodu poniżej dla przejrzystości (nieuwzględnione w liczbie bajtów).

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)

Stosowanie

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

Wersja bez golfa z wyjaśnieniem

// 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.
źródło