Decode string


41

Ini tantangan pertama saya di ppcg!

Memasukkan

String yang terdiri dari dua karakter ascii yang berbeda. Sebagai contoh

ABAABBAAAAAABBAAABAABBAABA

Tantangan

Tugasnya adalah untuk memecahkan kode string ini mengikuti aturan berikut:

  1. Lewati dua karakter pertama
  2. Pisahkan sisa string menjadi grup 8 karakter
  3. Di setiap grup, ganti setiap karakter dengan 0jika karakter itu sama dengan karakter pertama dari string asli, dan dengan yang 1lain
  4. Sekarang setiap grup mewakili byte. Ubah setiap grup menjadi karakter dari kode karakter byte
  5. Menggabungkan semua karakter

Contoh

Mari kita decode string di atas.

 AB  AABBAAAA  AABBAAAB  AABBAABA
 ^^     ^         ^         ^
 |      |         |         |
 |      \---------|---------/
 |                |
Skip      Convert to binary

Perhatikan bahwa itu Aadalah karakter pertama dalam string asli dan Byang kedua. Karena itu, ganti masing A- masing dengan 0dan masing B- masing dengan 1. Sekarang kami memperoleh:

00110000  00110001  00110010

yang ada [0x30, 0x31, 0x32]dalam biner. Nilai-nilai ini mewakili karakter ["0", "1", "2"]masing-masing, sehingga hasil akhirnya seharusnya 012.

Mencetak gol

Ini, tentu saja, , yang berarti membuat kode Anda sesingkat mungkin. Skor diukur dalam byte.

Batasan dan format IO

Aturan standar berlaku. Berikut ini beberapa aturan tambahan:

  • Anda dapat menerima input yang valid
    • String input terdiri dari tepat dua karakter yang berbeda
    • Dua karakter pertama berbeda
    • Panjang minimal dari string input adalah 2 karakter
    • Panjangnya akan selalu memberikan 2 modulo 8
  • Anda dapat menganggap bahwa string hanya akan selalu terdiri dari karakter ASCII yang dapat dicetak
    • Baik dalam input maupun dalam string yang diterjemahkan
  • Whitespace terkemuka dan tertinggal diizinkan dalam output (semua yang cocok /\s*/)

5
Harus dikatakan kawan, untuk tantangan pertama, ini adalah salah satu tantangan terformat yang lebih baik yang pernah saya lihat. Sebagai fyi, kotak pasir komunitas adalah tempat yang bagus untuk umpan balik sebelum memposting sehingga Anda tidak akan dibom secara acak karena aturan yang tidak Anda ketahui.
Magic Gurita Guci

@MagicOctopusUrn. Terima kasih! Tidak tahu tentang sandbox, saya akan memposting di sana lain kali :)

2
Saya sebagian besar menggunakannya sehingga orang dapat memanggil saya keluar pada pertanyaan duplikat, sangat sederhana untuk mengikuti aturan, agak sulit untuk mengetahui tentang dupes tanpa menghafal meta :). Saya juga merekomendasikan untuk memeriksa ruang obrolan, kami memiliki obrolan untuk hampir setiap bahasa yang Anda bisa berharap untuk belajar dan pertanyaan didorong.
Magic Gurita Guci

1
Tantangan besar pertama! Beberapa kasus uji lagi akan rapi.
Lynn

Tantangan pertama yang sangat bagus. Bersenang-senang bermain dengan yang satu ini.
ElPedro

Jawaban:



8

Stax , 15 11 byte

ó║¥U⌂½íèäöñ

Jalankan dan debug di staxlang.xyz!

Pendekatan cepat dan kotor. Bekerja untuk memperbaikinya. Memperbaikinya!

Dibongkar (13 byte) dan penjelasan

2:/8/{{[Im:bm
2:/              Split at index 2. Push head, then tail.
   8/            Split into length-8 segments.
     {      m    Map block over each segment:
      {  m         Map block over each character:
       [             Copy first two elements (below) in-place.
        I            Index of character in first two characters.
          :b       Convert from binary.
                 Implicit print as string.

Ahhhh ... Aku tahu ini akan mengalahkan kita.
Magic Gurita Guci

6

JavaScript (Node.js) , 67 byte

s=>s.replace(/./g,x=(c,i)=>(x=x*2|c==s[1],Buffer(i<3|i&7^1?0:[x])))

Cobalah online!

Bagaimana?

Kami menggunakan dua sintaks yang berbeda dari Bufferkonstruktor:

  • Buffer([n])menghasilkan buffer yang berisi byte tunggal n dan dipaksa ke karakter ASCII yang sesuai. Hanya 8 bit n paling signifikan yang dipertimbangkan.
  • Buffer(n)menghasilkan buffer n byte. Oleh karena itu, Buffer(0)menghasilkan buffer kosong, yang dipaksa ke string kosong.

Catatan: Keduanya tidak digunakan lagi dalam versi Node terbaru. Buffer.from([n])dan Buffer.alloc(n)harus digunakan sebagai gantinya.

Berkomentar

s =>                   // given the input string s
  s.replace(/./g, x =  // initialize x to a non-numeric value (will be coerced to 0)
    (c, i) => (        // for each character c at position i in s:
      x = x * 2 |      //   shift x to the left
          c == s[1],   //   and append the new bit, based on the comparison of c with s[1]
      Buffer(          //   invoke the constructor of Buffer (see above):
        i < 3 |        //     if i is less than 3
        i & 7 ^ 1 ?    //     or i is not congruent to 1 modulo 8:
          0            //       replace c with an empty string
        :              //     else:
          [x]          //       replace c with the ASCII char. whose code is the LSB of x
      )                //   end of Buffer constructor
  ))                   // end of replace(); return the new string

6

bash, 59 58 52 byte

tr -t "$1" 01 <<<$1|cut -c3-|fold -8|sed 'i2i
aP'|dc

Cobalah online!

Terima kasih kepada Sapi dukun untuk menghemat 6 byte.

Tantangan ini bekerja sangat baik dengan serangkaian coreutils (dan dcuntuk melakukan konversi dan output di akhir). Pertama, kita gunakan

tr -t "$1" 01 <<<$1

untuk mentransliterasikan dua karakter dalam input ke nol dan satu. The -tbendera memotong argumen pertama dengan panjang kedua, jadi ini untuk mengurangi transliterasi dua karakter pertama di input ke 0dan 1, yang adalah apa yang kita inginkan. Kemudian,

cut -c3-

menghapus dua karakter pertama, dan

fold -8

menghasilkan 8 karakter per baris. Akhirnya, sedperintah mengubah setiap baris menjadi dcpotongan yang membaca angka sebagai biner dan menampilkan byte tersebut.


Selalu menyenangkan untuk melihat jawaban bash :) Anda dapat menggunakan sed untuk menyederhanakan perhitungan dc dengan mengubah setiap baris menjadi kode dc yang mencetak setiap karakter dan kemudian mengevaluasi dalam dc tio.run/##S0oszvj/… (dan ruang setelah cut -cdapat dihapus)
Kritixi Lithos

6

Kode mesin Z80 pada BPK Amstrad, 32 31 30 byte

000001  0000  (9000)        ORG &9000
000002  9000  EB            EX DE, HL
000003  9001  46            LD B, (HL)
000004  9002  23            INC HL
000005  9003  5E            LD E, (HL)
000006  9004  23            INC HL
000007  9005  56            LD D, (HL)
000009  9006  1A            LD A, (DE)
000010  9007  05            DEC B
000011  9008  13            INC DE
000012  9009  4F            LD C, A
000014  900A                Light
000015  900A  26 01         LD H, &01
000016  900C                Last
000017  900C  13            INC DE
000018  900D  05            DEC B
000019  900E  C8            RET Z
000021  900F                Loop
000022  900F  1A            LD A, (DE)
000023  9010  B9            CP C
000024  9011  28 01         JR Z, Lable
000025  9013  37            SCF
000026  9014                Lable
000027  9014  ED 6A         ADC HL, HL
000028  9016  30 F4         JR NC, Last
000029  9018  7D            LD A, L
000030  9019  CD 5A BB      CALL &BB5A
000032  901C  18 EC         JR Light

Kode mengambil instruksi menggantikan setiap karakter dengan 0jika karakter itu sama dengan karakter pertama dari string asli, dan dengan 1sebaliknya secara harfiah dan tidak pernah repot untuk memeriksa bahwa karakter cocok dengan karakter kedua dalam string input. Itu hanya memeriksa sama-sebagai-karakter pertama dan berbeda-dari-karakter pertama.

Aku berlari keluar dari register (Z80 hanya memiliki 7 8-bit register mudah digunakan, petunjuk sisa perlu lagi) jadi aku meletakkan &01di H, bersama dengan menggunakan Luntuk membangun karakter ASCII (saya baru sadar itu tidak perlu untuk menginisialisasi L, menyimpan satu byte ). Ketika Hmeluap ke bendera Carry, karakter di Lsiap untuk menjadi output. Untungnya, ada 16-bit ADC( Ad dengan C arry) yang melakukan pekerjaan instruksi shift-kiri.

(DE)hanya bisa dibaca Ameskipun (HL)dapat dibaca ke register 8-bit, jadi itu adalah kompromi yang digunakan. Saya tidak dapat membandingkan (DE)dengan Csecara langsung, jadi saya harus memuatnya Aterlebih dahulu. Label hanyalah kata-kata acak yang dimulai dengan L(persyaratan assembler).

  • A Akumulator - satu-satunya register yang dapat melakukan perbandingan
  • Bregister register untuk instruksi DJNZ: D ecrement ( B) dan J ump jika N on Z ero . Dengan mengatur ulang kode, saya dapat melakukan pekerjaan DJNZdengan satu byte lebih sedikit
  • C karakter pertama dalam string input
  • D, Esebagai DEalamat karakter input saat ini
  • H pemicu carry (setiap loop ke-8)
  • L karakter keluaran sedang dibangun

masukkan deskripsi gambar di sini



5

J, 17 13 Bytes

u:_8#.\2}.1{=

-4 Terima kasih kepada FrownyFrog

Versi lama:

u:_8#.\2&({.i.}.)

Penjelasan:

u:_8#.\2}.1{=
            =  | Self classify, for each unique element x of y, compute x = y, element-wise
          1{   | Second row
       2}.     | Drop 2
  _8#.\        | Convert non-intersecting subarrays of length 8 from binary
u:             | Convert to characters

Contoh:

   = 'ABAABBAAAAAABBAAABAABBAABA'
1 0 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 0 1 1 0 0 1 1 0 1
0 1 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 1 0 0 1 1 0 0 1 0

   2}.1{= 'ABAABBAAAAAABBAAABAABBAABA'
0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 1 0 0 1 1 0 0 1 0

   _8#.\2}.1{= 'ABAABBAAAAAABBAAABAABBAABA'
48 49 50

   u:_8#.\2}.1{= 'ABAABBAAAAAABBAAABAABBAABA'
012

1
2}.1{=untuk menyimpan 4 byte.
FrownyFrog

Ya ampun ... Saya tidak dapat menemukan byte lain.
Magic Gurita Guci

1
@MagicOctopusUrn itu sebenarnya cuplikan, seharusnya ada [:di awal :)
FrownyFrog


5

R , 71 byte

function(s)intToUtf8(2^(7:0)%*%matrix((y=utf8ToInt(s))[-1:-2]==y[2],8))

Cobalah online!

Golf yang mengejutkan!

Pertama, ubah string menjadi ascii code-points with utf8ToInt, simpan sebagai y. Menghapus dua karakter pertama dengan pengindeksan negatif lebih pendek daripada menggunakan tail.

Array y[-1:-2]==y[2]sama dengan bit ketika %*%(perkalian matriks) diterapkan, tetapi pertama-tama kita membentuk kembali array menjadi matrixdengan nrow=8, mengkonversi dari array linier ke byte pengelompokan. Kebetulan, kita kemudian dapat mengkonversi ke titik kode ascii menggunakan perkalian matriks dengan kekuatan yang sesuai dari 2 2^(7:0),, dan kemudian kita mengubah titik kode kembali ke string dengan intToUtf8.



4

PHP, 73 71 byte

while($s=substr($argn,-6+$i+=8,8))echo~chr(bindec(strtr($s,$argn,10)));

Jalankan sebagai pipa dengan -nRatau coba online .

golf:

  • mulai indeks pada -6dan pra-kenaikan oleh8
  • mengeksploitasi yang strtrmengabaikan karakter berlebihan di parameter yang lebih panjang (tidak substrdiperlukan)
  • menerjemahkan ke 10dan kemudian membalik tidak perlu tanda kutip -> -1 byte
  • invert karakter alih-alih kode ascii -> ~berfungsi sebagai batas kata -> -1 byte.

3
Setidaknya Anda harus mencocokkan brainfuck:for(;$s=substr($argn,2+8*$i++,8);)echo~chr(bindec(strtr($s,$argn,10)));
Christoph

2
@Christoph Saya suka bagaimana Brainfuck tiba-tiba menjadi standar untuk panjang jawaban yang masuk akal.
Nit

4

Pyth, 20 9 byte

CittxLQQ2

Disimpan 11 byte berkat FryAmTheEggman.

Coba di sini

Penjelasan

CittxLQQ2
    xLQQ    Find the index of each character in the string.
  tt        Exclude the first 2.
 i      2   Convert from binary.
C           Get the characters.

@FryAmTheEggman Terima kasih. Jelas saya masih harus banyak belajar tentang Pyth.
Mnemonic

Haha, aku juga! Ini adalah bahasa golf yang sangat rumit. Saya harap Anda terus bermain golf di dalamnya :)
FryAmTheEggman

3

Ruby , 82 79 byte

->s{s[2..-1].tr(s[0,2],'01').chars.each_slice(8).map{|s|s.join.to_i(2).chr}*''}

Cobalah online!


1
Selamat datang di PPCG! Saya tidak melihat bahwa sudah ada jawaban di Ruby sebelum saya memposting milik saya, tetapi beberapa trik golf tipikal berlaku untuk pendekatan Anda juga - misalnya, yang terakhir .joindapat digantikan oleh *'', dan s[0..1]oleh s[0,2].
Kirill L.

3

Japt, 11 byte

¤£bXÃò8 ®Íd

Cobalah


Penjelasan

¤               :Slice from the 3rd character
 £  Ã           :Map over each X
  bX            :  Get the first 0-based index of X in the input
     ò8         :Split to an array of strings of length 8
        ®       :Map
         Í      :  Convert from base-2 string to base-10 integer
          d     :  Get the character at that codepoint

Penggunaan s2pintasan yang sangat pintar , bagus.
Nit

3

PHP + GNU Multi Precision, 63 61

<?=gmp_export(gmp_init(substr(strtr($argn,$argn,"01"),2),2));

sayangnya ekstensi GMP tidak diaktifkan secara default (tetapi dikirimkan).

Jalankan seperti ini:

echo "ABABABAAAAABABAAAAAABAABBAABAAAABBABAAABBB" | php -F a.php

<?=menghemat 2 byte dan mungkin hari itu. ;-)
Titus

@Itus ya tapi sayangnya tidak berhasil -R(saya mencoba).
Christoph

1
coba -Fsaja
Titus


3

Java 8, 143 142 141 byte

s->{char i=47;for(;++i<50;)s=s.replace(s.charAt(i%2),i);for(i=2;i<s.length();)System.out.print((char)Long.parseLong(s.substring(i,i+=8),2));}

-1 byte terima kasih kepada @ OlivierGrégoire .

Cobalah online.

Penjelasan:

s->{                            // Method with String parameter and no return-type
  char i=47;                    //  Index character, starting at 47
  for(;++i<50;)                 //  Loop 2 times
    s.replace(s.charAt(i%2),i)  //   Replace first characters to 0, second characters to 1
  for(i=2;i<s.length();)        //  Loop `i` from 2 upwards over the String-length
    System.out.print(           //   Print:
     (char)                     //    As character:
      Long.parseLong(           //     Convert Binary-String to number
       s.substring(i,i+=8)      //      The substring in range [i,i+8),
      ,2));}



2

APL + WIN, 30 byte

Indeks asal 0. Anjuran untuk input string

⎕av[2⊥¨(+\0=8|⍳⍴b)⊂b←2↓s≠↑s←⎕]

Penjelasan:

s≠↑s←⎕ prompts for string and creates binary vector not equal to first character

b←2↓s drops first two elements of binary

(+\0=8|⍳⍴b)⊂ splits binary into groups of 8

2⊥¨ converts each group to decimal

⎕av[...] displays decoded characters

Saya menganggap Quad-AV sejalan dengan ASCII untuk APL + WIN?
Zacharý

@ Zacharý Ya untuk 128 karakter pertama. Karakter APL khusus menggantikan beberapa karakter dalam rangkaian karakter ASCII yang diperluas.
Graham

2

Merah , 110 byte

func[s][t: 0 i: 128 foreach c next next s[if c = s/2[t: t + i]i: i / 2 if i = 0[prin to-char t t: 0 i: 128]]] 

Cobalah online!

Penjelasan:

Solusi mudah dan sederhana, tanpa builtin.

f: func [s] [                      ; s is the argument (string)
    t: 0                           ; total - initially 0
    i: 128                         ; powers of 2, initially 0
    b: s/2                         ; b is the second charachter
    foreach c next next s [        ; for each char in the input string after the 2nd one
        if c = b [t: t + i]        ; if it's equal to b than add the power of 2 to t
        i: i / 2                   ; previous power of 2
        if i = 0 [                 ; if it's 0 
            prin to-char t         ; convert t to character and print it
            t: 0                   ; set t to 0
            i: 128                 ; i to 128
        ]
    ]
] 

2

Google Sheets, 123 byte

=ArrayFormula(Join("",IfError(Char(Bin2Dec(Substitute(Substitute(Mid(A1,3+8*(Row(A:A)-1),8),Left(A1),0),Mid(A1,2,1),1))),""

Input ada di sel A1. Google akan secara otomatis menambahkan )))ke akhir formula.

Penjelasan:

  • Mid(A1,3+8*(Row(A:A)-1),8) meraih potongan karakter 8 sekaligus, dimulai dengan yang ketiga.
  • Substitute(Mid(~),Left(A1),0) mengganti setiap instance dari karakter pertama dengan 0.
  • Substitute(Substitute(~),Mid(A1,2,1),1) mengganti karakter kedua dengan 1.
  • Char(Bin2Dec(Substitute(~))) mengubah chunk ke desimal dan kemudian ke ASCII.
  • IfError(Char(~,""))mengoreksi semua kesalahan yang dihasilkan dari fakta yang Row(A:A)mengembalikan nilai jauh lebih banyak daripada yang kami Bin2Decberikan kepada kami banyak nilai nol dan Charkesalahan keluar dari nol.
  • ArrayFormula(Join("",IfError(~)))bergabung bersama semua Charhasil dan ArrayFormulainilah yang membuat Row(A:A)pengembalian array nilai bukan hanya nilai pertama.




2

Python 2 , 88 byte

i=input()
f=''.join('10'[x==i[0]]for x in i[2:])
while f:print chr(int(f[:8],2));f=f[8:]

Cobalah online!

Bukan yang terpendek - hanya cara alternatif.

Versi berikut mencetak output pada satu baris untuk 98 byte meskipun aturan menyatakan bahwa trailing spasi diperbolehkan .:

i=input();f=''.join('10'[x==i[0]]for x in i[2:]);o=""
while f:o+=chr(int(f[:8],2));f=f[8:]
print o

Cobalah online!


Hasil akhir harus dalam satu baris, bukan tiga.
idrougge

Dari OP: "Leading and trailing whitespace diizinkan dalam output (semua yang cocok dengan / \ s * /)". Pertandingan baris baru /\s*/.
ElPedro

1
Maaf, saya tidak cukup berpengalaman dalam notasi regex. : /
idrougge

Saya dan saya juga tidak
meng-




1

Haskell , 124 105 93 byte

f(x:_:y)=fromEnum.(/=x)<$>y
g[]=[]
g s=(toEnum.sum.zipWith((*).(2^))[7,6..0])s:g(drop 8s)
g.f

Cobalah online!

fmengubah string menjadi daftar bit dengan membandingkan setiap karakter dengan yang pertama, mengubah Bools menjadi nol dan yang dengan fromEnum. gmembagi daftar ini menjadi kelompok 8, mengubahnya menjadi desimal, dan mengambil nilai dari angka yang dihasilkan sebagai Enum, yang Charmerupakan turunan dari.

Perubahan:

  • -19 byte berkat @Laikoni (menghapus impor, menanamkan mapke dalam fungsi)
  • -12 byte terinspirasi oleh jawaban @ Lynn (menyingkirkan takedengan zip dengan daftar pendek)

2
Anda dapat menggunakan toEnumalih-alih chrdan menjatuhkan impor. Juga mapdapat dimasukkan ke dalam g. Ruang antar 8 sbisa dihilangkan.
Laikoni

1

Keempat (gforth) , 83 byte

: f over c@ 0 rot 2 do 2* over i 4 pick + c@ <> - i 8 mod 1 = if emit 0 then loop ;

Cobalah online!

Input adalah string Keempat standar (alamat dan panjang) output dicetak ke stdout

Penjelasan

over c@          \ get the value of the first character in the string
0 rot            \ add a starting "byte" value of 0 and put the length on top of the stack
2 do             \ start a loop from 2 to length-1
   2*            \ multiply the current byte value by 2 (shift "bits" left one)
   over          \ copy the reference char to the top of the stack
   i 4 pick +    \ add the index and the starting address to get address of the current char
   c@ <>         \ get the char at the address and check if not equal to the reference char
   -             \ subtract the value from our bit count, -1 is default "true" value in forth
   i 8 mod 1 =   \ check if we are at the last bit in a byte
   if            \ if we are
      emit 0     \ print the character and start our new byte at 0
   then          \ and end the if statement
loop             \ end the loop
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.