# PI window encryption

This is a simple encryption method that uses PI digits to encode a message, the method is simple:

The key is just a positive integer that indicates where the window starts then:

Given a string to encrypt, containing only lowercase letters, no spaces, you take its length, then you find the Nth digit of PI and then proceeds to shift every letter to the right for the amount indicated by the digit.

For example, if the key is 2 and I want to encode house, I take a window of 5 digits from the second one: 14159 and then it becomes:

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


a.- Your program/function/algorithm will receive two parameters, an string composed only of lowercase letters with no spaces and the key, which will be just a positive integer between 1 (1 refers to 3) and 1000, which could be more or less as I'm not quite sure how long does it take to compute PI with said accuracy because:

b.- You must compute PI yourself in your code, here is a neat webpage to compare with: Pi Day. The input should never have you calculate PI beyond the 1000 digit, meaning that length(message)+key <= 1000.

By computing Pi, I mean not harcode it in your code (silly for a code golf) nor use any embedded constant in your code nor any trigonometric identity (2*acos(0)) nor any web reference.

c.- The output will be just the encrypted string.

This is a code golf question, shorter code wins!

I'll be accepting the winning answer at July 14th, 2014.

• What happens when letters are shifted past the end of the alphabet? Does wrap-around to the beginning of the alphabet occur or something else? – Digital Trauma Jun 27 '14 at 22:39
• Yes, you just start over from the beginning. – BrunoJ Jun 27 '14 at 22:51
• What counts as "compute yourself"? ArcCos(-1)? – Martin Ender Jun 28 '14 at 0:04
• I explained better what I wanted to say by computing it yourself and pointed that 3 is the first digit. – BrunoJ Jun 28 '14 at 1:09
• This actually seems like a really smart encryption algorithm, why isn't this widely used (except with a more complicated constant like e^pi or something less recognizable)? – ASKASK Jun 28 '14 at 22:55

# CJam - 51

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


Example input:

zebra
20


Output:

dkdxe


This works for (string length) + key <= 2000, but is quite slow for the online interpreter (still fast with the java interpreter).

Here's a version that works up to 200 and you can try at http://cjam.aditsu.net/ without waiting too long:

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


# Python - 370

Ok, nice one, finally got the pi thing working with thanks to link1 and 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


Example output:

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


and another:

Wimt fcy d dnyh uhkvkv qhvadil


>>> f('This was a very secret message',1)

# JavaScript - 167 173176

Thanks to Michael for the clever representation of powers of 16.

This can calculate PI up to the 16-th digit.

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}


The test case:

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

• What about m=1 and m<<=4 instead of m='0x1' and m+=0 ? Saves 3 bytes. – Michael M. Jun 30 '14 at 9:19

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


Most of the golfed version is easy to read and understand. The final line is ungolfed below:

# 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: simplified my module arithmetic.

EDIT #2: refactored the BBP formula.

# Haskell - 265 267 bytes (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 is a golfed version of the algorithm that can be found at http://rosettacode.org/wiki/Pi#Haskell e is the encoding function : λ> e 2 "house" "isvxn"  It does not loop around if an index is outside of the lowercase alphabet. This means that some other characters can slip in the encoded string : "Sfufv#Kork(mq}nns j{i&sv&xitmujtu&vey|h{xljej|35.)(\"%(\"\"&\" %\"\"$()$''\"&'!)$'(\"&($(\"& !$'&)]hrs\"ow olih7$Tdkhnsj ns&qpdlw}oplwmxbipn#o{ur!vhbp\"mitj/"  Unfortunately, it takes several seconds with offsets greater than 10 000 to compute the output. Fortunately, when using the same offset multiple times, the digits only have to be computed the first time. # Bonus - Decoding d i s=zipWith(\k c->toEnum$fromEnum c-fromIntegral k::Char)(take(length s)\$drop(i-1)p)s


Again if we test with isvxn :

λ> d 2 "isvxn"
"house"

• Made a typo in your bonus section. d 2 "isvsn" should be d 2 "isvxn" – Spedwards Jun 30 '14 at 8:47
• Fixed. Thanks for noticing. – gxtaillon Jun 30 '14 at 9:44

# CoffeeScript - 148 Chars/Bytes

My first ever Code Golf

Unfortunately It does not support wrapping (So a z would end up being punctuation)

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

Demo on CSSDeck

Called with: