Giải mã chuỗi


41

Đây là thử thách đầu tiên của tôi trên ppcg!

Đầu vào

Một chuỗi bao gồm hai ký tự ascii khác nhau. Ví dụ

ABAABBAAAAAABBAAABAABBAABA

Thử thách

Nhiệm vụ là giải mã chuỗi này theo các quy tắc sau:

  1. Bỏ qua hai ký tự đầu tiên
  2. Chia phần còn lại của chuỗi thành các nhóm 8 ký tự
  3. Trong mỗi nhóm, thay thế mỗi ký tự bằng 0nếu ký tự đó giống với ký tự đầu tiên của chuỗi gốc và 1ngược lại
  4. Bây giờ mỗi nhóm đại diện cho một byte. Chuyển đổi từng nhóm thành ký tự từ mã byte byte
  5. Nối tất cả các nhân vật

Thí dụ

Hãy giải mã chuỗi trên.

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

Lưu ý rằng đó Alà ký tự đầu tiên trong chuỗi gốc và Blà ký tự thứ hai. Do đó, thay thế từng Avới 0và mỗi Bvới 1. Bây giờ chúng tôi có được:

00110000  00110001  00110010

đó là [0x30, 0x31, 0x32]trong nhị phân. Các giá trị này đại diện cho các ký tự ["0", "1", "2"]tương ứng, vì vậy đầu ra cuối cùng phải là 012.

Chấm điểm

Tất nhiên, đây là , có nghĩa là làm cho mã của bạn càng ngắn càng tốt. Điểm được đo bằng byte.

Ràng buộc và định dạng IO

Quy tắc tiêu chuẩn áp dụng. Dưới đây là một số quy tắc bổ sung:

  • Bạn có thể giả sử đầu vào hợp lệ
    • Chuỗi đầu vào bao gồm chính xác hai ký tự khác nhau
    • Hai nhân vật đầu tiên khác nhau.
    • Độ dài tối thiểu của chuỗi đầu vào là 2 ký tự
    • Độ dài sẽ luôn cho 2 modulo 8
  • Bạn có thể giả sử chuỗi sẽ luôn chỉ bao gồm các ký tự ASCII có thể in
    • Cả trong đầu vào và trong chuỗi giải mã
  • Khoảng trắng hàng đầu và dấu được cho phép trong đầu ra (mọi thứ khớp /\s*/)

5
Phải nói rằng, đối với thử thách đầu tiên, đây là một trong những thử thách được định dạng tốt hơn tôi từng thấy. Là một fyi, hộp cát cộng đồng là một nơi tuyệt vời để phản hồi trước khi đăng để bạn không bị ném bom ngẫu nhiên cho một quy tắc mà bạn không biết.
Bạch tuộc ma thuật Urn

@MagicOctopusUrn. Cảm ơn bạn! Không biết về hộp cát, tôi sẽ đăng ở đó vào lần tới :)

2
Tôi chủ yếu sử dụng nó để mọi người có thể gọi tôi ra các câu hỏi trùng lặp, rất đơn giản để tuân theo các quy tắc, khá khó để biết về bản sao mà không cần ghi nhớ meta :). Tôi cũng khuyên bạn nên kiểm tra các phòng chat, chúng tôi có các cuộc trò chuyện cho hầu hết mọi ngôn ngữ mà bạn có thể hy vọng học và các câu hỏi được khuyến khích.
Bạch tuộc ma thuật Urn

1
Thử thách đầu tiên tuyệt vời! Một số trường hợp thử nghiệm sẽ được gọn gàng.
Lynn

Thử thách đầu tiên thực sự tốt đẹp. Có niềm vui chơi với cái này.
ElPedro

Câu trả lời:



8

Stax , 15 11 byte

ó║¥U⌂½íèäöñ

Chạy và gỡ lỗi nó tại staxlang.xyz!

Cách tiếp cận bẩn 'nhanh'. Làm việc để cải thiện nó. Cải thiện nó!

Giải nén (13 byte) và giải thích

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 ... tôi biết điều này sẽ đánh bại chúng tôi.
Bạch tuộc ma thuật Urn

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

Hãy thử trực tuyến!

Làm sao?

Chúng tôi sử dụng hai cú pháp khác nhau của hàm Buffertạo:

  • Buffer([n])tạo một bộ đệm chứa byte n duy nhất và được ép buộc vào ký tự ASCII tương ứng. Chỉ có 8 bit có ý nghĩa nhỏ nhất của n được xem xét.
  • Buffer(n)tạo ra một bộ đệm gồm n byte. Do đó, Buffer(0)tạo ra một bộ đệm trống, được ép buộc thành một chuỗi rỗng.

Lưu ý: Cả hai đều không dùng nữa trong các phiên bản Node gần đây. Buffer.from([n])Buffer.alloc(n)nên được sử dụng thay thế.

Đã bình luận

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

Hãy thử trực tuyến!

Nhờ có quẻ bò để lưu 6 byte.

Thử thách này hoạt động rất tốt với một loạt các coreutils (và dcđể thực hiện chuyển đổi và đầu ra ở cuối). Đầu tiên, chúng tôi sử dụng

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

để phiên âm hai ký tự trong đầu vào thành số 0 và ký tự. Các -tcờ truncates đối số đầu tiên với độ dài của thứ hai, vì vậy điều này làm giảm đến chuyển ngữ hai ký tự đầu tiên trong đầu vào 01, đó là những gì chúng ta muốn. Sau đó,

cut -c3-

xóa hai ký tự đầu tiên và

fold -8

xuất ra 8 ký tự trên mỗi dòng. Cuối cùng, sedlệnh biến mỗi dòng thành một dcđoạn mã đọc số dưới dạng nhị phân và xuất ra byte đó.


Luôn luôn rất tuyệt khi thấy câu trả lời bash :) Bạn có thể sử dụng sed để đơn giản hóa các phép tính dc bằng cách chuyển đổi từng dòng thành mã dc in ra từng ký tự và sau đó đánh dấu nó trong dc tio.run/##S0oszvj/, (và không gian sau cut -ccó thể được gỡ bỏ)
Kritixi Lithos

6

Mã máy Z80 trên CPC 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

Mã này có hướng dẫn thay thế mỗi nhân vật với 0nếu nhân vật đó là giống như ký tự đầu tiên của chuỗi ban đầu, và với 1trường hợp theo nghĩa đen và không bao giờ bận tâm để kiểm tra xem một nhân vật phù hợp với nhân vật thứ hai trong chuỗi đầu vào. Nó chỉ kiểm tra cùng ký tự đầu tiên và khác với ký tự đầu tiên.

Tôi chạy ra khỏi thanh ghi (Z80 chỉ có 7 thanh ghi 8-bit dễ dàng sử dụng, hướng dẫn phần còn lại cần lâu hơn) vì vậy tôi đặt &01trong H, cùng với việc sử dụng Lđể xây dựng các ký tự ASCII (Tôi chỉ nhận ra đó là không cần thiết để khởi L, tiết kiệm một byte ). Khi Htràn vào cờ Carry, ký tự trong Lđã sẵn sàng để xuất ra. May mắn thay, có 16 bit ADC( Quảng cáo d với C arry) thực hiện công việc của một hướng dẫn dịch chuyển trái.

(DE)chỉ có thể được đọc vào Amặc dù (HL)có thể được đọc vào bất kỳ thanh ghi 8 bit nào, vì vậy đó là một sự thỏa hiệp mà sử dụng. Tôi không thể so sánh trực tiếp (DE)với nhau C, vì vậy tôi phải tải một cái vào Atrước. Các nhãn chỉ là các từ ngẫu nhiên bắt đầu bằng L(một yêu cầu của trình biên dịch).

  • A Accumulator - đăng ký duy nhất có thể so sánh
  • Bbộ đếm đăng ký cho hướng dẫn DJNZ: D ecrement ( B) và J ump nếu N trên Z ero . Bằng cách sắp xếp lại mã, tôi có thể thực hiện công việc DJNZvới một byte ít hơn
  • C ký tự đầu tiên trong chuỗi đầu vào
  • D, EDEđịa chỉ của ký tự đầu vào hiện tại
  • H kích hoạt mang (mỗi vòng 8)
  • L nhân vật đầu ra được xây dựng

nhập mô tả hình ảnh ở đây


6

05AB1E , 10 byte

¦¦Sk8ôJCçJ

Hãy thử trực tuyến!

-3 cảm ơn emigna.


Ù             # Unique letters, in order they appear.
 v            # For each...
  yN:         # Push letter and index, replace in input.
     }        # End loop.
      ¦¦      # Remove first x2.
        8ô    # Split into eighths.
          C   # Convert to integer.
           ç  # Convert to char.
            J # Join together entire result.

1
Bạn có thể sử dụng 01‡thay vì vòng lặp. EDIT: hoặc thậm chí tốt hơn:¦¦Sk8ôJCçJ
Emigna


5

J, 17 13 byte

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

-4 cảm ơn FrownyFrog

Phiên bản cũ:

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

Giải trình:

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

Ví dụ:

   = '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{=để lưu 4 byte.
FrownyFrog

Ôi trời, bị trói ... Tôi không thể tìm thấy một byte nào khác.
Bạch tuộc ma thuật Urn

1
@MagicOctopusUrn thực sự là một đoạn trích, nó nên có [:ngay từ đầu :)
FrownyFrog


5

R , 71 byte

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

Hãy thử trực tuyến!

Đáng ngạc nhiên là golf!

Đầu tiên, chuyển đổi chuỗi thành mã điểm ascii với utf8ToInt, lưu nó thành y. Loại bỏ hai ký tự đầu tiên có chỉ mục tiêu cực ngắn hơn so với sử dụng tail.

Mảng y[-1:-2]==y[2]tương đương với các bit khi %*%(nhân ma trận) được áp dụng, nhưng trước tiên chúng ta định hình lại mảng đó thành một matrixvới nrow=8, chuyển đổi từ một mảng tuyến tính sang các nhóm byte. Một cách ngẫu nhiên, sau đó chúng ta có thể chuyển đổi thành các điểm mã ascii bằng cách nhân ma trận với các lũy thừa thích hợp là 2 2^(7:0), và sau đó chúng ta chuyển đổi các điểm mã trở lại thành một chuỗi với intToUtf8.



4

PHP, 73 71 byte

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

Chạy như ống với -nRhoặc thử trực tuyến .

đánh gôn

  • bắt đầu chỉ số tại -6và tăng trước bởi8
  • khai thác mà strtrbỏ qua các ký tự quá mức trong tham số dài hơn (không substrcần thiết)
  • dịch sang 10và sau đó đảo ngược không cần dấu ngoặc kép -> -1 byte
  • đảo ngược ký tự thay vì mã ascii -> ~đóng vai trò là ranh giới từ -> -1 byte.

3
Ít nhất bạn nên phù hợp với brainfuck:for(;$s=substr($argn,2+8*$i++,8);)echo~chr(bindec(strtr($s,$argn,10)));
Christoph

2
@Christoph Tôi thích cách Brainfuck đột nhiên là một tiêu chuẩn cho độ dài câu trả lời hợp lý.
Nit

4

Bình thường, 20 9 byte

CittxLQQ2

Đã lưu 11 byte nhờ FryAmTheEggman.

Hãy thử nó ở đây

Giải trình

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 Cảm ơn. Rõ ràng là tôi vẫn còn nhiều điều để tìm hiểu về Pyth.
Mnemonic

Haha, tôi cũng vậy Đó là một ngôn ngữ chơi golf rất phức tạp. Tôi hy vọng bạn tiếp tục chơi gôn trong đó :)
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}*''}

Hãy thử trực tuyến!


1
Chào mừng đến với PPCG! Tôi không thấy rằng có đã là một câu trả lời trong Ruby trước khi tôi gửi tôi, nhưng một số thủ thuật chơi golf điển hình áp dụng đối với cách tiếp cận của bạn quá - ví dụ, người cuối cùng .joincó thể được thay thế bằng *'', và s[0..1]bởi s[0,2].
Kirill L.

3

Japt, 11 byte

¤£bXÃò8 ®Íd

Thử nó


Giải trình

¤               :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

Sử dụng s2phím tắt rất thông minh , đẹp.
Nit

3

PHP + GNU Nhiều độ chính xác, 63 61

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

thật đáng buồn khi phần mở rộng của GMP không được kích hoạt mặc định (nhưng được vận chuyển).

Chạy như thế này:

echo "ABABABAAAAABABAAAAAABAABBAABAAAABBABAAABBB" | php -F a.php

<?=tiết kiệm 2 byte và có thể cả ngày. ;-)
Tít

@Titus yeah nhưng thật đáng buồn là nó không hoạt động -R(Tôi đã thử).
Christoph

1
-Fthay vào đó hãy thử
Tít


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 nhờ @ OlivierGrégoire .

Hãy thử trực tuyến.

Giải trình:

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 + THẮNG, 30 byte

Chỉ mục gốc 0. Nhắc nhở đầu vào của chuỗi

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

Giải trình:

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

Tôi giả sử Quad-AV phù hợp với ASCII cho APL + WIN?
Zacharý

@ Zacharý Có cho 128 ký tự đầu tiên. Các ký tự APL đặc biệt thay thế một số ký tự trong bộ ký tự ASCII mở rộng.
Graham

2

Đỏ , 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]]] 

Hãy thử trực tuyến!

Giải trình:

Một giải pháp đơn giản, không có nội dung.

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))),""

Đầu vào là trong ô A1. Google sẽ tự động thêm )))vào cuối công thức.

Giải trình:

  • Mid(A1,3+8*(Row(A:A)-1),8) lấy các khối của các nhân vật 8 tại một thời điểm, bắt đầu với phần thứ ba.
  • Substitute(Mid(~),Left(A1),0) thay thế từng trường hợp của ký tự đầu tiên bằng 0.
  • Substitute(Substitute(~),Mid(A1,2,1),1) thay thế ký tự thứ hai bằng 1.
  • Char(Bin2Dec(Substitute(~))) chuyển đổi chunk thành thập phân và sau đó thành ASCII.
  • IfError(Char(~,""))sửa chữa tất cả các lỗi phát sinh từ thực tế là Row(A:A)lợi nhuận xa nhiều giá trị hơn chúng ta nên Bin2Deccung cấp cho chúng tôi rất nhiều không giá trị và Charcác lỗi trên không.
  • ArrayFormula(Join("",IfError(~)))kết hợp tất cả các Charkết quả và ArrayFormulalà những gì làm cho Row(A:A)trả về một mảng các giá trị thay vì chỉ giá trị đầu tiên.




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

Hãy thử trực tuyến!

Không phải là ngắn nhất - chỉ là một cách khác.

Phiên bản sau in đầu ra trên một dòng cho 98 byte mặc dù trạng thái quy tắc cho phép khoảng trắng theo dõi được phép:

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

Hãy thử trực tuyến!


Đầu ra cuối cùng phải ở trên một dòng, không phải ba.
idrougge

Từ OP: "Khoảng trắng hàng đầu và dấu kiểm được cho phép trong đầu ra (mọi thứ khớp với / \ s * /)". Trận đấu mới /\s*/.
ElPedro

1
Xin lỗi, tôi không đủ thành thạo trong ký hiệu regex. : /
idrougge

Tôi cũng vậy nhưng tôi đã làm cho nó chắc chắn ;-)
ElPedro




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

Hãy thử trực tuyến!

fchuyển đổi chuỗi thành một danh sách các bit bằng cách so sánh từng ký tự với ký tự đầu tiên, biến Bools thành số không và số có fromEnum. gchia danh sách này thành các nhóm 8, chuyển đổi chúng thành số thập phân và lấy giá trị của số kết quả làm số Enum, Charlà một ví dụ của.

Thay đổi:

  • -19 byte nhờ @Laikoni (loại bỏ nhập, nhúng mapvào chức năng)
  • -12 byte lấy cảm hứng từ câu trả lời của @ Lynn (loại bỏ takebằng cách nén với danh sách ngắn hơn)

2
Bạn có thể sử dụng toEnumthay vì chrvà thả nhập. Ngoài ra mapcó thể được bao gồm vào g. Khoảng cách giữa 8 scó thể được loại bỏ.
Laikoni

1

Forth (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 ;

Hãy thử trực tuyến!

Đầu vào là đầu ra chuỗi Forth (địa chỉ và độ dài) tiêu chuẩn được in ra thiết bị xuất chuẩn

Giải trình

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.