Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Using a language of your choice write a program that takes a string as an input, and returns the string encrypted.

Algorithm:

You should assume that each character is always encoded in a byte and is ASCII-based. The extended ASCII codes are mapped to whatever is the default code page in use by the system.

You should encrypt the code in the following way: code of first character +1, code of second character +2, code of third character +3 .....

Extended ASCII codes are based on this table: http://www.asciitable.com/

Shortest code wins.

share|improve this question
20  
If you're above 128 it's not ASCII. I have no idea what you're trying to say with your example of wrapping: please rewrite it to make it clear which values come from the plaintext and which come from the key stream. –  Peter Taylor Feb 4 at 20:59
1  
Is the requirement to jump past 0 when overflowing byte deliberate? (The successor to 255 for a byte is usually 0) –  Sylwester Feb 4 at 21:24
2  
Encryption algorithms that don't have keys don't seem rather useful. In fact this is just hardcoding one key for a substitution cipher. –  Cruncher Feb 5 at 13:49
1  
If you're above 255, it isn't even the OEM character set. Please read joelonsoftware.com/articles/Unicode.html when you get a chance. I re-read it every few years. :) –  Charles Burns Feb 5 at 16:38
1  
@user689 I edited the question. Let me know if you do agree with that or not. –  Victor Feb 5 at 20:03
show 4 more comments

19 Answers

up vote 4 down vote accepted

GolfScript 20 19 15 12

{0)255%:0+}%

This assigns a variable to the character 0, which allows us to not define it on the first iteration of the mapping. I love that you can do that in GolfScript! Each iteration of the mapping increments the 0 variable, and adds it to subsequent characters of the string (which is treated like an array).

This alternate 20-character GolfScript solution using zip encounters an interesting issue:

.,,]zip{~)255%+}%''+

Try it here. This standard online interpreter, however, treats zip differently for an array containing a string and an array. See this vs this. I'm not sure if an alternate version of Ruby or GolfScript is being used, or which one is considered canonical, but the second interpreter can be resolved with 2 characters:

.,,[\]zip{~)255%+}%''+

I also like a different solution for 23 characters:

1\{(@.@255%+\)@.}do]''+
share|improve this answer
    
The first one gives me an error message? undefined method 'rightparen' for nil:NilClass –  Gareth Feb 4 at 23:11
    
interesting - it works with this interpreter: copy.sh/golfscript/… –  Ben Reich Feb 4 at 23:14
    
Hmmm. This is where I get the error; different versions of Ruby or Golfscript, maybe? –  Gareth Feb 4 at 23:17
    
The more standard online interpreter (golfscript.apphb.com) treats zip differently with an array containing a string and an array. See copy.sh/golfscript/… vs golfscript.apphb.com/… –  Ben Reich Feb 4 at 23:19
    
@Gareth the new 15-character solution is cooler, anyway, and works in both! :) –  Ben Reich Feb 4 at 23:37
show 2 more comments

BrainFuck: 21

>,[+<[->+>+<<]>.>+>,]

Assumes EOF=zero

echo -n 'My secret password is 123456!' | beef encrypt.bf
==> N{#wjiym}*{mv36HJLNPR>
share|improve this answer
11  
Nice. And the code is encrypted too! –  Arlaud Pierre Feb 5 at 14:38
3  
"Obfuscated," not "encrypted." There is no secret key. –  BlueRaja - Danny Pflughoeft Feb 5 at 20:02
add comment

C — 67 56 49 characters

During compilation it might warn that q is missing a type...

q;main(p){for(;p=~getchar();)putchar(q++%255-p);}

Thanks to Josh for the significantly shorter rewrites!

$ echo 'My secret password is 123456!' | ./_encrypt
N{#wjiym}*{m����v3}�6HJLNPR>(

Confirm it handles the rollover from 255 to 1 correctly by encrypting 343 xs and checking for no xs in the output:

$ echo xxxxxxx | sed -e 's/x/xxxxxxx/g' -e 's/x/xxxxxxx/g' | ./_encrypt | grep -o x | wc -l
0
share|improve this answer
2  
You can make this quite a bit shorter: q;main(p){for(;p>0;q*=q<255)putchar(++q+(p=getchar()));} –  Josh Feb 4 at 20:20
1  
Wow, I'm always amazed at what people can do with normally verbose languages! Is it okay to revise my submission using it? –  Yimin Rong Feb 4 at 20:25
1  
@Gareth - I don't think that's what he means. If you encrypt and it gives 0, then "correct" it to 1, then accurate decryption isn't guaranteed. –  Yimin Rong Feb 4 at 21:06
1  
You can test for EOF by ~p. And I think you can also make the condition p=~getchar() and then use ++q+~p (saving parentheses). –  ugoren Feb 4 at 21:25
1  
Using @ugoren's recommendations I can get it down to 49 characters, passing both test cases: q;main(p){for(;p=~getchar();)putchar(q++%255-p);} –  Josh Feb 5 at 1:59
show 8 more comments

Befunge 98 - 15 bytes

:~+'U3*%1+,1+#@

Keeps a counter (starting at 0) and adds that to the ~ input. Then, computes 255 (as 85 * 3 in the form of 'U3*), then mods (%). Then, it adds 1 and prints it, then adds one to the counter, then uses # to skip over the @. At the end of the input, the IP goes the other way and hits the @, ending the program.

Alternatively, if your interpreter supports unicode, this 14 byte (13 char) solution works:

:~+'ÿ%1+,1+#@

Sample run (in command prompt, so some of the unicode characters are actually some ascii value):

This string will be encrypted using the predetermined method!2.7182818284590452353602874713526624

Output:

Ujlw%y{zrxr,äw{|1tx4zäzèÆèÅüü>öôèÉèDÖÄîHÖ£ÉÉÆóöó₧¢íÖÖVñ¥¡ó¬á^pmwrzu|v~yÇ}⌂ä|üâüâåàëäçÄÄîÉïÄæÅöòÆò
share|improve this answer
    
+1 for bothering using Befunge. –  Arlaud Pierre Feb 5 at 14:39
    
@ArlaudPierre What are you talking about? Befunge is my favorite programming language. –  Quincunx Feb 5 at 17:08
    
Is ÿ considered one or two bytes? Its value is 255 which is within one unsigned byte... –  Quincunx Feb 6 at 1:21
add comment

J, 21 characters

a.{~1+256|(+i.@#)a.i.

Usage (borrowing Yimin's test text):

   a.{~1+256|(+i.@#)a.i.'My secret password is 123456!'
N{#wjiym}*{m????v3}?6HJLNPR>
share|improve this answer
add comment

Python2.7 (67 chars)

import sys;print''.join([chr((ord(x)+1)%256)for x in sys.argv[1]])
share|improve this answer
add comment

JavaScript, 90c

t.split("").map(function(c,a){return String.fromCharCode(c.charCodeAt(0)+a+1)}).join("")
[].map.call(t,function(c,a){return String.fromCharCode(c.charCodeAt(0)+a%255+1)}).join("")

Fiddledee

share|improve this answer
1  
Your code doesn't wrap after 255 chars, it needs to be this: .split("").map(function(c,a){return String.fromCharCode(c.charCodeAt(0)+a%255+1)}).join("") –  A.M.K Feb 4 at 23:51
1  
You can also do this and save 1 character: [].map.call(t,function(c,a){return String.fromCharCode(c.charCodeAt(0)+a%255+1)}).join("") –  A.M.K Feb 5 at 0:22
    
@A.M.K: Nice.. ducktyping the string, very clever! Forgot the modulus -.- –  micha Feb 5 at 0:39
1  
@micha I will try to understand what you write later. But I can see that you can drop that 0 in .charCodeAt(0) and save one char. –  Gaurang Tandon Feb 7 at 16:00
1  
You don't need the 0 in c.charCodeAt and in EcmaScript 6 (supported in Firefox & Google Chrome), you can make it even shorter: [].map.call(t,(c,a)=>String.fromCharCode(c.charCodeAt()+a%255+1)}).join("") –  toothbrush Feb 22 at 14:34
show 1 more comment

Javascript/JScript: 72 to 105 chars

Here is a Javascript/JScript attempt at making a version of this code.

I'm aware that there is another Javascript code, but that one relies on recent Javascript implementations.

That is a bad thing!!!

That code is invalid in ie8< without polyfills.

Here is my version:

function $(c){for(var i=0,l=c.length,o='';i<l;o+=String.fromCharCode(c.charCodeAt(i++)+i&255));return o;}
//function call, 105 chars, absolutely valid!

function $(c){for(i=0,l=c.length,o='';i<l;o+=String.fromCharCode(c.charCodeAt(i++)+i&255));return o;}
//function call, no var keyword, 101 chars, completely valid!

function $(c){for(i=0,l=c.length,o='';i<l;o+=String.fromCharCode(c.charCodeAt(i++)+i));return o;}
//function call, 97 chars, most likely invalid!

c='';//here goes input, output is in var `o`, dont count this line
for(i=0,l=c.length,o='';i<l;o+=String.fromCharCode(c.charCodeAt(i++)+i&255));
//no function call, input goes to var c, 77 chars of pure working code! valid for sure!

c='';//here goes input, output is in var `o`, dont count this line
for(i=0,l=c.length,o='';i<l;o+=String.fromCharCode(c.charCodeAt(i++)+i));
//no function call, input goes to var c, no char wrapping after 255, 73 chars of probably invalid code

@toothbrush gave me this answer:

i=0;while(i<c.length)c[i]=String.fromCharCode(c.charCodeAt(i++)+i%255+1)

It changes the original string and is only 72 bytes!

I don't know why he has %255+1 in the end when &255 does the same job, is faster and shorter.

But I will keep the original answer intact.


Consider this and test it with a Javascript/JScript interpreter.

I know that the 73 char version and the 97 char function call version will be invalid, but its still here!

If you will be using the code in a production environment (website), use the 105 chars long and consider changing the function name to something else (or you might have problems with jQuery and MooTools).

share|improve this answer
    
The 73 character version can be even shorter: i=0;while(i<c.length)c[i]=String.fromCharCode(c.charCodeAt(i++)+i). To properly handle the wrapping of the numbers: i=0;while(i<c.length)c[i]=String.fromCharCode(c.charCodeAt(i++)+i%255+1) - this version is still shorter than the current version! Both modify the original string. –  toothbrush Feb 22 at 14:45
    
@Ismael Miguel, No offense, but this is a code golf website; the code isn't intended to ever be used. Therefore browser compatibility isn't a consideration. –  A.M.K Apr 14 at 19:50
    
@A.M.K Does it work? Is it short? –  Ismael Miguel Apr 14 at 20:39
    
@IsmaelMiguel, Yes, but you said I'm aware that there is another Javascript code, but that one relies on recent Javascript implementations. That is a bad thing!!!. All I'm saying is that since this is a code golf question, that isn't a bad thing. I've even seen answers that use features that haven't been implemented yet! –  A.M.K yesterday
    
Yes, but the upvotes are based on code beauty, not functionality. Basically: they are upvoting code that MIGHT not work for an undefined time. –  Ismael Miguel yesterday
add comment

Julia 51 (-4 if in place is allowed)

g(s)=([s.data[i]+=(i-1)%255+1 for i=1:length(s)];s)
g(s)=[s.data[i]+=(i-1)%255+1 for i=1:length(s)] # in place version
julia> g("a"^256) # ^ operator repeats strings
"bcdefghijklmnopqrstuvwxyz{|}~\x7f��������������������������������������������������������������������������������������������������������������������������������\0\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\e\x1c\x1d\x1e\x1f !\"#\$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`b"
share|improve this answer
    
Note that 0 is not allowed as an encryptor, so in your example you shouldn't see a outputted. –  Yimin Rong Feb 4 at 20:16
    
Or maybe it is, once I reread the specs, it might be asking for a non-reversible encryption. –  Yimin Rong Feb 4 at 21:09
    
No I think you are right. I updated it, which adds a few letters. –  gggg Feb 4 at 21:57
add comment

Python3 (99 chars)

e=''
i=0
for c in __import__("sys").argv[1]:
        i=(i+1)%255
        e+=chr(ord(c)+i)
print(e)

Example

python encrypt.py password outputs qcvw|uyl

share|improve this answer
1  
The output for password should be qcvw|uyl. –  Gareth Feb 4 at 23:13
    
Yeah, i fixed that, was a little bit to hectic :) –  klingt.net Feb 4 at 23:15
3  
You can remove the from sys... part by doing for c in __import__("sys").argv[1]. –  SimonT Feb 5 at 3:14
add comment

CoffeeScript, 73 64 chars

t.replace /./g,(c,a)->String.fromCharCode c.charCodeAt()+a%255+1

[].map.call(t,(c,a)->String.fromCharCode c.charCodeAt(0)+a%255+1).join ""

Example: "Test string".replace /./g,(c,a)->String.fromCharCode c.charCodeAt()+a%255+1 outputs Ugvx%y{zrxr

Coffee to Javascript converter (paste in right box): http://js2coffee.org/

As per Ismael Miguel's comments, this method should work in IE 5.5+.

share|improve this answer
add comment

GolfScript, 27 characters

[.,,\]zip[{{+}*255%1+}/]''+

Hmmm...seems a bit long. Maybe I should stick to J.

share|improve this answer
add comment

Haskell, 77C 59C

import Data.Char
e s=h s 1
h""_=""
h(x:s)i=(chr(mod((ord x)+i)128)):h s(i+1)

v2

import Data.Char
e s = map chr(zipWith(+)(map ord s)[1..])

I am assuming that input doesn't need to be on STDIN.

Example run:

*Main> e "hello"
"igopt"
share|improve this answer
add comment

Ruby 45

i=0
gets.chars{|c|$><<((c.ord+i+=1)%255).chr}
share|improve this answer
add comment

Erlang: 60C

Not the smallest or prettiest, but this one can be run standalone in the command line. Set T to your text.

{S,_}=lists:mapfoldl(fun(C,I)->{C+I,(I+1)rem 255}end,1,T),S.

Yields: "qcvw|uyl"

share|improve this answer
add comment

Rebol, 58 chars

s: input forall s[s/1: mod(index? s)+(to-integer s/1)256]s
share|improve this answer
add comment

Groovy, 53 Characters

i=0;args[0].chars.collect{(char)it+(++i%255)}.join()
share|improve this answer
add comment

Perl, 54 char

$i=1;print map{chr((ord()+$i++)%256)}split//,$ARGV[0];

Example:

perl encrypt.pl password
> qcvw|uyl
share|improve this answer
add comment

Dart, 68

f(s,{i=1})=>new String.fromCharCodes(s.runes.map((c)=>(c+i++)%255));

Example:

f('My secret password is 123456!');
> N{#wjiym}*{mv3}6HJLNPR>
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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