Parsing Parcel

24

Terima kasih atas bantuan Anda dalam tantangan Mark My Mail , PPCG-Post telah berhasil mencap semua paketnya dengan barcode yang dihasilkan!

Sekarang, saatnya untuk memecahkan kode mereka.

Dalam tantangan ini, program Anda akan, dengan memberikan barcode yang dihasilkan dari tantangan Mark My Mail , mendekodekannya dan mengembalikan integer yang disandikan.

Tapi hati-hati! Barcode mungkin terbalik ...


Barcode 4-negara

Jika Anda melewatkan tantangan pengodean, Anda harus tahu jenis barcode apa yang sedang kita bicarakan. Barcode 4-negara adalah bar baris dengan empat kemungkinan status, masing-masing mewakili bilangan bulat basis-4:

            |       |
Bar:    |   |   |   |
                |   |

Digit:  0   1   2   3

Dirender dalam ASCII, barcode akan mengambil tiga baris teks, menggunakan karakter pipe ( |) untuk mewakili bagian dari bar, dan spasi ( ) untuk mewakili bagian kosong. Akan ada satu ruang di antara setiap bar. Contoh barcode mungkin terlihat seperti ini:

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

Untuk mengonversi kode batang kembali ke bilangan bulat yang disandikannya, petakan setiap bilah ke basis-4 digit yang sesuai, gabungkan ini, dan ubah menjadi desimal.

Karena setiap barcode juga akan mewakili barcode yang berbeda ketika terbalik, kami menerapkan urutan mulai / berhenti sehingga orienasi dapat dihitung. Untuk tujuan tantangan ini, kami akan menggunakan urutan start / stop yang ditentukan oleh Australia Post: setiap barcode dimulai dan diakhiri dengan 1 0urutan.


Tantangan

Tugas Anda adalah, mengingat barcode ASCII 4-state, menguraikannya dan mengembalikan integer yang dikodekannya - pada dasarnya kebalikan dari Mark My Mail .

Tapi untuk meningkatkannya, ada tangkapan - barcode mungkin terbalik. Seperti di dunia nyata, itu akan diserahkan kepada pembaca barcode (program Anda) untuk menentukan orientasi yang benar menggunakan urutan start / stop.

Contoh:

Diberikan barcode berikut:

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

Kita dapat dengan jelas melihat bahwa pasangan angka pertama dan terakhir adalah 0, 2dan bukan 1, 0. Ini berarti bahwa barcode terbalik - jadi kita harus memutarnya 180 derajat (tidak hanya membalik setiap batang) untuk mencapai orientasi yang benar:

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

Sekarang, kita dapat memulai decoding. Kami memetakan setiap bilah ke basis-4 digit yang sesuai, mengabaikan urutan mulai / berhenti karena mereka tidak menyandikan data.

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

- - 2 1 0 3 0 2 3 - -

Kami menggabungkan ini ke integer basis-4 2103023, lalu mengonversinya menjadi representasi desimal 9419untuk hasil akhir.


Aturan

  • Input akan selalu berupa barcode 4-negara yang valid, yang diberikan dalam ASCII sebagaimana dijelaskan di atas, dengan urutan mulai / henti yang dijelaskan.
    • Anda dapat meminta spasi tambahan, atau garis stripping, serta baris baru tambahan - format apa pun yang sesuai dengan golf Anda.
    • Mungkin atau mungkin tidak dalam orientasi yang benar - program Anda harus menentukan apakah akan membacanya terbalik, dengan menggunakan urutan start / stop.
    • Ini tidak akan menyandikan angka nol di bilangan bulat basis-4.
  • Anda dapat mengambil input sebagai daftar baris, atau string dengan baris baru.
  • Outputnya harus berupa bilangan bulat di basis integer standar bahasa Anda, mewakili data yang disandikan oleh barcode.
  • Karena prangko berukuran kecil dan dapat memuat kode yang sangat sedikit, kode Anda harus sesingkat mungkin: ini adalah - sehingga program terpendek (dalam byte) menang!

Uji Kasus

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

= 4096 (terbalik)

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

= 7313145 (terbalik)

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

= 9419 (dibalik)

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

= 990 (tidak terbalik)

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

= 12345 (tidak terbalik)

FlipTack
sumber
-1 judul pada dua posting bukan format yang sama. ("P the P" vs "M my M", pilih 'the' atau 'my': p)
Rɪᴋᴇʀ
1
Akan "daftar baris" menjadi salah [String], [{#Char}], [{Char}], [[Char]]?, Mengingat bahwa Stringini setara dengan{#Char}
Οurous
3
@Ouros Notasi apa itu? Saya sangat curiga jawabannya adalah "ya", karena tipe data sangat berbeda antara bahasa, jadi tantangan pengkodean umumnya menerima "apa pun yang setara dalam bahasa Anda", tapi saya tidak tahu apa representasi berbeda yang Anda coba wakili.
IMSoP
1
Apa berikutnya? Kirim email? Kirim Telegram? Memproses Posting?
Sanchises
1
@Our ya, tipe data fleksibel, seperti yang dijelaskan IMSoP.
FlipTack

Jawaban:

5

Sekam , 16 byte

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

Cobalah online!

Input adalah daftar baris (tautan TIO menggunakan string multiline untuk kejelasan). Garis harus memiliki panjang yang sama, dan tidak boleh ada spasi tambahan.

Penjelasan

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

Python 2 , 113 105 byte

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

Cobalah online!

tongkat
sumber
2

Python 2 , 96 byte

lambda a:int(`[2*(r==q)+(p==q)for p,q,r in zip(*a[::(a>'|')*2-1].split('\n'))[4:-4:2]]`[1::3],4)

Cobalah online!

Lynn
sumber
2

Retina , 71 byte

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

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

Cobalah online! Tautan mencakup test case yang lebih kecil. Membutuhkan garis pertama dan terakhir harus berlapis ruang hingga panjang garis tengah. Penjelasan:

(.).
$1

Hapus spasi yang tidak perlu.

sO$^`^\|.*|.

Membalikkan karakter dalam kode, tetapi jika kode batang dimulai dengan |, maka pilih seluruh kode, jika tidak pisahkan menjadi karakter. Kemudian, balikkan. Ini membalik kode jika dimulai dengan a 0.

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

Hapus urutan mulai / hentikan dan baris tengah (yang tidak berguna bagi kami).

\|
 |
+`\| 
 ||||

Ubah spasi dan |s dari basis 4 ke unary.

.*¶$
$&$&

Gandakan baris terakhir.

\|

Konversikan ke desimal.

Neil
sumber
2

Java (OpenJDK 8) , 181 160 byte

Tidak terlalu buruk untuk solusi java, saya yakin ada optimisasi yang bisa saya buat, tapi saya sudah terlalu lama melihatnya.

Kurangi beberapa byte dengan memperpendek loop daripada menggunakan substring.

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

Cobalah online!

Tidak disatukan

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
sumber
Baru saja mencoba kode Anda tetapi dengan barcode terbalik dari contoh "| | |" "| | | | | | | | | |" dan beri saya 1024, Ok saya tidak bisa memformat ini, tetapi yang pada contoh tetapi, coba contoh yang Anda miliki tetapi tanpa membalikkannya, mungkin saya melakukan input yang buruk :)
Java Gonzar
@JavaGonzalezArribas Saya mencoba contoh pertama (tidak terbalik) dan sepertinya berfungsi dengan baik. Mungkinkah Anda menempatkan satu spasi terlalu sedikit di baris pertama input?
Luke Stevens
Itu mungkin masalahnya, jawaban yang bagus :)
Java Gonzar
Sarankan l+~ialih-alihl-1-i
ceilingcat
2

Java 8 , 208 166 157 151 byte

Cobalah, mungkin bisa lebih baik, dikurangi 42 karena cek yang tidak perlu, -9 menghapus variabel, -6 terima kasih kepada Luke Stevens

Masukan adalah 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;
}
Java Gonzar
sumber
1
Jika Anda menggunakan array karakter daripada Strings, Anda dapat memeriksa | dengan menggunakan> 32 daripada == "|" yang menghemat 2 byte untuk setiap penggunaan (6 keseluruhan). Anda juga dapat menghapus tanda kurung di sekitar saat mendeklarasikan lambda untuk dua byte lainnya.
Luke Stevens
2

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

Cobalah online!

Suram
sumber
1

Pip , 46 43 42 byte

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

Mengambil baris barcode sebagai tiga argumen baris perintah. Baris pertama dan ketiga harus diisi dengan panjang baris kedua dengan spasi. Cobalah online!

Penjelasan

Pertama beberapa persiapan:

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

Sekarang amati bahwa jika kita mengabaikan baris tengah dan memperlakukan |sebagai 1 dan 0, setiap bilah hanyalah angka biner 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
DLosc
sumber
1

Sekam , 39 38 byte

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

Mengambil input sebagai daftar string: Cobalah online atau coba test-suite!

Penjelasan

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
ბიმო
sumber
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$\

Cobalah online!

Xcali
sumber
0

Oktaf , 80 75 68 byte

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

Cobalah online!

Anehnya, bi2dedefault MSB di kanan daripada kiri, menyebabkan beberapa sakit kepala sementara saya membuat ini ... saya pikir saya harus memiliki cara optimal membalik array sebelum mengindeks itu, tetapi ada sangat banyak cara untuk melakukannya ( baik dalam pengindeksan pertama, atau dengan flipud, fliplr, rot90, '(transpose), pengindeksan akhir ...). Mengambil array persegi panjang dengan spasi dan |s (jadi, dibutuhkan spasi tambahan)

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

JavaScript (ES6), 184 181 byte

Saya bukan pegolf berpengalaman - saya yakin ini bisa ditingkatkan, tetapi saya menyukai tantangan ini! Saya selalu bertanya-tanya tentang tanda-tanda itu.

Fungsi fmengambil daftar string dengan spasi tambahan yang dibutuhkan. Baris baru ditambahkan ke kode di bawah ini untuk kejelasan (tidak termasuk dalam jumlah 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)

Pemakaian

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

Versi tidak dikoleksi dengan penjelasan

// 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.
sumber