Dekodiere den String


41

Dies ist meine erste Herausforderung bei ppcg!

Eingang

Eine Zeichenfolge, die aus zwei verschiedenen ASCII-Zeichen besteht. Zum Beispiel

ABAABBAAAAAABBAAABAABBAABA

Herausforderung

Die Aufgabe besteht darin, diese Zeichenfolge nach folgenden Regeln zu dekodieren:

  1. Überspringe die ersten beiden Zeichen
  2. Teilen Sie den Rest der Zeichenfolge in Gruppen von 8 Zeichen
  3. In jeder Gruppe ersetzen jedes Zeichen mit , 0ob das Zeichen das gleiche wie das erste Zeichen des ursprünglichen Zeichenfolge und mit 1ansonsten
  4. Jetzt repräsentiert jede Gruppe ein Byte. Konvertieren Sie jede Gruppe in Zeichen aus dem Byte-Zeichencode
  5. Verketten Sie alle Zeichen

Beispiel

Lassen Sie uns den obigen String dekodieren.

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

Beachten Sie, dass dies Adas erste und Bdas zweite Zeichen in der ursprünglichen Zeichenfolge ist. Ersetzen Sie daher jeweils Amit 0und Bmit 1. Jetzt erhalten wir:

00110000  00110001  00110010

das ist [0x30, 0x31, 0x32]in binär. Diese Werte stellen jeweils Zeichen ["0", "1", "2"]dar, daher sollte die endgültige Ausgabe erfolgen 012.

Wertung

Dies ist natürlich , was bedeutet, dass Sie Ihren Code so kurz wie möglich halten. Die Bewertung wird in Bytes gemessen.

Einschränkungen und IO-Format

Es gelten Standardregeln. Hier sind einige zusätzliche Regeln:

  • Sie können eine gültige Eingabe annehmen
    • Eingabezeichenfolge besteht aus genau zwei verschiedenen Zeichen
    • Die ersten beiden Zeichen sind unterschiedlich
    • Die Mindestlänge der Eingabezeichenfolge beträgt 2 Zeichen
    • Die Länge ergibt immer 2 Modulo 8
  • Sie können davon ausgehen, dass die Zeichenfolge immer nur aus druckbaren ASCII-Zeichen besteht
    • Sowohl in der Eingabe als auch in der dekodierten Zeichenfolge
  • Führende und nachfolgende Leerzeichen sind in der Ausgabe zulässig (alles, was passt /\s*/)

5
Ich muss sagen, Mann, für eine erste Herausforderung ist dies eine der besser formatierten Herausforderungen, die ich je gesehen habe. Die Community-Sandbox ist ein großartiger Ort für Feedback vor dem Posten, damit Sie nicht nach dem Zufallsprinzip für eine Regel bombardiert werden, die Sie nicht kannten.
Magic Octopus Urn

@MagicOctopusUrn. Danke! Wusste nichts über Sandbox, werde ich das nächste Mal dort

2
Ich benutze es meistens, damit die Leute mich auf doppelte Fragen ansprechen können, sehr einfach zu befolgende Regeln, ziemlich schwer über Dupes zu wissen, ohne Meta auswendig zu lernen :). Ich würde auch empfehlen, die Chatrooms zu besuchen. Wir haben Chats für fast jede Sprache, die Sie gerne lernen würden, und Fragen sind erwünscht.
Magic Octopus Urn

1
Tolle erste Herausforderung! Einige weitere Testfälle wären ordentlich.
Lynn

Wirklich schöne erste Herausforderung. Hatte Spaß damit zu spielen.
ElPedro

Antworten:



8

Stax , 15 11 Bytes

ó║¥U⌂½íèäöñ

Führen Sie es aus und debuggen Sie es unter staxlang.xyz!

Schneller und schmutziger Ansatz. Wir arbeiten daran, es zu verbessern. Verbesserte es!

Entpackt (13 Bytes) und Erklärung

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 ... ich wusste, das würde uns schlagen.
Magic Octopus 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])))

Probieren Sie es online!

Wie?

Wir verwenden zwei verschiedene Syntaxen des BufferKonstruktors:

  • Buffer([n])generiert einen Puffer, der das einzige Byte n enthält, und wird in das entsprechende ASCII-Zeichen umgewandelt. Es werden nur die 8 niedrigstwertigen Bits von n berücksichtigt.
  • Buffer(n)erzeugt einen Puffer von n Bytes. Daher Buffer(0)erzeugt einen leeren Puffer, der auf eine leere Zeichenfolge dazu gezwungen wird.

Hinweis: Beide sind in neueren Node-Versionen veraltet. Buffer.from([n])und Buffer.alloc(n)sollte stattdessen verwendet werden.

Kommentiert

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 Bytes

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

Probieren Sie es online!

Vielen Dank an Cows Quack für die Einsparung von 6 Bytes.

Diese Herausforderung funktioniert bemerkenswert gut mit einer Reihe von Coreutils (und dcder Konvertierung und Ausgabe am Ende). Erstens verwenden wir

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

um die zwei Zeichen in der Eingabe in Nullen und Einsen umzuwandeln. Das -tFlag schneidet das erste Argument auf die Länge des zweiten ab, sodass die ersten beiden Zeichen in der Eingabe in 0und transliteriert werden müssen 1. Dann,

cut -c3-

Entfernt die ersten beiden Zeichen und

fold -8

Gibt 8 der Zeichen pro Zeile aus. Schließlich sedverwandelt der Befehl jede Zeile in ein dcSnippet, das die Zahl als Binärzahl liest und dieses Byte ausgibt.


Es ist immer schön, eine bash - Antwort zu sehen :) Sie können sed verwenden, um die DC - Berechnungen zu vereinfachen, indem Sie jede Zeile in einen DC - Code konvertieren, der jedes Zeichen ausgibt, und ihn dann in dc tio.run/##S0oszvj/… (und dem Raum danach cut -ckann entfernt werden)
Kritixi Lithos

6

Z80-Maschinencode auf einem Amstrad-CPC, 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

Der Code übernimmt die Anweisung , jedes Zeichen durch zu ersetzen, 0wenn dieses Zeichen mit dem ersten Zeichen der ursprünglichen Zeichenfolge identisch ist. 1Andernfalls wird buchstäblich nicht geprüft, ob ein Zeichen mit dem zweiten Zeichen in der Eingabezeichenfolge übereinstimmt. Es wird nur geprüft, ob das erste Zeichen und das erste Zeichen identisch sind.

Ich lief aus Registern (die Z80 hat nur 7 leicht verwendbar 8-Bit - Register, der Rest Notwendigkeit mehr Anweisungen) so habe ich &01in H, zusammen mit der Verwendung Ldes ASCII - Zeichens aufzubauen (ich es nur realisiert unnötig zu initialisieren L, speichern ein Byte ). Wenn Hdas Carry-Flag überschritten wird, kann das Zeichen in Lausgegeben werden. Glücklicherweise gibt es ein 16-Bit ADC( Ad d mit C arry), das die Aufgabe eines Linksschiebebefehls erfüllt.

(DE)kann nur eingelesen werden, Aobwohl (HL)es in jedes 8-Bit-Register eingelesen werden kann. Es war also ein Kompromiss, den man verwenden sollte. Ich konnte nicht direkt (DE)mit vergleichen C, also musste ich zuerst einen laden A. Die Bezeichnungen sind nur zufällige Wörter, die mit L(einer Anforderung des Assemblers) beginnen.

  • A der Akku - das einzige Register, das Vergleiche anstellen kann
  • Bdas Zählerregister für den Befehl DJNZ: D ecrement ( B) und J ump if N on Z ero . Durch die Neuanordnung des Codes konnte ich die Aufgabe DJNZmit einem Byte weniger erledigen
  • C das erste Zeichen in der Eingabezeichenfolge
  • D, Eals DEAdresse des aktuellen Eingabezeichens
  • H der Carry-Trigger (jede 8. Schleife)
  • L das ausgegebene Zeichen wird aufgebaut

Bildbeschreibung hier eingeben


6

05AB1E , 10 Bytes

¦¦Sk8ôJCçJ

Probieren Sie es online!

-3 danke an 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
Sie können 01‡anstelle der Schleife verwenden. EDIT: oder noch besser:¦¦Sk8ôJCçJ
Emigna


5

J, 17 13 Bytes

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

-4 danke an FrownyFrog

Alte Version:

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

Erläuterung:

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

Beispiele:

   = '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{=um 4 Bytes zu sparen.
FrownyFrog

Oh mein Gott, gebunden ... Ich kann kein weiteres Byte finden.
Magic Octopus Urn

1
@MagicOctopusUrn es ist eigentlich ein Schnipsel, sollte es [:am Anfang haben :)
FrownyFrog


5

R , 71 Bytes

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

Probieren Sie es online!

Überraschend golfen!

Konvertiert zuerst den String mit in ASCII-Code-Punkte utf8ToIntund speichert ihn als y. Das Entfernen der ersten beiden Zeichen mit negativer Indizierung ist kürzer als das Verwenden von tail.

Das Array y[-1:-2]==y[2]ist äquivalent zu den Bits, wenn %*%(Matrixmultiplikation) angewendet wird, aber zuerst formen wir dieses Array in ein matrixmit um nrow=8und wandeln es von einem linearen Array in Bytegruppierungen um. Glücklicherweise können wir dann mithilfe der Matrixmultiplikation mit den entsprechenden Zweierpotenzen in ASCII-Codepunkte 2^(7:0)konvertieren und die Codepunkte anschließend mit in eine Zeichenfolge zurückkonvertieren intToUtf8.



4

PHP, 73 71 Bytes

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

Laufen Sie als Pipe mit -nRoder versuchen Sie es online .

Golfen:

  • Index starten um -6und vorinkrementieren um8
  • Exploit, der strtrübermäßige Zeichen im längeren Parameter ignoriert (nicht substrerforderlich)
  • Für das Übersetzen in 10und das anschließende Invertieren sind keine Anführungszeichen erforderlich -> -1 Byte
  • Zeichen invertieren statt ASCII-Code -> ~dient als Wortgrenze -> -1 Byte.

3
Zumindest sollten Sie Brainfuck passen:for(;$s=substr($argn,2+8*$i++,8);)echo~chr(bindec(strtr($s,$argn,10)));
Christoph

2
@Christoph Mir gefällt, wie Brainfuck plötzlich ein Standard für vernünftige Antwortlängen ist.
Nit

4

Pyth, 20 9 Bytes

CittxLQQ2

11 Bytes dank FryAmTheEggman gespart.

Probieren Sie es hier aus

Erläuterung

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 Danke. Offenbar muss ich noch viel über Pyth lernen.
Gedächtnisstütze

Haha, ich auch! Es ist eine sehr komplizierte Golfsprache. Ich hoffe, Sie weiterhin Golf spielen :)
FryAmTheEggman

3

Ruby , 82 79 Bytes

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

Probieren Sie es online!


1
Willkommen bei PPCG! Ich habe nicht gesehen, dass es in Ruby bereits eine Antwort gab, bevor ich meine veröffentlicht habe, aber einige typische Golf-Tricks treffen auch auf Ihren Ansatz zu - z. B. kann der letzte .joindurch *''und s[0..1]durch ersetzt werden s[0,2].
Kirill L.

3

Japt, 11 Bytes

¤£bXÃò8 ®Íd

Versuch es


Erläuterung

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

Sehr kluger Gebrauch der s2Abkürzung, nett.
Nit

3

PHP + GNU Multiple Precision, 63 61

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

Leider ist die GMP-Erweiterung nicht standardmäßig aktiviert (sondern ausgeliefert).

Laufen Sie wie folgt:

echo "ABABABAAAAABABAAAAAABAABBAABAAAABBABAAABBB" | php -F a.php

<?=Spart 2 Bytes und eventuell den Tag. ;-)
Titus

@Titus ja, aber leider funktioniert es nicht mit -R(ich habe es versucht).
Christoph

1
versuchen Sie es -Fstattdessen
Titus


3

Java 8, 143 142 141 Bytes

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 danke an @ OlivierGrégoire .

Probieren Sie es online aus.

Erläuterung:

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 Bytes

Indexursprung 0. Fordert zur Eingabe eines Strings auf

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

Erläuterung:

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

Ich nehme an, Quad-AV ist in Übereinstimmung mit ASCII für APL + WIN?
Zacharý

@ Zacharý Ja für die ersten 128 Zeichen. Die APL-Sonderzeichen ersetzen einige der Zeichen im erweiterten ASCII-Zeichensatz.
Graham

2

Rot , 110 Bytes

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

Probieren Sie es online!

Erläuterung:

Eine einfache, unkomplizierte Lösung, keine eingebauten.

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

Die Eingabe erfolgt in Zelle A1. Google fügt automatisch )))das Ende der Formel hinzu.

Erläuterung:

  • Mid(A1,3+8*(Row(A:A)-1),8) packt ab dem dritten Stück jeweils 8 Zeichen.
  • Substitute(Mid(~),Left(A1),0) Ersetzt jede Instanz des ersten Zeichens durch 0.
  • Substitute(Substitute(~),Mid(A1,2,1),1) ersetzt das zweite Zeichen durch 1.
  • Char(Bin2Dec(Substitute(~))) konvertiert den Block in Dezimalzahl und dann in ASCII.
  • IfError(Char(~,""))alle korrigiert die Fehler , die resultieren aus der Tatsache , dass Row(A:A)Renditen weit mehr Werte als wir so Bin2Decgibt uns eine Menge von Nullwerten und CharFehler heraus auf Null.
  • ArrayFormula(Join("",IfError(~)))Fügt alle CharErgebnisse zusammen und ArrayFormulamacht die Row(A:A)Rückgabe zu einem Array von Werten anstelle nur des ersten Werts.




2

Python 2 , 88 Bytes

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

Probieren Sie es online!

Nicht die kürzeste - nur eine Alternative.

Die folgende Version gibt die Ausgabe in einer Zeile für 98 Byte aus, obwohl die Regeln festlegen, dass nachfolgende Leerzeichen zulässig sind:

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

Probieren Sie es online!


Die endgültige Ausgabe sollte in einer Zeile erfolgen, nicht in drei.
Idrougge

From OP: "Führende und nachfolgende Leerzeichen sind in der Ausgabe zulässig (alles, was mit / \ s * / übereinstimmt)". Newline-Übereinstimmungen /\s*/.
ElPedro

1
Tut mir leid, ich bin nicht gut genug mit der Regex-Notation vertraut. : /
idrougge

Ich bin es auch nicht, aber ich habe es gegoogelt, um sicher zu sein
;-)




1

Haskell , 124 105 93 Bytes

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

Probieren Sie es online!

fwandelt die Zeichenfolge in eine Liste von Bits um, indem jedes Zeichen mit dem ersten verglichen wird und das Bools in Nullen und Einsen mit umgewandelt wird fromEnum. gteilt diese Liste in Gruppen von 8, wandelt sie in dezimalen, und nimmt den Wert der erhaltenen Zahl als Enum, die Chareine Instanz ist.

Änderungen:

  • -19 Bytes dank @Laikoni (Import entfernen, mapin Funktion einbetten )
  • -12 Bytes, inspiriert von take@Lynns Antwort (wird durch Zippen mit kürzerer Liste entfernt)

2
Sie können den Import toEnumanstelle von verwenden chrund verwerfen. Auch das mapkann in aufgenommen werden g. Der Zwischenraum 8 skann entfernt werden.
Laikoni

1

Viertens (gviertens) , 83 Bytes

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

Probieren Sie es online!

Die Eingabe ist eine standardmäßige Forth-Zeichenfolge (Adresse und Länge). Die Ausgabe erfolgt auf Standardausgabe

Erläuterung

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.