Dekoduj ciąg

41

To jest moje pierwsze wyzwanie na ppcg!

Wejście

Ciąg składający się z dwóch różnych znaków ascii. Na przykład

ABAABBAAAAAABBAAABAABBAABA

Wyzwanie

Zadaniem jest odkodowanie tego ciągu zgodnie z następującymi regułami:

  1. Pomiń pierwsze dwa znaki
  2. Podziel resztę ciągu na grupy po 8 znaków
  3. W każdej grupie zamień każdy znak na, 0jeśli znak ten jest taki sam jak pierwszy znak oryginalnego łańcucha, i na 1inny
  4. Teraz każda grupa reprezentuje bajt. Konwertuj każdą grupę na znak z bajtowego kodu znaków
  5. Połącz wszystkie postacie

Przykład

Dekodujmy powyższy ciąg.

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

Zauważ, że Ajest to pierwszy znak w oryginalnym ciągu znaków i Bjest on drugim. W związku z tym, należy wymienić każdy Az 0a każdy Bz 1. Teraz otrzymujemy:

00110000  00110001  00110010

który jest [0x30, 0x31, 0x32]w formacie binarnym. Wartości te reprezentują ["0", "1", "2"]odpowiednio znaki , więc końcowy wynik powinien być 012.

Punktacja

Jest to oczywiście , co oznacza, że ​​kod powinien być jak najkrótszy. Wynik mierzony jest w bajtach.

Ograniczenia i format IO

Obowiązują standardowe zasady. Oto kilka dodatkowych zasad:

  • Możesz założyć prawidłowe dane wejściowe
    • Łańcuch wejściowy składa się z dokładnie dwóch różnych znaków
    • Pierwsze dwa znaki są różne
    • Minimalna długość ciągu wejściowego wynosi 2 znaki
    • Długość zawsze daje 2 modulo 8
  • Możesz założyć, że ciąg będzie zawsze składał się tylko z drukowalnych znaków ASCII
    • Zarówno na wejściu, jak i w dekodowanym ciągu
  • Wiodące i końcowe białe znaki są dozwolone w danych wyjściowych (wszystko, co pasuje /\s*/)
Jo King
źródło
5
Muszę powiedzieć, człowieku, w przypadku pierwszego wyzwania jest to jedno z lepiej sformatowanych wyzwań, jakie kiedykolwiek widziałem. Jako fyi, społeczna piaskownica jest doskonałym miejscem na informację zwrotną przed opublikowaniem, więc nie dostajesz się losowo zbombardowanego przedstawiciela z powodu reguły, której nie znasz.
Magic Octopus Urn
@MagicOctopusUrn. Dziękuję Ci! Nie wiedziałem o piaskownicy, opublikuję tam następnym razem :)
2
Najczęściej go używam, aby ludzie mogli zadzwonić do mnie na duplikaty pytań, bardzo proste do przestrzegania zasad, raczej trudne do poznania o duplikatach bez zapamiętywania meta :). Polecam również sprawdzenie czatów, mamy czaty dla prawie każdego języka, którego możesz się nauczyć, i pytania są zachęcane.
Magic Octopus Urn
1
Świetne pierwsze wyzwanie! Kilka innych przypadków testowych byłoby fajnych.
Lynn,
Naprawdę miłe pierwsze wyzwanie. Bawiłem się dobrze grając z tym.
ElPedro,

Odpowiedzi:

13

pieprzenie mózgu , 76 71 65 bajtów

-6 bajtów dzięki Nitrodon!

,>>,,[>>++++++++[-[->+<]<<<<[->+>-<<]>>[[-]>>+<<]>[->++<],>>]<.<]

Wypróbuj online!

Czuje się dziwnie pokonując Pythona ...

Jo King
źródło
1
Nie, jeśli 8 słów kluczowych w BF było tak długo, jak ich odpowiednik w języku Python.
user202729
Pomaga to, że BF automatycznie konwertuje Unicode.
LastStar007,
65 bajtów
Nitrodon
8

Stax , 15 11 bajtów

ó║¥U⌂½íèäöñ

Uruchom i debuguj na staxlang.xyz!

Szybkie i brudne podejście. Pracuję nad ulepszeniem. Poprawiłem to!

Rozpakowano (13 bajtów) i wyjaśnienie

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.
Khuldraeseth na'Barya
źródło
Ahhhh ... Wiedziałem, że to nas pokona.
Magic Octopus Urn
6

JavaScript (Node.js) , 67 bajtów

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

Wypróbuj online!

W jaki sposób?

Używamy dwóch różnych składni Bufferkonstruktora:

  • Buffer([n])generuje bufor zawierający jedyny bajt n i jest wymuszany na odpowiedni znak ASCII. Uwzględniane są tylko 8 najmniej znaczących bitów n .
  • Buffer(n)generuje bufor n bajtów. Dlatego Buffer(0)generuje pusty bufor, który jest wymuszany na pusty ciąg.

Uwaga: Oba są przestarzałe w najnowszych wersjach węzłów. Buffer.from([n])i Buffer.alloc(n)powinny być używane zamiast tego.

Skomentował

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
Arnauld
źródło
6

bash, 59 58 52 bajtów

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

Wypróbuj online!

Dzięki kwakowi Krowy za oszczędność 6 bajtów.

To wyzwanie działa wyjątkowo dobrze z serią coreutils (i dcdo konwersji i wyjścia na końcu). Po pierwsze używamy

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

aby transliterować dwa znaki na wejściu do zer i jedynek. -tFlag obcina pierwszy argument do długości sekundę, więc ta zmniejsza się do transliteracji dwa pierwsze znaki z wejścia do 0i 1, co jest, co chcemy. Następnie,

cut -c3-

usuwa pierwsze dwa znaki i

fold -8

wyprowadza 8 znaków w linii. Na koniec sedpolecenie zamienia każdą linię w dcfragment kodu, który odczytuje liczbę jako binarną i generuje bajt.

Klamka
źródło
Zawsze miło jest widzieć odpowiedź bash :) Możesz użyć sed, aby uprościć obliczenia DC, konwertując każdą linię na kod DC, który wypisuje każdy znak, a następnie sprawdzając go w dc tio.run/##S0oszvj/… (i spacja po cut -cmoże zostać usunięta)
Kritixi Lithos
6

Kod maszynowy Z80 na Amstrad CPC, 32 31 30 bajtów

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

Kod pobiera instrukcję zastępującą każdy znak, 0jeśli ten znak jest taki sam jak pierwszy znak oryginalnego łańcucha, a w 1przeciwnym razie dosłownie i nigdy nie zadaje sobie trudu, aby sprawdzić, czy znak pasuje do drugiego znaku w ciągu wejściowym. Po prostu sprawdza, czy znak jest taki sam jak pierwszy i różni się od pierwszego.

Pobiegłem z rejestrów (Z80 ma tylko 7 łatwo użytkowej rejestry 8-bitowe, potrzeba reszta dłuższe instrukcje), więc kładę &01się Hwraz z użyciem Lbudować znak ASCII (zdałem sobie sprawę, że to konieczne, aby zainicjować L, oszczędzając jeden bajt ). Kiedy Hpojawi się flaga Flagi, postać w Ljest gotowa do wyjścia. Na szczęście istnieje 16-bitowy ADC( Ad d z C arry), który wykonuje instrukcje lewoskrętne.

(DE)może być odczytany tylko do, Achociaż (HL)może być odczytany do dowolnego 8-bitowego rejestru, więc był to kompromis, którego użyć. Nie mogłem porównać (DE)z Cbezpośrednio, więc musiałam załadować jeden w Apierwszej kolejności. Etykiety są tylko losowymi słowami, które zaczynają się od L(wymaganie asemblera).

  • A Akumulator - jedyny rejestr, który może dokonywać porównań
  • Brejestr licznika dla instrukcji DJNZ: D ecrement ( B) i J UMP jeśli N o Z ero . Zmieniając kod, byłem w stanie wykonać zadanie DJNZz jednym mniejszym bajtem
  • C pierwszy znak w ciągu wejściowym
  • D, Ejako DEadres bieżącego znaku wejściowego
  • H wyzwalacz przenoszenia (co 8 pętla)
  • L budowany jest znak wyjściowy

wprowadź opis zdjęcia tutaj

CJ Dennis
źródło
6

05AB1E , 10 bajtów

¦¦Sk8ôJCçJ

Wypróbuj online!

-3 dzięki emignie.


Ù             # 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.
Urna Magicznej Ośmiornicy
źródło
1
Możesz użyć 01‡zamiast pętli. EDYCJA: lub nawet lepiej:¦¦Sk8ôJCçJ
Emigna,
5

J, 17 13 bajtów

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

-4 dzięki FrownyFrog

Stara wersja:

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

Wyjaśnienie:

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

Przykłady:

   = '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
Bolce Bussiere
źródło
1
2}.1{=aby zapisać 4 bajty.
FrownyFrog
O mój, związany ... Nie mogę znaleźć innego bajtu.
Magic Octopus Urn
1
@MagicOctopusUrn to tak naprawdę fragment, powinien on mieć [:na początku :)
FrownyFrog
5

Python 2 , 77 bajtów

lambda s:[chr(int(`map(s.find,s)`[i:i+24:3],2))for i in range(7,3*len(s),24)]

Wypróbuj online!

maxb
źródło
5

R , 71 bajtów

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

Wypróbuj online!

Zaskakująco golfowy!

Najpierw konwertuje ciąg znaków na punkty kodu ascii za pomocą utf8ToInt, zapisując go jako y. Usunięcie pierwszych dwóch znaków z ujemnym indeksowaniem jest krótsze niż użycie tail.

Tablica y[-1:-2]==y[2]jest równoważna bitom, gdy %*%stosowane jest (mnożenie macierzy), ale najpierw przekształcamy tę tablicę w znak „ matrixz” nrow=8, konwertując z tablicy liniowej na grupy bajtów. Na szczęście możemy następnie przekonwertować na punkty kodu ascii za pomocą mnożenia macierzy z odpowiednimi potęgami 2 2^(7:0), a następnie przekonwertować punkty kodu z powrotem na ciąg znaków za pomocą intToUtf8.

Giuseppe
źródło
4

Python 3 , 77 bajtów

a,b,*r=input();x=i=0
for c in r:i*=2;i|=a!=c;x+=1;x%8or print(end=chr(i&255))

Wypróbuj online!

ovs
źródło
4

PHP, 73 71 bajtów

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

Uruchom jako potok z -nRlub spróbuj online .

gra w golfa:

  • rozpocznij indeks o -6i inkrementuj o8
  • exploit strtrignorujący nadmierne znaki w dłuższym parametrze ( substrniepotrzebne)
  • tłumaczenie na, 10a następnie odwrócenie nie wymaga cudzysłowów -> -1 bajt
  • odwróć znak zamiast kodu ascii -> ~służy jako granica słowa -> -1 bajt.
Tytus
źródło
3
Przynajmniej powinieneś pasować do pieprzenia mózgu:for(;$s=substr($argn,2+8*$i++,8);)echo~chr(bindec(strtr($s,$argn,10)));
Christoph
2
@Christoph Podoba mi się, że Brainfuck nagle staje się standardem dla rozsądnej długości odpowiedzi.
Nit
4

Pyth, 20 9 bajtów

CittxLQQ2

Zaoszczędzono 11 bajtów dzięki FryAmTheEggman.

Wypróbuj tutaj

Wyjaśnienie

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.
Mnemoniczny
źródło
@FryAmTheEggman Thanks. Najwyraźniej wciąż muszę się wiele nauczyć o Pyth.
Mnemoniczny
Haha, ja też! To bardzo skomplikowany język golfa. Mam nadzieję, że nadal będziesz grać w golfa :)
FryAmTheEggman
3

Rubin , 82 79 bajtów

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

Wypróbuj online!

lfvt
źródło
1
Witamy w PPCG! Nie widziałem, że w Ruby była już odpowiedź, zanim opublikowałem moje, ale niektóre typowe triki golfowe dotyczą również twojego podejścia - np. Ostatnie .joinmożna zastąpić przez *''i s[0..1]przez s[0,2].
Kirill L.
3

Japt, 11 bajtów

¤£bXÃò8 ®Íd

Spróbuj


Wyjaśnienie

¤               :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
Kudłaty
źródło
Bardzo sprytne użycie s2skrótu, miło.
Nit
3

PHP + GNU Multiple Precision, 63 61

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

niestety rozszerzenie GMP nie jest domyślnie aktywowane (ale dostarczane).

Uruchom tak:

echo "ABABABAAAAABABAAAAAABAABBAABAAAABBABAAABBB" | php -F a.php
Christoph
źródło
<?=oszczędza 2 bajty i prawdopodobnie dzień. ;-)
Tytus
@Titus tak, ale niestety to nie działa -R(próbowałem).
Christoph
1
spróbuj -Fzamiast tego
Titus
3

Haskell , 75 bajtów

f[_,_]=""
f(z:o:s)=toEnum(sum[2^b|(b,c)<-zip[7,6..0]s,c==o]):f(z:o:drop 8s)

Wypróbuj online!

Lynn
źródło
3

Java 8, 143 142 141 141 bajtów

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 bajt dzięki @ OlivierGrégoire .

Wypróbuj online.

Wyjaśnienie:

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));}
Kevin Cruijssen
źródło
142 bajty
Olivier Grégoire,
2

APL + WIN, 30 bajtów

Początek indeksu 0. Monity o wprowadzenie ciągu

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

Wyjaśnienie:

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
Graham
źródło
Zakładam, że Quad-AV jest zgodny z ASCII dla APL + WIN?
Zacharý 24.04.18
@ Zacharý Tak dla pierwszych 128 znaków. Specjalne znaki APL zastępują niektóre znaki w rozszerzonym zestawie znaków ASCII.
Graham,
2

Czerwony , 110 bajtów

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

Wypróbuj online!

Wyjaśnienie:

Proste, proste rozwiązanie, bez wbudowanych funkcji.

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
        ]
    ]
] 
Galen Iwanow
źródło
2

Arkusze Google, 123 bajty

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

Dane wejściowe są w komórce A1. Google automatycznie doda )))na końcu formuły.

Wyjaśnienie:

  • Mid(A1,3+8*(Row(A:A)-1),8) chwyta kawałki znaków 8 na raz, zaczynając od trzeciego.
  • Substitute(Mid(~),Left(A1),0) zamienia każdą instancję pierwszego znaku na 0.
  • Substitute(Substitute(~),Mid(A1,2,1),1) zamienia drugą postać na 1.
  • Char(Bin2Dec(Substitute(~))) konwertuje porcję na dziesiętną, a następnie na ASCII.
  • IfError(Char(~,""))koryguje wszystkie błędy wynikające z faktu, że Row(A:A)zwraca znacznie więcej wartości niż my, więc Bin2Decdaje nam dużo zerowych wartości i Charbłędów na zero.
  • ArrayFormula(Join("",IfError(~)))łączy wszystkie Charwyniki i ArrayFormulajest tym, co powoduje, że Row(A:A)zwracana jest tablica wartości zamiast tylko pierwszej wartości.
Inżynier Toast
źródło
2

REXX, 41 bajtów

arg a+2 b
say x2c(b2x(translate(b,01,a)))

Wypróbuj online!

leniuchować
źródło
Bardzo fajny. Przez długi czas nie grał w REXX.
ElPedro,
2

Python 2 , 88 bajtów

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

Wypróbuj online!

Nie najkrótszy - tylko alternatywny sposób.

Następująca wersja drukuje dane wyjściowe w jednym wierszu dla 98 bajtów, chociaż reguły mówią, że końcowe białe znaki są dozwolone:

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

Wypróbuj online!

ElPedro
źródło
Ostateczne wyjście powinno znajdować się w jednym wierszu, a nie w trzech.
idrougge,
Z OP: „Początkowe i końcowe białe znaki są dozwolone w danych wyjściowych (wszystko, co pasuje do / \ s * /)”. Dopasowania nowej linii /\s*/.
ElPedro,
1
Przepraszam, nie znam się na notacji regularnej. : /
idrougge
Ja też nie jestem
Googledłem,
1

Haskell , 124 105 93 bajtów

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

Wypróbuj online!

fkonwertuje ciąg na listę bitów, porównując każdy znak z pierwszym, zamieniając Bools na zera i jedynki z fromEnum. gdzieli tę listę na grupy po 8, konwertuje je na dziesiętne i przyjmuje wartość wynikowej liczby jako an Enum, co Charjest instancją.

Zmiany:

  • -19 bajtów dzięki @Laikoni (usuwanie importu, osadzanie mapw funkcji)
  • -12 bajtów inspirowanych odpowiedzią @ Lynn (pozbycie się takeprzez skompresowanie krótszej listy)
użytkownik9549915
źródło
2
Możesz użyć toEnumzamiast chri upuścić import. Również mapmogą być włączone do g. Przestrzeń między 8 smożna usunąć.
Laikoni,
1

Dalej (gforth) , 83 bajty

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

Wypróbuj online!

Wejście jest standardowym ciągiem Forth (adres i długość), wyjście jest wypisywane na standardowe wyjście

Wyjaśnienie

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