Crittografia binaria


11

Questo si basa su xkcd # 153 .

Crea un programma o una funzione con nome che accetta 2 parametri, ognuno dei quali è una stringa o un elenco o una matrice di byte o caratteri. Il secondo parametro conterrà solo caratteri estratti da lrfu(o byte ASCII equivalenti). Dovrebbe essere interpretato come una serie di istruzioni da eseguire su una sequenza di bit rappresentata dal primo parametro.

Il trattamento eseguito deve essere equivalente al seguente:

  1. Converti il ​​primo parametro in una singola stringa di bit formata concatenando i bit di ciascun carattere (interpretato come uno di ASCII a 7 bit, un ASCII esteso a 8 bit o una codifica Unicode standard). Ad esempio, se il primo parametro è "AB"allora questo sarebbe uno di 10000011000010(7 bit), 0100000101000010(8 bit o UTF-8) 00000000010000010000000001000010, o 01000001000000000100001000000000(UTF-16 nei due endiannesses), ecc.
  2. Per ogni carattere nel secondo parametro, in ordine, eseguire le istruzioni corrispondenti:
    • lruota la stringa di bit a sinistra. Ad esempio 10000011000010diventa 00000110000101.
    • rruota la stringa di bit a destra. Ad esempio 10000011000010diventa 01000001100001.
    • finverte (o inverte) ogni bit nella stringa di bit. Ad esempio 10000011000010diventa 01111100111101.
    • uinverte la stringa di bit. Ad esempio 10000011000010diventa 01000011000001.
  3. Converti la stringa di bit in una stringa ASCII che utilizza un carattere per bit. Ad esempio 10000011000010diventa "10000011000010". Questo perché non tutti i set di 7/8 bit hanno un carattere assegnato a loro.

Esempio (in Python):

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

Si trasforma "b"nella sua rappresentazione binaria ASCII a 8 bit 01100010, la ruota a destra ( 00110001), capovolge ogni bit ( 11001110) e lo inverte ( 01110011).

Flessibilità

Altri caratteri possono essere utilizzati al posto dei caratteri l, r, f, e u, ma devono essere chiaramente documentati.

tabellone segnapunti

Grazie a @Optimizer per aver creato il seguente frammento di codice. Per utilizzare, fai clic su "Mostra frammento di codice", scorri verso il basso e fai clic su "► Esegui frammento di codice".


3
Quale può essere il secondo parametro? Può essere "rrfrburb"? Inoltre, quando uno sposta o inverte i bit, lo fa per ogni singola lettera o per la stringa nel suo insieme? Altri casi di test lo renderebbero più chiaro.
xnor

1
Intendi spostamento o rotazione? uno spostamento a sinistra in C comporterà la perdita del bit più a sinistra e il bit più a destra diventerà zero. Per uno spostamento dei diritti su un numero senza segno, accade il contrario. Per un numero con segno non sono sicuro che esista un comportamento definito universalmente per ciò che viene spostato per i numeri negativi (è 0 o 1?) Ad ogni modo, le informazioni vengono sempre perse quando viene effettuato un turno, che non è il caso per una rotazione.
Level River St


2
@flawr, non credo che avrebbe alcun vantaggio rispetto alla capacità esistente di cercare "xkcd"
Peter Taylor,

1
@KSFT Penso che dovrò dire di no. Trasformalo in una stringa unendoti.

Risposte:


1

CJam, 34 32 byte

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

Utilizza i seguenti caratteri per le istruzioni:

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

L'input sta prendendo da STDIN con la parola sulla prima riga e la stringa di istruzioni sulla seconda riga.

Provalo qui.

Spiegazione

Ottenere la stringa di bit è in realtà solo una questione di interpretazione dei codici carattere come le cifre di un numero base-256 (e ottenere la sua rappresentazione base-2). La cosa difficile è che quest'ultima conversione di base non riempie il risultato con 0s a sinistra. Pertanto, aggiungo un 1 iniziale all'input iniziale, quindi divido nuovamente 1 nella rappresentazione binaria. Ad esempio, se l'input è ab, lo trasformo in un array [1 'a 'b], lo interpreto come base-256 (i caratteri vengono automaticamente convertiti in codici carattere), che è 90466e il in base-2, che è [1 0 1 1 0 0 0 0 1 0 1 1 0 0 0 1 0]. Ora, se rimuovo quel vantaggio, 1ho il bitstream che sto cercando.

Ecco cosa fa questa parte del codice:

1l+256b2b1>

Ora ho letto l'elenco delle istruzioni ed eseguo un blocco per ogni carattere nella stringa di istruzioni:

l{...}/

La prima cosa da fare è quello di valutare il carattere e interi effettivi 0, 1, 2o 3. Ora la vera magia del golf ... a seconda delle istruzioni voglio eseguire un breve codice che implementa l'operazione:

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

Potrei memorizzarli in una matrice di blocchi e scegliere il blocco giusto da eseguire, ma codificarli in una stringa è in realtà più breve:

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

In primo luogo, utilizzo l'associato intero con l'istruzione per tagliare l'inizio della stringa. Quindi per la rotazione a sinistra, la stringa rimane invariata, per la rotazione a destra il primo carattere viene scartato e così via. Quindi seleziono ogni quarto carattere dalla stringa, a partire dal primo, con 4%. Nota come i quattro frammenti di codice sono distribuiti in tutta la stringa. Infine, valuto la stringa come codice con ~.

La stringa di bit viene stampata automaticamente alla fine del programma.


Perché 1m<piuttosto che (+? Stai lavorando su un array piuttosto che su un numero, vero?
Peter Taylor,

@Peter oh giusto, grazie. Lo aggiusterò più tardi.
Martin Ender,

2

CJam, 34 byte

Un altro approccio in CJam.

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

Il testo di input è sulla prima riga e le istruzioni sono sulla seconda riga.

Istruzioni:

)        Rotate left.
(        Rotate right.
 (space) Flip.
~        Reverse.

1
Questo è abbastanza intelligente. Un peccato che f~non sia implementato, vero? ;)
Martin Ender,

2

Pyth 33

jku@[+eGPG+tGhG_Gms!dG)sHwsmjCk2z

usi:

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

Pyth Github

Provalo online qui.

Questo è un programma che accetta la stringa come primo argomento e la stringa di comandi come secondo argomento. Nella versione online, dovresti dare le stringhe separate da una nuova riga, in questo modo:

AbC
0321

Spiegazione:

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

Qualcosa che non riuscivo a comprimere: Pyth's reduceusa automaticamente Gper il valore precedente e Hper il valore successivo.


Perdi il tuo tocco? Solo 1 byte in meno di CJam?
Ottimizzatore

@Optimizer In realtà, posso batterlo usando le stesse istruzioni. Ma non pensavo che questo sarebbe valido perché la sfida dice "Al posto di possono essere usate altre letterelrfu , ma devono essere chiaramente documentate". (enfasi mia)
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

1

Matlab (166 byte)

Questo utilizza lettere abcdanziché lrfurispettivamente.

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

Alcuni trucchi usati qui per risparmiare spazio:

  • Utilizzando abcdle lettere mi permette di sottrarre 97una volta, e poi le lettere diventano 0, 1, 2, 3. Ciò consente di risparmiare spazio nelle clausole switch- case.
  • La definizione circshiftcome funzione anonima di una lettera consente di risparmiare spazio, poiché viene utilizzata due volte.
  • Poiché è Dcostituito da '0'e '1'caratteri (codici ASCII 48e 49), l'istruzione D=char(97-D)corrisponde all'inversione tra '0'e '1'valori. Si noti che ciò 97non ha nulla a che fare con quello di cui sopra.
  • Al 'posto del trasposizione viene utilizzata la trasposizione coniugata complessa .'.

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)

0

C #, 418 byte

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

formattato:

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

0

J, 164

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

formattato:

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.

Esempio

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

0

JavaScript (E6), 163 167

Sfruttando appieno la flessibilità di input, una funzione denominata con 2 parametri di array.

  • Primo parametro, matrice di byte corrispondente a codici carattere a 7 bit
  • Secondo parametro, matrice di byte corrispondente ai caratteri ASCII 'F', 'L', 'R', 'U' -> 70, 76, 82, 85

La funzione restituisce una stringa di caratteri composta da '1' e '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('')

L'esempio si f("b", "rfu") traduce in F([98],[82,70,85]), il risultato è0111001

Nota che usare stringhe di caratteri è molto più lungo in JavaScript! Conteggio byte 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('')

Esempio F("b", "RFU") , il risultato è di 0111001nuovo


0

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

Abbastanza semplice. Passa attraverso i personaggi sed esegue un'azione per ognuno di essi.


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

Simile alla mia risposta Pyth in approccio: ho creato un elenco di tutte le stringhe e indicizzato in essa in base al valore della stringa di istruzioni su cui ripeto usando ridurre.

usi:

0  ->  Rotate left
1  ->  Rotate right
2  ->  Reverse order
3  ->  Invert bits
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.