13
\$\begingroup\$

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.

\$\endgroup\$
14
  • 1
    \$\begingroup\$ 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? \$\endgroup\$ Commented Jun 27, 2014 at 22:39
  • 1
    \$\begingroup\$ Yes, you just start over from the beginning. \$\endgroup\$
    – BrunoJ
    Commented Jun 27, 2014 at 22:51
  • 6
    \$\begingroup\$ What counts as "compute yourself"? ArcCos(-1)? \$\endgroup\$ Commented Jun 28, 2014 at 0:04
  • 1
    \$\begingroup\$ I explained better what I wanted to say by computing it yourself and pointed that 3 is the first digit. \$\endgroup\$
    – BrunoJ
    Commented Jun 28, 2014 at 1:09
  • 1
    \$\begingroup\$ 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)? \$\endgroup\$
    – ASKASK
    Commented Jun 28, 2014 at 22:55

6 Answers 6

5
\$\begingroup\$

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)

\$\endgroup\$
3
\$\begingroup\$

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*-}%
\$\endgroup\$
1
\$\begingroup\$

JavaScript - 167 173 176

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"
\$\endgroup\$
1
  • \$\begingroup\$ What about m=1 and m<<=4 instead of m='0x1' and m+=0 ? Saves 3 bytes. \$\endgroup\$
    – Michael M.
    Commented Jun 30, 2014 at 9:19
1
\$\begingroup\$

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

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.

\$\endgroup\$
0
\$\begingroup\$

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"
\$\endgroup\$
2
  • \$\begingroup\$ Made a typo in your bonus section. d 2 "isvsn" should be d 2 "isvxn" \$\endgroup\$
    – Spedwards
    Commented Jun 30, 2014 at 8:47
  • \$\begingroup\$ Fixed. Thanks for noticing. \$\endgroup\$
    – gxtaillon
    Commented Jun 30, 2014 at 9:44
0
\$\begingroup\$

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:

alert e 'house', 2

isvxn

\$\endgroup\$
1
  • \$\begingroup\$ Did you read the whole question, as it clearly states that you are not allowed to "use any embedded constant in your code"? \$\endgroup\$
    – core1024
    Commented Jul 14, 2014 at 17:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.