Decodifica la cuerda


41

Este es mi primer desafío en ppcg!

Entrada

Una cadena que consta de dos caracteres ascii diferentes. Por ejemplo

ABAABBAAAAAABBAAABAABBAABA

Reto

La tarea es decodificar esta cadena siguiendo estas reglas:

  1. Salta los dos primeros caracteres
  2. Divida el resto de la cadena en grupos de 8 caracteres.
  3. En cada grupo, reemplace cada carácter con 0si ese carácter es el mismo que el primer carácter de la cadena original, y 1si no
  4. Ahora cada grupo representa un byte. Convierta cada grupo en carácter a partir del código de bytes
  5. Concatenar todos los personajes

Ejemplo

Decodifiquemos la cadena de arriba.

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

Observe que Aes el primer carácter de la cadena original y Bes el segundo. Por lo tanto, reemplace cada Acon 0y cada uno Bcon 1. Ahora obtenemos:

00110000  00110001  00110010

que está [0x30, 0x31, 0x32]en binario Estos valores representan caracteres ["0", "1", "2"]respectivamente, por lo que la salida final debería ser 012.

Tanteo

Esto es, por supuesto, , lo que significa hacer que su código sea lo más corto posible. La puntuación se mide en bytes.

Restricciones y formato IO

Aplican reglas estándar. Aquí hay algunas reglas adicionales:

  • Puede asumir una entrada válida
    • La cadena de entrada consta de exactamente dos caracteres diferentes
    • Los dos primeros personajes son diferentes.
    • La longitud mínima de la cadena de entrada es de 2 caracteres.
    • La longitud siempre dará 2 módulo 8
  • Puede suponer que la cadena siempre constará solo de caracteres ASCII imprimibles
    • Tanto en la entrada como en la cadena decodificada
  • Los espacios en blanco iniciales y finales están permitidos en la salida (todo lo que coincida /\s*/)

55
Tengo que decir hombre, para un primer desafío, este es uno de los desafíos mejor formateados que he visto. Como digo, el sandbox de la comunidad es un gran lugar para recibir comentarios antes de publicar para que no te bombardeen aleatoriamente por una regla que no conocías.
Urna mágica del pulpo

@MagicOctopusUrn. ¡Gracias! No sabía sobre sandbox, publicaré allí la próxima vez :)

2
Principalmente lo uso para que la gente pueda llamarme por preguntas duplicadas, reglas muy simples de seguir, bastante difíciles de saber sobre los engaños sin memorizar meta :). También recomiendo revisar las salas de chat, tenemos chats para casi todos los idiomas que podrías desear aprender y se alientan las preguntas.
Urna de pulpo mágico

1
¡Gran primer desafío! Algunos casos de prueba más estarían bien.
Lynn

Realmente bonito primer desafío. Me divertí jugando con este.
ElPedro

Respuestas:



8

Stax , 15 11 bytes

ó║¥U⌂½íèäöñ

¡Ejecútelo y depúrelo en staxlang.xyz!

Enfoque rápido y sucio. Trabajando para mejorarlo. ¡Lo mejoré!

Desempaquetado (13 bytes) y explicación

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 ... Sabía que esto nos ganaría.
Urna mágica de pulpo

6

JavaScript (Node.js) , 67 bytes

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

Pruébalo en línea!

¿Cómo?

Utilizamos dos sintaxis diferentes del Bufferconstructor:

  • Buffer([n])genera un búfer que contiene el único byte n y se obliga al carácter ASCII correspondiente. Solo se consideran los 8 bits menos significativos de n .
  • Buffer(n)genera un búfer de n bytes. Por lo tanto, Buffer(0)genera un búfer vacío, que se convierte en una cadena vacía.

Nota: Ambos están en desuso en versiones recientes de Node. Buffer.from([n])y Buffer.alloc(n)debe usarse en su lugar.

Comentado

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

Pruébalo en línea!

Gracias a Cows quack por guardar 6 bytes.

Este desafío funciona notablemente bien con una serie de coreutils (y dcpara hacer la conversión y la salida al final). Primero, usamos

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

para transcribir los dos caracteres en la entrada a ceros y unos. La -tbandera trunca el primer argumento a la longitud del segundo, por lo que esto se reduce a transcribir los primeros dos caracteres en la entrada a 0y 1, que es lo que queremos. Luego,

cut -c3-

elimina los dos primeros caracteres y

fold -8

genera 8 de los caracteres por línea. Finalmente, el sedcomando convierte cada línea en un dcfragmento que lee el número como binario y genera ese byte.


Siempre es bueno ver una respuesta bash :) Puede usar sed para simplificar los cálculos de CC convirtiendo cada línea en código de CC que imprima cada carácter y luego evaluándolo en dc tio.run/##S0oszvj/… (y el espacio después cut -cpuede ser eliminado)
Kritixi Lithos

6

Código de máquina Z80 en un Amstrad CPC, 32 31 30 bytes

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

El código toma la instrucción de reemplazar cada carácter con 0si ese carácter es el mismo que el primer carácter de la cadena original, y con lo 1contrario literalmente y nunca se molesta en verificar que un carácter coincida con el segundo carácter en la cadena de entrada. Simplemente comprueba el mismo como primer carácter y diferente del primer carácter.

Salí corriendo de registros (el Z80 tiene solamente 7 fácilmente utilizables registros de 8 bits, las instrucciones al resto necesidad más largos) por lo que poner &01en H, junto con el uso Lde construir el carácter ASCII (Me di cuenta de que es innecesaria para inicializar L, el ahorro de un byte ) Cuando se Hdesborda en la bandera Carry, el personaje Lestá listo para salir. Afortunadamente, hay un 16 bits ADC( Ad d con C arry) que hace el trabajo de una instrucción de desplazamiento a la izquierda.

(DE)solo se puede leer, Aaunque (HL)se puede leer en cualquier registro de 8 bits, por lo que fue un compromiso cuál usar. No podía comparar (DE)con Cdirectamente, así que tuve que cargar uno en Aprimer lugar. Las etiquetas son solo palabras aleatorias que comienzan con L(un requisito del ensamblador).

  • A el acumulador: el único registro que puede hacer comparaciones
  • Bel contador se registra para la instrucción DJNZ: D ecrement ( B) y J ump si N en Z ero . Al reorganizar el código, pude hacer el trabajo DJNZcon un byte menos
  • C el primer caracter en la cadena de entrada
  • D, Ecomo DEla dirección del carácter de entrada actual
  • H el gatillo de transporte (cada 8vo bucle)
  • L el carácter de salida que se está construyendo

ingrese la descripción de la imagen aquí


6

05AB1E , 10 bytes

¦¦Sk8ôJCçJ

Pruébalo en línea!

-3 gracias 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
Puede usar en 01‡lugar del bucle. EDITAR: o incluso mejor:¦¦Sk8ôJCçJ
Emigna


5

J, 17 13 bytes

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

-4 gracias a FrownyFrog

Versión antigua:

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

Explicación:

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

Ejemplos:

   = '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{=para guardar 4 bytes.
FrownyFrog

Oh, atado ... No puedo encontrar otro byte.
Urna mágica del pulpo

1
@MagicOctopusUrn en realidad es un fragmento, debería tener un [:al principio :)
FrownyFrog


5

R , 71 bytes

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

Pruébalo en línea!

Sorprendentemente golfístico!

Primero, convierte la cadena en puntos de código ASCII con utf8ToInt, guardándola como y. Eliminar los dos primeros caracteres con indexación negativa es más corto que usar tail.

La matriz y[-1:-2]==y[2]es equivalente a los bits cuando %*%se aplica (multiplicación de matriz), pero primero damos forma a esa matriz en matrixa nrow=8, convirtiéndola de una matriz lineal a agrupaciones de bytes. Afortunadamente, podemos convertir a los puntos de código ascii usando la multiplicación de matrices con las potencias apropiadas de 2 2^(7:0), y luego convertimos los puntos de código a una cadena con intToUtf8.



4

PHP, 73 71 bytes

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

Ejecutar como tubería -nRo probarlo en línea .

campos de golf:

  • índice de inicio en -6y pre-incremento por8
  • explotación que strtrignora los caracteres excesivos en el parámetro más largo (no es substrnecesario)
  • traducir 10y luego invertir no necesita comillas -> -1 byte
  • invertir el carácter en lugar del código ascii -> ~sirve como límite de palabra -> -1 byte.

3
Al menos deberías igualar brainfuck:for(;$s=substr($argn,2+8*$i++,8);)echo~chr(bindec(strtr($s,$argn,10)));
Christoph

2
@ Christoph Me gusta cómo Brainfuck de repente es un estándar para una respuesta razonable.
Nit

4

Pyth, 20 9 bytes

CittxLQQ2

Guardado 11 bytes gracias a FryAmTheEggman.

Pruébalo aquí

Explicación

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 Gracias. Evidentemente, todavía tengo mucho que aprender sobre Pyth.
Mnemónico

Jaja, yo también! Es un lenguaje de golf muy complejo. Espero que
sigas

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}*''}

Pruébalo en línea!


1
Bienvenido a PPCG! No vi que ya había una respuesta en Ruby antes de publicar la mía, pero algunos trucos de golf típicos también se aplican a su enfoque, por ejemplo, el último .joinpuede ser reemplazado por *'', y s[0..1]por s[0,2].
Kirill L.

3

Japt, 11 bytes

¤£bXÃò8 ®Íd

Intentalo


Explicación

¤               :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 muy inteligente del s2atajo, agradable.
Nit

3

PHP + GNU Precisión múltiple, 63 61

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

Lamentablemente, la extensión GMP no está activada por defecto (sino que se envía).

Corre así:

echo "ABABABAAAAABABAAAAAABAABBAABAAAABBABAAABBB" | php -F a.php

<?=ahorra 2 bytes y posiblemente el día. ;-)
Titus

@Titus sí, pero lamentablemente no funciona con -R(lo intenté).
Christoph

1
intente en su -Flugar
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 gracias a @ OlivierGrégoire .

Pruébalo en línea.

Explicación:

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

Origen del índice 0. Solicita la entrada de una cadena

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

Explicación:

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

¿Asumo que Quad-AV está en línea con ASCII para APL + WIN?
Zacharý

@ Zacharý Sí para los primeros 128 caracteres. Los caracteres APL especiales reemplazan algunos de los caracteres en el conjunto de caracteres ASCII extendido.
Graham

2

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

Pruébalo en línea!

Explicación:

Una solución simple y directa, sin componentes incorporados.

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

Hojas de cálculo de Google, 123 bytes

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

La entrada está en la celda A1. Google agregará automáticamente )))al final de la fórmula.

Explicación:

  • Mid(A1,3+8*(Row(A:A)-1),8) agarra trozos de caracteres 8 a la vez, comenzando con el tercero.
  • Substitute(Mid(~),Left(A1),0) reemplaza cada instancia del primer carácter con 0.
  • Substitute(Substitute(~),Mid(A1,2,1),1) reemplaza el segundo personaje con 1.
  • Char(Bin2Dec(Substitute(~))) convierte el fragmento a decimal y luego a ASCII.
  • IfError(Char(~,""))corrige todos los errores que resultan del hecho de que Row(A:A)devuelve muchos más valores que nosotros, por lo que nos Bin2Decda muchos valores cero y Charerrores en cero.
  • ArrayFormula(Join("",IfError(~)))une todos los Charresultados y ArrayFormulaes lo que hace que el Row(A:A)retorno sea una matriz de valores en lugar de solo el primer valor.




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

Pruébalo en línea!

No es el más corto, solo una forma alternativa.

La siguiente versión imprime el resultado en una línea para 98 bytes, aunque las reglas establecen que se permite el espacio en blanco final .:

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

Pruébalo en línea!


La salida final debe estar en una línea, no en tres.
idrougge

Desde OP: "Los espacios en blanco iniciales y finales están permitidos en la salida (todo lo que coincide con / \ s * /)". Newline coincide /\s*/.
ElPedro

1
Lo siento, no estoy suficientemente versado en notación de expresiones regulares. : /
idrougge

Yo tampoco, pero lo busqué en Google solo para estar seguro ;-)
ElPedro




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

Pruébalo en línea!

fconvierte la cadena en una lista de bits comparando cada carácter con el primero, convirtiendo los Bools en ceros y unos con fromEnum. gdivide esta lista en grupos de 8, los convierte a decimal y toma el valor del número resultante como an Enum, que Chares una instancia de.

Cambios:

  • -19 bytes gracias a @Laikoni (eliminando importación, incrustando mapen la función)
  • -12 bytes inspirados en la respuesta de @ Lynn (deshacerse de la takecompresión con una lista más corta)

2
Puede usar en toEnumlugar de chry soltar la importación. También mapse puede incluir en g. El espacio entre 8 sse puede eliminar.
Laikoni el

1

Adelante (gforth) , 83 bytes

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

Pruébalo en línea!

La entrada es una cadena estándar de Forth (dirección y longitud) que se imprime en stdout

Explicación

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.