Decodifica la stringa


41

Questa è la mia prima sfida su ppcg!

Ingresso

Una stringa composta da due diversi caratteri ASCII. Per esempio

ABAABBAAAAAABBAAABAABBAABA

Sfida

L'attività è di decodificare questa stringa seguendo queste regole:

  1. Salta i primi due personaggi
  2. Dividi il resto della stringa in gruppi di 8 caratteri
  3. In ogni gruppo, sostituisci ogni carattere con 0se quel carattere è uguale al primo carattere della stringa originale e con 1altrimenti
  4. Ora ogni gruppo rappresenta un byte. Converti ciascun gruppo in carattere dal codice char byte
  5. Concatena tutti i personaggi

Esempio

Decodifichiamo la stringa sopra.

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

Si noti che Aè il primo carattere nella stringa originale ed Bè il secondo. Pertanto, sostituire ciascuno Acon 0e ciascuno Bcon 1. Ora otteniamo:

00110000  00110001  00110010

che è [0x30, 0x31, 0x32]in binario. Questi valori rappresentano ["0", "1", "2"]rispettivamente i caratteri , quindi dovrebbe essere l'output finale 012.

punteggio

Questo è, ovviamente, , il che significa che il tuo codice sarà il più breve possibile. Il punteggio viene misurato in byte.

Vincoli e formato IO

Si applicano le regole standard. Ecco alcune regole aggiuntive:

  • Puoi assumere un input valido
    • La stringa di input è composta esattamente da due caratteri diversi
    • I primi due personaggi sono diversi
    • La lunghezza minima della stringa di input è di 2 caratteri
    • La lunghezza fornirà sempre 2 modulo 8
  • Puoi presumere che la stringa sarà sempre composta solo da caratteri ASCII stampabili
    • Sia nell'input che nella stringa decodificata
  • Gli spazi bianchi iniziali e finali sono consentiti nell'output (tutto ciò che corrisponde /\s*/)

5
Devo dire amico, per una prima sfida, questa è una delle sfide meglio formattate che abbia mai visto. In quanto fyi, la sandbox della community è un ottimo posto per i feedback prima di postare in modo da non essere bombardato a caso per una regola che non conoscevi.
Magic Octopus Urn il

@MagicOctopusUrn. Grazie! Non sapevo di sandbox,

2
Lo uso principalmente in modo che le persone possano chiamarmi su domande duplicate, molto semplici da seguire regole, piuttosto difficili da sapere sui duplicati senza memorizzare meta :). Consiglio anche di dare un'occhiata alle chat room, abbiamo chat per quasi tutte le lingue che potresti sperare di imparare e le domande sono incoraggiate.
Magic Octopus Urn il

1
Grande prima sfida! Alcuni altri casi di test sarebbero accurati.
Lynn,

Prima sfida davvero bella. Mi sono divertito a giocare con questo.
ElPedro,

Risposte:



8

Stax , 15 11 byte

ó║¥U⌂½íèäöñ

Eseguilo e esegui il debug su staxlang.xyz!

Approccio rapido e sporco. Lavorando per migliorarlo. Migliorato!

Spacchettato (13 byte) e spiegazione

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 ... sapevo che questo ci avrebbe battuti.
Magic Octopus Urn il

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

Provalo online!

Come?

Usiamo due diverse sintassi del Buffercostruttore:

  • Buffer([n])genera un buffer contenente il solo byte n ed è forzato al corrispondente carattere ASCII. Vengono considerati solo gli 8 bit meno significativi di n .
  • Buffer(n)genera un buffer di n byte. Pertanto, Buffer(0)genera un buffer vuoto, che viene forzato in una stringa vuota.

Nota: entrambi sono obsoleti nelle versioni recenti del nodo. Buffer.from([n])e Buffer.alloc(n)dovrebbe essere usato invece.

Commentate

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

Provalo online!

Grazie a Cows Quack per aver salvato 6 byte.

Questa sfida funziona molto bene con una serie di coreutils (e dcper fare la conversione e l'output alla fine). Innanzitutto, usiamo

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

per traslitterare i due caratteri nell'input in zero e uno. La -tbandiera tronca il primo argomento alla lunghezza del secondo, quindi questo si riduce alla traslitterazione dei primi due caratteri nell'input a 0e 1, che è quello che vogliamo. Poi,

cut -c3-

rimuove i primi due caratteri e

fold -8

genera 8 caratteri per riga. Infine, il sedcomando trasforma ogni riga in uno dcsnippet che legge il numero come binario e genera quel byte.


Sempre bello vedere una risposta bash :) Puoi usare sed per semplificare i calcoli in cc convertendo ogni riga in codice cc che stampa ogni carattere e poi valutandolo in cc tio.run/##S0oszvj/… (e il lo spazio dopo cut -cpuò essere rimosso)
Kritixi Lithos,

6

Codice macchina Z80 su un 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

Il codice prende l'istruzione sostituire ogni carattere con 0se quel carattere è lo stesso del primo carattere della stringa originale e con1 altrimenti letteralmente e non si preoccupa mai di verificare che un carattere corrisponda al secondo carattere nella stringa di input. Controlla solo lo stesso carattere del primo carattere e diverso dal primo carattere.

Ho finito di registri (Z80 ha solo 7 facilmente utilizzabili registri a 8-bit, le istruzioni del resto necessità più lunghi) così ho messo &01in H, insieme con l'utilizzo Lper costruire il carattere ASCII (Ho appena realizzato che è necessario inizializzare L, risparmiando un byte ). Quando Htrabocca nella bandiera Carry, il personaggio in Lè pronto per essere emesso. Fortunatamente, esiste un 16 bit ADC( Ad d con C arry) che svolge il compito di un'istruzione di spostamento a sinistra.

(DE)può essere letto solo Asebbene (HL)possa essere letto in qualsiasi registro a 8 bit, quindi è stato un compromesso quale utilizzare. Non ho potuto confrontare (DE)con Cdirettamente, così ho dovuto caricare l'uno nell'altro Aprima. Le etichette sono solo parole casuali che iniziano con L(un requisito dell'assemblatore).

  • A l'accumulatore - l'unico registro che può fare confronti
  • Bil contro registro per l'istruzione DJNZ: D ecrement ( B) e J ump se N su Z ero . Riorganizzando il codice, sono stato in grado di fare il lavoro DJNZcon un byte in meno
  • C il primo carattere nella stringa di input
  • D, Ecome DEl'indirizzo del carattere di input corrente
  • H il grilletto carry (ogni 8 ° loop)
  • L il carattere di output che si sta costruendo

inserisci qui la descrizione dell'immagine


6

05AB1E , 10 byte

¦¦Sk8ôJCçJ

Provalo online!

-3 grazie a 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
Puoi usare al 01‡posto del loop. MODIFICA: o meglio:¦¦Sk8ôJCçJ
Emigna il


5

J, 17 13 byte

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

-4 grazie a FrownyFrog

Vecchia versione:

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

Spiegazione:

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

Esempi:

   = '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{=per salvare 4 byte.
FrownyFrog,

Oh mio, legato ... Non riesco a trovare un altro byte.
Magic Octopus Urn il

1
@MagicOctopusUrn è in realtà uno snippet, dovrebbe avere un [:all'inizio :)
FrownyFrog


5

R , 71 byte

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

Provalo online!

Sorprendentemente da golf!

Innanzitutto, converte la stringa in punti di codice ASCII utf8ToInt, salvandola come y. La rimozione dei primi due caratteri con indicizzazione negativa è più breve dell'uso tail.

L'array y[-1:-2]==y[2]è equivalente ai bit quando %*%viene applicato (moltiplicazione di matrici), ma prima ridisegniamo quell'array in un matrixcon nrow=8, convertendo da un array lineare in raggruppamenti di byte. Fortunatamente, possiamo quindi convertire i punti di codice ASCII utilizzando la moltiplicazione di matrice con i poteri appropriati di 2 2^(7:0), e quindi riconvertire i punti di codice in una stringa con intToUtf8.



4

PHP, 73 71 byte

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

Esegui come pipe -nRo provalo online .

golfings:

  • inizio indice a -6e pre-incremento di8
  • exploit che strtrignora i caratteri eccessivi nel parametro più lungo (nosubstr necessario)
  • traduzione in 10 e quindi l'inversione non richiede virgolette -> -1 byte
  • inverti carattere invece del codice ascii -> ~funge da limite di parole -> -1 byte.

3
Almeno dovresti abbinare brainfuck:for(;$s=substr($argn,2+8*$i++,8);)echo~chr(bindec(strtr($s,$argn,10)));
Christoph il

2
@Christoph Mi piace come Brainfuck sia improvvisamente uno standard per una lunghezza della risposta ragionevole.
Nit

4

Pyth, 20 9 byte

CittxLQQ2

Salvato 11 byte grazie a FryAmTheEggman.

Provalo qui

Spiegazione

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 Grazie. Evidentemente ho ancora molto da imparare su Pyth.
Mnemonico,

Ah, anche io! È un linguaggio golf molto complesso. Spero che continui a giocare a golf :)
FryAmTheEggman,

3

Rubino , 82 79 byte

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

Provalo online!


1
Benvenuti in PPCG! Non ho visto che c'era già una risposta in Ruby prima di pubblicare la mia, ma alcuni trucchi tipici del golf si applicano anche al tuo approccio, ad esempio l'ultimo .joinpuò essere sostituito da *''e s[0..1]da s[0,2].
Kirill L.,

3

Japt, 11 byte

¤£bXÃò8 ®Íd

Provalo


Spiegazione

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

Uso molto intelligente della s2scorciatoia, carino.
Nit

3

PHP + GNU Multiple Precision, 63 61

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

purtroppo l'estensione GMP non è attivata di default (ma spedita).

Esegui in questo modo:

echo "ABABABAAAAABABAAAAAABAABBAABAAAABBABAAABBB" | php -F a.php

<?=salva 2 byte e possibilmente il giorno. ;-)
Tito

@Titus sì, ma purtroppo non funziona -R(ho provato).
Christoph,

1
prova -Finvece
Tito


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 grazie a @ OlivierGrégoire .

Provalo online.

Spiegazione:

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

Origine indice 0. Richiede l'immissione di una stringa

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

Spiegazione:

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

Suppongo che Quad-AV sia in linea con ASCII per APL + WIN?
Zacharý,

@ Zacharý Sì per i primi 128 caratteri. Gli speciali caratteri APL sostituiscono alcuni dei caratteri nel set di caratteri ASCII esteso.
Graham,

2

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

Provalo online!

Spiegazione:

Una soluzione semplice e diretta, senza 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

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

L'input è nella cella A1. Google aggiungerà automaticamente))) alla fine della formula.

Spiegazione:

  • Mid(A1,3+8*(Row(A:A)-1),8) prende pezzi di personaggi 8 alla volta, a partire dal terzo.
  • Substitute(Mid(~),Left(A1),0) sostituisce ogni istanza del primo carattere con 0.
  • Substitute(Substitute(~),Mid(A1,2,1),1) sostituisce il secondo carattere con 1.
  • Char(Bin2Dec(Substitute(~))) converte il blocco in decimale e quindi in ASCII.
  • IfError(Char(~,""))corregge tutti gli errori che derivano dal fatto che Row(A:A)restituisce molti più valori di noi, quindi Bin2Decci dà molti valori zero eChar errori su zero.
  • ArrayFormula(Join("",IfError(~)))unisce tutti i Charrisultati ed ArrayFormulaè ciò che rende il Row(A:A)ritorno un array di valori anziché solo il primo valore.




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

Provalo online!

Non il più breve - solo un modo alternativo.

La versione seguente stampa l'output su una riga per 98 byte sebbene le regole stabiliscano che è consentito lo spazio bianco finale:

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

Provalo online!


L'output finale dovrebbe essere su una riga, non su tre.
idrougge,

Da OP: "Sono consentiti spazi bianchi iniziali e finali nell'output (tutto ciò che corrisponde a / \ s * /)". Partite Newline /\s*/.
ElPedro,

1
Mi dispiace, non sono abbastanza esperto nella notazione regex. : /
idrougge

Nemmeno io ma ho cercato su Google solo per essere sicuri ;-)
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

Provalo online!

fconverte la stringa in un elenco di bit confrontando ciascun carattere con il primo, trasformando la Bools in zeri e quelli con fromEnum. gdivide questo elenco in gruppi di 8, li converte in decimali e prende il valore del numero risultante come un Enum, cheChar è un'istanza di.

I cambiamenti:

  • -19 byte grazie a @Laikoni (rimozione dell'importazione, incorporamento mapin funzione)
  • -12 byte ispirati alla risposta di @ Lynn (eliminando takezippando con un elenco più breve)

2
È possibile utilizzare toEnumanziché chrrilasciare l'importazione. Anche il mappuò essere incluso in g. Lo spazio tra 8 spuò essere rimosso.
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 ;

Provalo online!

L'input è una stringa Forth standard (indirizzo e lunghezza) l'output viene stampato su stdout

Spiegazione

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.