6
\$\begingroup\$

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.

\$\endgroup\$
11
  • 21
    \$\begingroup\$ 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. \$\endgroup\$ Feb 4, 2014 at 20:59
  • 1
    \$\begingroup\$ Is the requirement to jump past 0 when overflowing byte deliberate? (The successor to 255 for a byte is usually 0) \$\endgroup\$
    – Sylwester
    Feb 4, 2014 at 21:24
  • 3
    \$\begingroup\$ Encryption algorithms that don't have keys don't seem rather useful. In fact this is just hardcoding one key for a substitution cipher. \$\endgroup\$
    – Cruncher
    Feb 5, 2014 at 13:49
  • 3
    \$\begingroup\$ 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. :) \$\endgroup\$ Feb 5, 2014 at 16:38
  • 1
    \$\begingroup\$ @user689 I edited the question. Let me know if you do agree with that or not. \$\endgroup\$ Feb 5, 2014 at 20:03

20 Answers 20

15
\$\begingroup\$

BrainFuck: 21

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

Assumes EOF=zero

echo -n 'My secret password is 123456!' | beef encrypt.bf
==> N{#wjiym}*{mv36HJLNPR>
\$\endgroup\$
2
  • 13
    \$\begingroup\$ Nice. And the code is encrypted too! \$\endgroup\$ Feb 5, 2014 at 14:38
  • 5
    \$\begingroup\$ "Obfuscated," not "encrypted." There is no secret key. \$\endgroup\$ Feb 5, 2014 at 20:02
7
\$\begingroup\$

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
\$\endgroup\$
13
  • 2
    \$\begingroup\$ You can make this quite a bit shorter: q;main(p){for(;p>0;q*=q<255)putchar(++q+(p=getchar()));} \$\endgroup\$
    – Josh
    Feb 4, 2014 at 20:20
  • 1
    \$\begingroup\$ Wow, I'm always amazed at what people can do with normally verbose languages! Is it okay to revise my submission using it? \$\endgroup\$
    – user15259
    Feb 4, 2014 at 20:25
  • 1
    \$\begingroup\$ @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. \$\endgroup\$
    – user15259
    Feb 4, 2014 at 21:06
  • 1
    \$\begingroup\$ 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). \$\endgroup\$
    – ugoren
    Feb 4, 2014 at 21:25
  • 1
    \$\begingroup\$ 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);} \$\endgroup\$
    – Josh
    Feb 5, 2014 at 1:59
5
\$\begingroup\$

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Ç}⌂ä|üâüâåàëäçÄÄîÉïÄæÅöòÆò
\$\endgroup\$
2
  • \$\begingroup\$ @ArlaudPierre What are you talking about? Befunge is my favorite programming language. \$\endgroup\$
    – Justin
    Feb 5, 2014 at 17:08
  • \$\begingroup\$ Is ÿ considered one or two bytes? Its value is 255 which is within one unsigned byte... \$\endgroup\$
    – Justin
    Feb 6, 2014 at 1:21
4
\$\begingroup\$

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]''+
\$\endgroup\$
7
  • \$\begingroup\$ The first one gives me an error message? undefined method 'rightparen' for nil:NilClass \$\endgroup\$
    – Gareth
    Feb 4, 2014 at 23:11
  • \$\begingroup\$ interesting - it works with this interpreter: copy.sh/golfscript/… \$\endgroup\$
    – Ben Reich
    Feb 4, 2014 at 23:14
  • \$\begingroup\$ Hmmm. This is where I get the error; different versions of Ruby or Golfscript, maybe? \$\endgroup\$
    – Gareth
    Feb 4, 2014 at 23:17
  • \$\begingroup\$ 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/… \$\endgroup\$
    – Ben Reich
    Feb 4, 2014 at 23:19
  • \$\begingroup\$ @Gareth the new 15-character solution is cooler, anyway, and works in both! :) \$\endgroup\$
    – Ben Reich
    Feb 4, 2014 at 23:37
4
\$\begingroup\$

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>
\$\endgroup\$
3
\$\begingroup\$

Python2.7 (67 chars)

import sys;print''.join([chr((ord(x)+1)%256)for x in sys.argv[1]])
\$\endgroup\$
3
\$\begingroup\$

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

\$\endgroup\$
6
  • 1
    \$\begingroup\$ 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("") \$\endgroup\$
    – A.M.K
    Feb 4, 2014 at 23:51
  • 1
    \$\begingroup\$ 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("") \$\endgroup\$
    – A.M.K
    Feb 5, 2014 at 0:22
  • \$\begingroup\$ @A.M.K: Nice.. ducktyping the string, very clever! Forgot the modulus -.- \$\endgroup\$
    – micha
    Feb 5, 2014 at 0:39
  • 1
    \$\begingroup\$ @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. \$\endgroup\$ Feb 7, 2014 at 16:00
  • 1
    \$\begingroup\$ 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("") \$\endgroup\$
    – Toothbrush
    Feb 22, 2014 at 14:34
3
\$\begingroup\$

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

\$\endgroup\$
5
  • \$\begingroup\$ 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. \$\endgroup\$
    – Toothbrush
    Feb 22, 2014 at 14:45
  • \$\begingroup\$ @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. \$\endgroup\$
    – A.M.K
    Apr 14, 2014 at 19:50
  • \$\begingroup\$ @A.M.K Does it work? Is it short? \$\endgroup\$ Apr 14, 2014 at 20:39
  • \$\begingroup\$ @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! \$\endgroup\$
    – A.M.K
    Apr 17, 2014 at 0:40
  • \$\begingroup\$ Yes, but the upvotes are based on code beauty, not functionality. Basically: they are upvoting code that MIGHT not work for an undefined time. \$\endgroup\$ Apr 17, 2014 at 17:17
2
\$\begingroup\$

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

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

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+.

\$\endgroup\$
2
\$\begingroup\$

Ruby functional, 67

puts ARGV[0].bytes.map.with_index(1){|b,i|b+i%255}.map(&:chr).join

Example:

$ ruby encrypt.rb password
=> qcvw|uyl
\$\endgroup\$
1
  • \$\begingroup\$ A new user without the comment privilege suggested shortening the code to puts ARGV[0].bytes.map.with_index(1){|b,i|(b+i&255).chr}*''. I've rejected the edit as per our policy but you might want to review it and edit it in yourself and credit them. \$\endgroup\$ Sep 3, 2016 at 8:48
1
\$\begingroup\$

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"
\$\endgroup\$
3
  • \$\begingroup\$ Note that 0 is not allowed as an encryptor, so in your example you shouldn't see a outputted. \$\endgroup\$
    – user15259
    Feb 4, 2014 at 20:16
  • \$\begingroup\$ Or maybe it is, once I reread the specs, it might be asking for a non-reversible encryption. \$\endgroup\$
    – user15259
    Feb 4, 2014 at 21:09
  • \$\begingroup\$ No I think you are right. I updated it, which adds a few letters. \$\endgroup\$
    – gggg
    Feb 4, 2014 at 21:57
1
\$\begingroup\$

GolfScript, 27 characters

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

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

\$\endgroup\$
1
\$\begingroup\$

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"
\$\endgroup\$
1
\$\begingroup\$

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"

\$\endgroup\$
1
\$\begingroup\$

Rebol, 58 chars

s: input forall s[s/1: mod(index? s)+(to-integer s/1)256]s
\$\endgroup\$
1
\$\begingroup\$

Groovy, 53 Characters

i=0;args[0].chars.collect{(char)it+(++i%255)}.join()
\$\endgroup\$
1
\$\begingroup\$

Ruby, 45 39 bytes

gets.chars{|c|putc(c.ord+$.)%256;$.+=1}
\$\endgroup\$
0
\$\begingroup\$

Perl, 54 char

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

Example:

perl encrypt.pl password
> qcvw|uyl
\$\endgroup\$
0
\$\begingroup\$

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>
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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