Crittografia della finestra PI


13

Questo è un semplice metodo di crittografia che utilizza cifre PI per codificare un messaggio, il metodo è semplice:

La chiave è solo un numero intero positivo che indica dove inizia la finestra:

Data una stringa da crittografare, contenente solo lettere minuscole, senza spazi, ne prendi la lunghezza, quindi trovi l'ennesima cifra di PI e procedi quindi a spostare ogni lettera a destra per l'importo indicato dalla cifra.

Ad esempio, se la chiave è 2e voglio codificare house, prendo una finestra di 5 cifre dalla seconda: 14159e poi diventa:

h -> i
o -> s
u -> v
s -> x
e -> n

a.- Il tuo programma / funzione / algoritmo riceverà due parametri, una stringa composta solo da lettere minuscole senza spazi e la chiave, che sarà solo un numero intero positivo compreso tra 1 (1 si riferisce a 3) e 1000, che potrebbe essere maggiore o meno poiché non sono del tutto sicuro del tempo necessario per calcolare il PI con detta precisione perché:

b.- Devi calcolare te stesso PI nel tuo codice, ecco una pagina web ordinata da confrontare con: Pi Day . L'input non dovrebbe mai farti calcolare PI oltre la cifra di 1000, il che significa che lunghezza (messaggio) + chiave <= 1000.

Con il calcolo di Pi, intendo non codificarlo nel tuo codice (sciocco per un codice golf) né usare alcuna costante incorporata nel tuo codice né alcuna identità trigonometrica (2 * acos (0)) né alcun riferimento web.

c.- L'output sarà solo la stringa crittografata.

Questa è una domanda di golf del codice, il codice più corto vince!

Accetterò la risposta vincente il 14 luglio 2014.


1
Cosa succede quando le lettere vengono spostate oltre la fine dell'alfabeto? Si verifica l'inizio dell'alfabeto o qualcos'altro?
Digital Trauma,

1
Sì, ricominciare da capo.
BrunoJ,

6
Cosa conta come "calcola te stesso"? ArcCos(-1)?
Martin Ender,

1
Ho spiegato meglio cosa volevo dire calcolandolo tu stesso e ho indicato che 3 è la prima cifra.
BrunoJ,

1
Questo in realtà sembra un algoritmo di crittografia davvero intelligente, perché non è ampiamente usato (tranne con una costante più complicata come e ^ pi o qualcosa di meno riconoscibile)?
CHIEDERE il

Risposte:


3

CJam - 51

l_,li(2e4,-2%{2+_2/@*\/2e2000+}*Ab><]z{~+_'z>26*-}%

Esempio di input:

zebra
20

Produzione:

dkdxe

Funziona con (lunghezza stringa) + tasto <= 2000, ma è piuttosto lento per l'interprete online (ancora veloce con l'interprete java).

Ecco una versione che funziona fino a 200 e puoi provare su http://cjam.aditsu.net/ senza aspettare troppo a lungo:

l_,li(2e3,-2%{2+_2/@*\/2e200+}*Ab><]z{~+_'z>26*-}%

5

Python - 370

Ok, bello, finalmente ho funzionato grazie a link1 e link2 .

from decimal import *
def f(s,n): 
 j=len(s)
 getcontext().prec=j+n+5
 d=Decimal
 e=d(0)
 for k in range(0,j+n+5): 
  e+=(d(16)**(-k)*(d(4)/(8*k+1)-d(2)/(8*k+4)-d(1)/(8*k+5)-d(1)/(8*k+6)))
 c=`e`.split("'")[1].replace('.','')
 t=''
 for i,l in enumerate(s):
  o=ord(l)
  for v in[0,32]:
   if 64+v<o<91+v:
    l=chr(((o-65-v)+int(c[i+n-1]))%26+65+v)
  t+=l   
 print t

Esempio di output:

>>> f('house',2)
isvxn

e un altro:

Wimt fcy d dnyh uhkvkv qhvadil   

>>> f ('Questo era un messaggio molto segreto', 1)


1

JavaScript - 167 173 176

Grazie a Michael per la rappresentazione intelligente dei poteri di 16.

Questo può calcolare PI fino alla 16a cifra.

function e(s,o){for(p=i=n=r='',m=1;s[+i];m<<=4,n>o?r+=String.fromCharCode(s.charCodeAt(i)-+-(1e15*p+'')[o+i++]):0)p-=(4/((d=8*n++)+1)-2/(d+=4)-1/++d-1/++d)/m;return r}

Il caso di prova:

> e("house",2)
"isvxn"

Che dire di m=1e m<<=4invece di m='0x1'e m+=0? Salva 3 byte.
Michael M.

1

Python - 321 304 288 285

from decimal import*
d=Decimal
s,n=raw_input(),input()
l=len(s)
getcontext().prec=n+l
print''.join([chr((v-97)%26+97)for v in map(sum,zip(map(ord,s),map(int,str(sum([(d(4)/(8*k+1)-d(2)/(8*k+4)-d(1)/(8*k+5)-d(1)/(8*k+6))/16**k for k in range(0,l+n)])).replace('.','')[n-1:n+l])))])

La maggior parte della versione golfata è di facile lettura e comprensione. La riga finale non è scritta sotto:

# Calculate PI using the BBP formula.
pi = 0
for k in range(0,l+n):
    pi += (d(1)/(16**k))*((d(4)/(8*k+1))-(d(2)/(8*k+4))-(d(1)/(8*k+5))-(d(1)/(8*k+6)))

# Remove the decimal point in PI.
pi = str(pi).replace('.','')

result = []
# For the ASCII sum of each pair of letters in `s` and its digit in PI 
for v in sum(zip(map(ord, s), map(int, pi))):
    result.append((v-97)%26+97)

# Convert all the ordinal values to characters
print ''.join(map(chr, result))

EDIT # 1: semplificato l'aritmetica del mio modulo.

EDIT # 2: refactored la formula BBP.


0

Haskell - 265 267 byte (no IO)

p=g(1,0,1,1,3,3)where g(q,r,t,k,n,l)=if 4*q+r-t<n*t then n:g(10*q,10*(r-n*t),t,k,div(10*(3*q+r))t-10*n,l) else g(q*k,(2*q+r)*l,t*l,k+1,div(q*(7*k+2)+r*l)(t*l),l+2)
e i s=zipWith(\k c->toEnum$fromIntegral k+fromEnum c::Char)(take(length s)$drop(fromIntegral$i-1)p)s

pè una versione golfizzata dell'algoritmo che può essere trovata su http://rosettacode.org/wiki/Pi#Haskell

e è la funzione di codifica:

λ> e 2 "house"
"isvxn"

Non esegue il ciclo continuo se un indice si trova all'esterno dell'alfabeto minuscolo. Ciò significa che alcuni altri caratteri possono scivolare nella stringa codificata:

"Sfufv#Kork(mq}nns j{i&sv&xitmujtu&vey|h{xljej|35.)(\"%(\"\"&\" %\"\"$()$ ''\"&'!)$'(\"&($(\"& !$'&)]hrs\"ow olih7$Tdkhnsj ns&qpdlw}oplwmxbipn#o{ur!vhbp\"mitj/"

Sfortunatamente, ci vogliono diversi secondi con offset maggiori di 10 000 al calcolo dell'output. Fortunatamente, quando si utilizza lo stesso offset più volte, le cifre devono essere calcolate solo la prima volta.

Bonus - Decodifica

d i s=zipWith(\k c->toEnum$fromEnum c-fromIntegral k::Char)(take(length s)$drop(i-1)p)s

Ancora una volta se testiamo con isvxn:

λ> d 2 "isvxn"
"house"

Hai fatto un refuso nella sezione bonus. d 2 "isvsn"dovrebbe essered 2 "isvxn"
Spedwards,

Fisso. Grazie per averlo notato.
gxtaillon,

0

CoffeeScript - 148 caratteri / byte

Il mio primo Code Golf in assoluto

Sfortunatamente non supporta il wrapping (quindi az finirebbe per essere punteggiatura)

e = (m, k) -> (m.split (''). map (v, i) -> String.fromCharCode v.charCodeAt () + parseInt Math.PI.toString (). replace ('.', '') .slice (k-1, k-m.length + 1) [i]). join ( '')

Demo su CSSDeck

Chiamato con:

allerta e 'casa', 2

isvxn


Hai letto l'intera domanda, in quanto indica chiaramente che non ti è consentito "utilizzare alcuna costante incorporata nel tuo codice"?
core1024
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.