Cryptage binaire

11

Ceci est basé sur xkcd # 153 .

Créez un programme ou une fonction nommée qui prend 2 paramètres, chacun étant une chaîne ou une liste ou un tableau d'octets ou de caractères. Le deuxième paramètre ne contiendra que des caractères tirés de lrfu(ou les octets ASCII équivalents). Elle doit être interprétée comme une série d'instructions à exécuter sur une séquence de bits représentée par le premier paramètre.

Le traitement effectué doit être équivalent à ce qui suit:

  1. Convertissez le premier paramètre en une seule chaîne de bits formée en concaténant les bits de chaque caractère (interprété comme l'un des codes ASCII 7 bits, ASCII étendu 8 bits ou un codage Unicode standard). Par exemple, si le premier paramètre est "AB"alors ce serait l'un de 10000011000010(7 bits), 0100000101000010(8 bits ou UTF-8) 00000000010000010000000001000010, ou 01000001000000000100001000000000(UTF-16 dans les deux endiannesses), etc.
  2. Pour chaque caractère du deuxième paramètre, dans l'ordre, exécutez l'instruction correspondante:
    • lfait tourner la chaîne de bits à gauche. Par exemple, 10000011000010devient 00000110000101.
    • rfait tourner la chaîne de bits à droite. Par exemple, 10000011000010devient 01000001100001.
    • fretourne (ou inverse) chaque bit de la chaîne de bits. Par exemple, 10000011000010devient 01111100111101.
    • uinverse la chaîne de bits. Par exemple, 10000011000010devient 01000011000001.
  3. Convertissez la chaîne de bits en une chaîne ASCII qui utilise un caractère par bit. Par exemple, 10000011000010devient "10000011000010". En effet, tous les ensembles de 7/8 bits n'ont pas de caractère attribué.

Exemple (en Python):

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

Il se transforme "b"en sa représentation binaire ASCII 8 bits 01100010, le fait pivoter vers la droite ( 00110001), retourne chaque bit ( 11001110) et l'inverse ( 01110011).

Souplesse

D' autres caractères peuvent être utilisés à la place des personnages l, r, fet u, mais ils doivent être clairement documentées.

Tableau d'affichage

Merci à @Optimizer avoir créé l'extrait de code suivant. Pour l'utiliser, cliquez sur "Afficher l'extrait de code", faites défiler vers le bas et cliquez sur "► Exécuter l'extrait de code".


la source
3
Quel peut être le deuxième paramètre? Est-ce possible "rrfrburb"? De plus, lorsque l'on décale ou inverse des bits, le fait-on pour chaque lettre individuelle ou pour la chaîne dans son ensemble? Plus de cas de test le rendraient plus clair.
xnor
1
Voulez-vous dire décalage ou rotation? un décalage à gauche en C entraînera la perte du bit le plus à gauche et le bit le plus à droite devenant nul. Pour un changement de droits sur un numéro non signé, l'inverse se produit. Pour un numéro signé, je ne sais pas s'il existe un comportement universellement défini pour ce qui est décalé pour les nombres négatifs (est-ce 0 ou 1?) Dans les deux cas, les informations sont toujours perdues lorsqu'un décalage est effectué, ce qui n'est pas le cas pour une rotation.
Level River St
2
FWIW il y a déjà une question basée sur ce XKCD .
Peter Taylor
2
@flawr, je ne pense pas que cela aurait un avantage sur la capacité existante de rechercher 'xkcd'
Peter Taylor
1
@KSFT Je pense que je vais devoir dire non à cela. Faites-en une chaîne en la joignant.

Réponses:

1

CJam, 34 32 octets

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

Il utilise les caractères suivants pour les instructions:

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

L'entrée provient de STDIN avec le mot sur la première ligne et la chaîne d'instructions sur la deuxième ligne.

Testez-le ici.

Explication

Obtenir la chaîne de bits est vraiment juste une question d'interprétation des codes de caractères comme les chiffres d'un nombre en base 256 (et d'obtenir sa représentation en base 2). La chose délicate est que cette dernière conversion de base ne remplira pas le résultat avec des 0 à gauche. Par conséquent, j'ajoute un 1 de tête à l'entrée initiale, puis je le scinde à nouveau dans la représentation binaire. Par exemple, si l'entrée est ab, je la transforme en un tableau [1 'a 'b], interprète cela comme base-256 (les caractères sont automatiquement convertis en codes de caractères), ce qui est 90466et en base-2, qui l'est [1 0 1 1 0 0 0 0 1 0 1 1 0 0 0 1 0]. Maintenant, si je supprime simplement ce leader1 début, j'ai le train de bits que je recherche.

C'est ce que fait cette partie du code:

1l+256b2b1>

Maintenant, je lis la liste des instructions et exécute un bloc pour chaque caractère de la chaîne d'instructions:

l{...}/

La première chose à faire est d'évaluer le caractère et les entiers réels 0, 1, 2ou 3. Maintenant, la vraie magie du golf ... en fonction de l'instruction, je veux exécuter un court morceau de code qui implémente l'opération:

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

Je pourrais les stocker dans un tableau de blocs et choisir le bon bloc à exécuter, mais les encoder dans une chaîne est en fait plus court:

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

Tout d'abord, j'utilise l'entier associé à l'instruction pour couper le début de la chaîne. Ainsi, pour la rotation à gauche, la chaîne est inchangée, pour la rotation à droite, le premier caractère est supprimé et ainsi de suite. Ensuite, je sélectionne chaque quatrième caractère de la chaîne, en commençant par le premier, avec 4%. Remarquez comment les quatre extraits de code sont distribués dans la chaîne. Enfin, j'évalue simplement la chaîne en tant que code avec ~.

La chaîne de bits est imprimée automatiquement à la fin du programme.

Martin Ender
la source
Pourquoi 1m<plutôt que (+? Vous travaillez sur un tableau plutôt que sur un nombre, n'est-ce pas?
Peter Taylor
@Peter oh oui, merci. Je vais arranger ça plus tard.
Martin Ender
2

CJam, 34 octets

Une autre approche dans CJam.

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

Le texte saisi se trouve sur la première ligne et les instructions se trouvent sur la deuxième ligne.

Instructions:

)        Rotate left.
(        Rotate right.
 (space) Flip.
~        Reverse.
jimmy23013
la source
1
C'est assez intelligent. Une honte qui f~n'est pas implémentée cependant, n'est-ce pas? ;)
Martin Ender
2

Pyth 33

jku@[+eGPG+tGhG_Gms!dG)sHwsmjCk2z

Les usages:

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

Gythub Pyth

Essayez-le en ligne ici.

Il s'agit d'un programme qui prend la chaîne comme premier argument et la chaîne de commandes comme deuxième argument. Dans la version en ligne, vous devez donner les chaînes séparées par une nouvelle ligne, comme ceci:

AbC
0321

Explication:

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

Quelque chose que je ne pouvais pas vraiment saisir: Pyth reduceutilise automatiquement Gla valeur précédente et Hla valeur suivante.

FryAmTheEggman
la source
Vous perdez votre contact? Juste 1 octet de moins que CJam?
Optimizer
@Optimizer En fait, je peux battre cela en utilisant les mêmes instructions. Mais je ne pensais pas que ce serait valable parce que le défi dit "D'autres lettres peuvent être utilisées à la place lrfu, mais elles doivent être clairement documentées." (c'est moi qui souligne)
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
la source
1

Matlab (166 octets)

Cela utilise des lettres abcdau lieu de lrfurespectivement.

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';

Quelques astuces utilisées ici pour économiser de l'espace:

  • En utilisant des abcdlettres me permet soustrais 97une fois, puis les lettres deviennent 0, 1, 2, 3. Cela économise de l'espace dans le switch-case clauses .
  • La définition circshiftd'une fonction anonyme à une lettre économise également de l'espace, car elle est utilisée deux fois.
  • Puisqu'il se Dcompose de '0'et de '1'caractères (codes ASCII 48et 49), l'instruction D=char(97-D)correspond à l'inversion entre les valeurs '0'et '1'. Notez que cela 97n'a rien à voir avec celui mentionné ci-dessus.
  • La transposition conjugué complexe 'est utilisée à la place de la transposition .'.
Luis Mendo
la source
0

Python 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
la source
0

C #, 418 octets

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()));}}

Formaté:

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
la source
0

J, 164

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

Formaté:

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.

Exemple

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
la source
0

JavaScript (E6), 163 167

Utilisant pleinement la flexibilité d'entrée, une fonction nommée avec 2 paramètres de tableau.

  • Premier paramètre, tableau d'octets correspondant aux codes de caractères à 7 bits
  • Deuxième paramètre, tableau d'octets correspondant aux caractères ascii 'F', 'L', 'R', 'U' -> 70, 76, 82, 85

La fonction renvoie une chaîne de caractères composée de «1» et «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('')

Exemple f("b", "rfu") traduit en F([98],[82,70,85]), le résultat est0111001

Notez que l' utilisation de chaînes de caractères est beaucoup plus longue en javascript! Nombre d'octets 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('')

Exemple F("b", "RFU") , le résultat est à 0111001nouveau

edc65
la source
0

Rubis, 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}}

Assez simple. Boucles à travers les personnages set exécute une action pour l'un d'eux.

britishtea
la source
0

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

Semblable à ma réponse pyth en approche: je construis une liste de toutes les chaînes et l'indexer en fonction de la valeur de la chaîne d'instruction que j'itère en utilisant réduire.

Les usages:

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