Cifrado binario

11

Esto se basa en xkcd # 153 .

Cree un programa o función con nombre que tome 2 parámetros, cada uno de los cuales es una cadena o una lista o matriz de bytes o caracteres. El segundo parámetro solo contendrá caracteres extraídos de lrfu(o los bytes ASCII equivalentes). Debe interpretarse como una serie de instrucciones que deben realizarse en una secuencia de bits representada por el primer parámetro.

El procesamiento realizado debe ser equivalente al siguiente:

  1. Convierta el primer parámetro en una sola cadena de bits formada concatenando los bits de cada carácter (interpretado como uno de ASCII de 7 bits, un ASCII extendido de 8 bits o una codificación Unicode estándar). Por ejemplo, si el primer parámetro es "AB", este sería uno de 10000011000010(7 bits), 0100000101000010(8 bits o UTF-8) 00000000010000010000000001000010, o 01000001000000000100001000000000(UTF-16 en las dos endianidades), etc.
  2. Para cada carácter en el segundo parámetro, en orden, ejecute la instrucción correspondiente:
    • lgira la cadena de bits a la izquierda. Por ejemplo, se 10000011000010convierte 00000110000101.
    • rgira la cadena de bits a la derecha. Por ejemplo, se 10000011000010convierte 01000001100001.
    • fvoltea (o invierte) cada bit en la cadena de bits. Por ejemplo, se 10000011000010convierte 01111100111101.
    • uinvierte la cadena de bits. Por ejemplo, se 10000011000010convierte 01000011000001.
  3. Convierta la cadena de bits en una cadena ASCII que utiliza un carácter por bit. Por ejemplo, se 10000011000010convierte "10000011000010". Esto se debe a que no todos los conjuntos de 7/8 bits tienen un carácter asignado.

Ejemplo (en Python):

>>> f("b", "rfu")
01110011

Se convierte "b"en su representación binaria ASCII de 8 bits 01100010, la gira hacia la derecha ( 00110001), voltea cada bit ( 11001110) y la invierte ( 01110011).

Flexibilidad

Otros caracteres se pueden utilizar en lugar de los caracteres l, r, f, y u, pero deben ser claramente documentados.

Marcador

Gracias a @Optimizer por crear el siguiente fragmento de código. Para usar, haga clic en "Mostrar fragmento de código", desplácese hasta la parte inferior y haga clic en "► Ejecutar fragmento de código".


fuente
3
¿Cuál puede ser el segundo parámetro? Puede ser "rrfrburb"? Además, cuando uno cambia o invierte bits, ¿lo hace para cada letra individual, o la cadena como un todo? Más casos de prueba lo aclararían.
xnor
1
¿Te refieres a shift o rotar? un desplazamiento a la izquierda en C dará como resultado que el bit más a la izquierda se pierda y el bit más a la derecha se vuelva cero. Para un cambio de derechos en un número sin signo, sucede lo contrario. Para un número con signo, no estoy seguro de si existe un comportamiento universalmente definido para lo que se cambia por números negativos (¿es 0 o 1?) De cualquier manera, la información siempre se pierde cuando se realiza un cambio, que no es el caso para rotar
Level River St
2
@flawr, no creo que tenga ninguna ventaja sobre la capacidad existente para buscar 'xkcd'
Peter Taylor
1
@KSFT Creo que voy a tener que decir que no a eso. Hazlo una cuerda uniéndolo.

Respuestas:

1

CJam, 34 32 bytes

1l+256b2b1>l{~"11W:mm%!<>">4%~}/

Utiliza los siguientes caracteres para las instrucciones:

0: left rotation
1: right rotation
2: reverse
3: flip

La entrada está tomando de STDIN con la palabra en la primera línea y la cadena de instrucciones en la segunda línea.

Pruébalo aquí.

Explicación

Obtener la cadena de bits es solo una cuestión de interpretar los códigos de caracteres como los dígitos de un número base 256 (y obtener su representación base 2). Lo complicado es que la última conversión de base no rellenará el resultado con 0s a la izquierda. Por lo tanto, agrego un 1 inicial a la entrada inicial, y luego divido ese 1 nuevamente en la representación binaria. Como ejemplo, si la entrada es ab, la convierto en una matriz [1 'a 'b], interpreto eso como base-256 (los caracteres se convierten automáticamente en códigos de caracteres), que es 90466y a base-2, que es [1 0 1 1 0 0 0 0 1 0 1 1 0 0 0 1 0]. Ahora, si solo elimino ese liderazgo 1, tengo el flujo de bits que estoy buscando.

Eso es lo que hace esta parte del código:

1l+256b2b1>

Ahora leo la lista de instrucciones y ejecuto un bloque para cada carácter en la cadena de instrucciones:

l{...}/

Lo primero que debe hacer es evaluar el carácter y números enteros reales 0, 1, 2o 3. Ahora, la verdadera magia del golf ... dependiendo de las instrucciones, quiero ejecutar un código corto que implemente la operación:

Integer:  Code  Operation
0         1m<   "Left rotation";
1         1m>   "Right rotation";
2         W%    "Reverse";
3         :!    "Flip each bit";

Podría almacenarlos en una matriz de bloques y elegir el bloque correcto para ejecutar, pero codificarlos en una cadena es en realidad más corto:

"11W:mm%!<>">4%~

Primero, uso el número entero asociado con la instrucción para cortar el comienzo de la cadena. Entonces, para la rotación hacia la izquierda, la cadena no cambia, para la rotación hacia la derecha se descarta el primer carácter y así sucesivamente. Luego selecciono cada cuarto carácter de la cadena, comenzando por el primero, con 4%. Observe cómo se distribuyen los cuatro fragmentos de código en toda la cadena. Finalmente solo evalúo la cadena como código con ~.

La cadena de bits se imprime automáticamente al final del programa.

Martin Ender
fuente
¿Por qué en 1m<lugar de (+? Estás trabajando en una matriz en lugar de un número, ¿no?
Peter Taylor
@ Peter oh cierto, gracias. Lo arreglaré más tarde.
Martin Ender
2

CJam, 34 bytes

Otro enfoque en CJam.

1l+256b2b1>l_S/,1&@f=_,,@f{W%~}\f=

El texto de entrada está en la primera línea y las instrucciones están en la segunda línea.

Instrucciones:

)        Rotate left.
(        Rotate right.
 (space) Flip.
~        Reverse.
jimmy23013
fuente
1
Esto es bastante inteligente. Una pena que f~no se implementa, ¿no? ;)
Martin Ender
2

Pyth 33

jku@[+eGPG+tGhG_Gms!dG)sHwsmjCk2z

Usos:

0    : rotate right
1    : rotate left
2    : reverse order
3    : flip values

Pyth github

Pruébelo en línea aquí.

Este es un programa que toma la cadena como primer argumento y la cadena de comandos como segundo argumento. En la versión en línea, debe dar las cadenas separadas por una nueva línea, así:

AbC
0321

Explicación:

                                    : z=input() (implicit)
jk                                  : join("", ...)
  u@[                 )sHw          : reduce(select from [...] the value at int(H), input(), ...)
     +eGPG                          : [ G[-1] + G[:1],
          +tGhG                     : G[1:] + G[1],
               _G                   : G[::-1],
                 ms!dG              : map(lambda d: int(not(d)), G) ]
                          smjCk2z   : first arg = sum(map(lambda k:convert_to_base(ord(k),2),z)

Algo que no pude comprender: Pyth's reduceusa automáticamente Gel valor anterior y Hel siguiente.

FryAmTheEggman
fuente
¿Perdiendo tu toque? ¿Solo 1 byte más corto que CJam?
Optimizador
@Optimizer En realidad, puedo superar eso usando las mismas instrucciones. Pero no pensé que esto sería válido porque el desafío dice "Se pueden usar otras letras en lugar de lrfu, pero deben estar claramente documentadas". (énfasis mío)
Martin Ender
1

Scala - 192

def f(i:String,l:String)=(i.flatMap(_.toBinaryString).map(_.toInt-48)/:l){
case(b,'l')⇒b.tail:+b.head
case(b,'r')⇒b.last+:b.init
case(b,'f')⇒b.map(1-_)
case(b,'u')⇒b.reverse}.mkString
gilad hoch
fuente
1

Matlab (166 bytes)

Esto usa letras en abcdlugar de lrfurespectivamente.

function D=f(B,C)
D=dec2bin(B,8)';
D=D(:);
g=@circshift;
for c=C
switch c-97
case 0
D=g(D,-1);
case 1
D=g(D,1);
case 2
D=char(97-D);
case 3
D=flipud(D);
end
end
D=D';

Algunos trucos utilizados aquí para ahorrar espacio:

  • El uso de abcdlas letras me permite restar 97una vez, y luego se convierten en las letras 0, 1, 2, 3. Esto ahorra espacio en los switch- casecláusulas.
  • La definición circshiftcomo una función anónima de una letra también ahorra espacio, ya que se usa dos veces.
  • Dado que Dconsta de '0'y '1'caracteres (códigos ASCII 48y 49), la declaración D=char(97-D)corresponde a inversión entre '0'y '1'valores. Tenga en cuenta que esto 97no tiene nada que ver con lo mencionado anteriormente.
  • La transposición de conjugado complejo 'se usa en lugar de la transposición .'.
Luis Mendo
fuente
0

Pitón 2 - 179

b="".join([bin(ord(i))[2:]for i in input()])
for i in input():b=b[-1]+b[:-1]if i=="r"else b[1:]+b[0]if i=="l"else[str("10".find(j))for j in b]if i=="f"else b[::-1]
print"".join(b)
KSFT
fuente
0

C #, 418 bytes

using System;using System.Collections.Generic;using System.Linq;class P{string F(string a,string o){var f=new Dictionary<char,Func<string,IEnumerable<char>>>{{'l',s=>s.Substring(1)+s[0]},{'r',s=>s[s.Length-1]+s.Substring(0,s.Length-1)},{'u',s=>s.Reverse()},{'f',s=>s.Select(c=>(char)(97-c))}};return o.Aggregate(string.Join("",a.Select(c=>Convert.ToString(c,2).PadLeft(8,'0'))),(r,c)=>new string(f[c](r).ToArray()));}}

Formateado:

using System;
using System.Collections.Generic;
using System.Linq;

class P
{
    string F(string a, string o)
    {
        // define string operations
        var f = new Dictionary<char, Func<string, IEnumerable<char>>>
        {
            {'l', s => s.Substring(1) + s[0]},
            {'r', s => s[s.Length - 1] + s.Substring(0, s.Length - 1)},
            {'u', s => s.Reverse()},
            {'f', s => s.Select(c => (char) (97 - c))}
        };
        // for each operation invoke f[?]; start from converted a
        return o.Aggregate(
            // convert each char to binary string, pad left to 8 bytes and join them
            string.Join("", a.Select(c => Convert.ToString(c, 2).PadLeft(8, '0'))),
            // invoke f[c] on result of prev operation
            (r, c) => new string(f[c](r).ToArray())
        );
    }
}
Krzysztof
fuente
0

J, 164

([: >@:}. (([: }. >&{.) ; >@:{.@:>@:{. 128!:2 >@:}.)^:({.@:$@:>@:{.))@:(>@:((<;._1 ' 1&|."1 _1&|."1 -. |."1') {~ 'lrfu' i. 0&({::)@:]) ; ;@:([: (8$2)&#: a. i. 1&({::)))

Formateado:

nextop=:([: }. >&{.)
exec=: (>@:{.@:>@:{.) apply"1 >@:}.
times=: ({.@:$@:>@:{.)
gapply=: [: >@:}. (nextop ; exec)^:(times) f.

tobin=: ;@:([: (8#2)&#:(a.i.1&{::))
g=:'1&|.';'_1&|.';'-.';'|.'
tog =:  g {~ ('lrfu' i. 0&{::@:])
golf=: gapply @: (>@:tog;tobin)  f.

Ejemplo

golf ('rfu';'b')
0 1 1 1 0 0 1 1


golf ('lruuff';'b')
0 1 1 0 0 0 1 0

(8#2)#: 98
0 1 1 0 0 0 1 0

golf ('lruuff';'AB')
0 1 0 0 0 0 0 1 0 1 0 0 0 0 1 0

tobin '';'AB'
0 1 0 0 0 0 0 1 0 1 0 0 0 0 1 0
joebo
fuente
0

JavaScript (E6), 163 167

Utilizando completamente la flexibilidad de entrada, una función con nombre con 2 parámetros de matriz.

  • Primer parámetro, matriz de bytes correspondiente a códigos de caracteres de 7 bits
  • Segundo parámetro, matriz de bytes correspondiente a los caracteres ascii 'F', 'L', 'R', 'U' -> 70, 76, 82, 85

La función devuelve una cadena de caracteres compuesta por '1' y '0'

F=(a,s,r='')=>
  a.map(c=>r+=(128|c).toString(2).slice(-7))-
  s.map(c=>a=c<71?a.map(c=>1-c):c<77?a.concat(a.shift):c<83?[a.pop(),...a]:a.reverse(),a=[...r])
  ||a.join('')

Ejemplo f("b", "rfu") traducir a F([98],[82,70,85]), el resultado es0111001

¡Tenga en cuenta que el uso de cadenas de caracteres es mucho más largo en javascript! Cuenta de bytes 186

F=(a,s,r='')=>
  [for(c of a)r+=(128|c.charCodeAt()).toString(2).slice(-7)]-
  [for(c of(a=[...r],s))a=c<'G'?a.map(c=>1-c):c<'M'?a.concat(a.shift):c<'S'?[a.pop(),...a]:a.reverse()]
  ||a.join('')

Ejemplo F("b", "RFU") , el resultado es 0111001nuevamente

edc65
fuente
0

Rubí, 151

f=->i,s{s.chars.inject(i.unpack("B*")[0]){|a,c|
a.reverse! if c==?u
a.tr!"01","10" if c==?f
a<<a.slice!(1..-1) if c==?l
a<<a.slice!(0..-2) if c==?r
a}}

Bastante sencillo. Recorre los caracteres sy realiza una acción para cualquiera de ellos.

britishtea
fuente
0

Pitón 2, 142

j="".join
f=lambda S,I:reduce(lambda s,i:[s[1:]+s[0],s[-1]+s[:-1],s[::-1],j([`1^int(c)`for c in s])][int(i)],I,j([bin(ord(c))[2:]for c in S]))

Similar a mi respuesta de pyth en el enfoque: construyo una lista de todas las cadenas e indexo en él en función del valor de la cadena de instrucciones que itero usando reducir.

Usos:

0  ->  Rotate left
1  ->  Rotate right
2  ->  Reverse order
3  ->  Invert bits
FryAmTheEggman
fuente