Obfuscating text by cycling ternary digits

28

0

The goal of this challenge is the write the shortest function/program to take input text, encrypt it using the method below, and return the result.

As an example, I will use the string hello world.

First, get the input text.

hello world

Second, convert the string into ternary (base 3). Use this key:

a = 000
b = 001
c = 002
d = 010
e = 011
f = 012
g = 020

...

w = 211
x = 212
y = 220
z = 221
[space] = 222

With this key, hello world becomes 021011102102112222211112122102010, as seen below.

 h   e   l   l   o       w   o   r   l   d
021 011 102 102 112 222 211 112 122 102 010

Third, move the first digit to the end.

021011102102112222211112122102010
becomes
210111021021122222111121221020100

Fourth, convert the number back into a string using the same key.

210 111 021 021 122 222 111 121 221 020 100
 v   n   h   h   r       n   q   z   g   j

Lastly, return the encrypted text.

vnhhr nqzgj

Here are some sample text and their output:

the turtle ==> dvo fh ego

python ==> uudwqn

code golf ==> hpjoytqgp

As this is code golf, the shortest entry in bytes wins. Errors are allowed if some of the characters are not lowercase letters or space. This is my first challenge, so any suggestions would be more than helpful.

Good luck!

Leaderboard:

var QUESTION_ID=54643;function answersUrl(e){return"http://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),e.has_more?getAnswers():process()}})}function shouldHaveHeading(e){var a=!1,r=e.body_markdown.split("\n");try{a|=/^#/.test(e.body_markdown),a|=["-","="].indexOf(r[1][0])>-1,a&=LANGUAGE_REG.test(e.body_markdown)}catch(n){}return a}function shouldHaveScore(e){var a=!1;try{a|=SIZE_REG.test(e.body_markdown.split("\n")[0])}catch(r){}return a}function getAuthorName(e){return e.owner.display_name}function process(){answers=answers.filter(shouldHaveScore).filter(shouldHaveHeading),answers.sort(function(e,a){var r=+(e.body_markdown.split("\n")[0].match(SIZE_REG)||[1/0])[0],n=+(a.body_markdown.split("\n")[0].match(SIZE_REG)||[1/0])[0];return r-n});var e={},a=1,r=null,n=1;answers.forEach(function(s){var t=s.body_markdown.split("\n")[0],o=jQuery("#answer-template").html(),l=(t.match(NUMBER_REG)[0],(t.match(SIZE_REG)||[0])[0]),c=t.match(LANGUAGE_REG)[1],i=getAuthorName(s);l!=r&&(n=a),r=l,++a,o=o.replace("{{PLACE}}",n+".").replace("{{NAME}}",i).replace("{{LANGUAGE}}",c).replace("{{SIZE}}",l).replace("{{LINK}}",s.share_link),o=jQuery(o),jQuery("#answers").append(o),e[c]=e[c]||{lang:c,user:i,size:l,link:s.share_link}});var s=[];for(var t in e)e.hasOwnProperty(t)&&s.push(e[t]);s.sort(function(e,a){return e.lang>a.lang?1:e.lang<a.lang?-1:0});for(var o=0;o<s.length;++o){var l=jQuery("#language-template").html(),t=s[o];l=l.replace("{{LANGUAGE}}",t.lang).replace("{{NAME}}",t.user).replace("{{SIZE}}",t.size).replace("{{LINK}}",t.link),l=jQuery(l),jQuery("#languages").append(l)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",answers=[],page=1;getAnswers();var SIZE_REG=/\d+(?=[^\d&]*(?:&lt;(?:s&gt;[^&]*&lt;\/s&gt;|[^&]+&gt;)[^\d&]*)*$)/,NUMBER_REG=/\d+/,LANGUAGE_REG=/^#*\s*([^,]+)/;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"><div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table></div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table></div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody></table><table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody></table>

The Turtle

Posted 2015-08-13T16:52:40.320

Reputation: 858

3Note that this technically is obfuscation, not encryption. There is no encryption key here. – John Dvorak – 2015-08-14T08:43:44.800

@JanDvorak Will "cipher" work? – The Turtle – 2015-08-14T13:55:00.300

To build on @JanDvorak's comment, I would describe this as an "encoding," which is a standard way of expressing data in a different format (e.g., you can express a bit string with hexadecimal encoding, or base64 encoding). – apsillers – 2015-08-14T19:26:47.297

@apsillers Except now you're re-encoding into the same alphabet as the source. For no reason other than obfuscation^K code golf challenge :-D – John Dvorak – 2015-08-14T19:51:30.720

1

@JanDvorak Agreed -- I'd be more likely to call ROT13 "obfuscation" rather than "encoding" (even though it satisfies both definitions). Probably the most precise title would be "Obfuscate text by..."

– apsillers – 2015-08-14T19:54:59.373

@apsillers Okay, thanks! Changed. – The Turtle – 2015-08-14T20:55:10.100

Can we assume some limit as to the string length? Or perhaps you cauld define some penalty (add some number to the byte count) for code that only works for short strings. I have a method in mind for strings up to 10 or 11 characters; maybe others can come up with efficient approaches for short strings too – Luis Mendo – 2015-08-14T22:32:41.233

@LuisMendo I guess the limit is about how much the programming language can handle. (I know that is kind of vague, but I don't think a programming language would have a 11-character limit) I would like to see the program though! (maybe here on the comments?) – The Turtle – 2015-08-14T23:16:46.960

2@TheTurtle The idea was to pack the characters into a large integer (uint64) using increasing powers of 27. The displacement by one digit would then be equivalent to multiplying this large integer by 3, and the introduction of the first digit on the other end would simply be an addition. But there are complications, such as discarding the last "carry" (perhaps via a mod operation), and I couldn't get it to work with few bytes – Luis Mendo – 2015-08-14T23:29:50.160

Answers

16

Pyth, 23 22 bytes

sXc.<sXz=+GdJ^UK3K1KJG

Try it online: Regular Input / Test Suite

Thanks to @isaacg for one byte.

Explanation:

sXc.<sXz=+GdJ^UK3K1KJG
        =+Gd             append a space the G (preinitialized with the alphabet)
               K3        assign 3 to K
            J^UK K       assign all 3-digit ternary numbers 
                         [[0,0,0], [0,0,1],...,[2,2,2]] to J
      Xz  G J            translate input from G to J
     s                   sum (join all ternary numbers to one big list)
   .<             1      rotate by 1
  c                K     split into lists of size 3
 X                  JG   translate from J to G
s                        join chars to string and print

Jakube

Posted 2015-08-13T16:52:40.320

Reputation: 21 462

1We had the same idea. I wrote a Pyth port of my CJam, then scrolled down and saw your answer :/ – Andrea Biondo – 2015-08-14T08:22:23.797

1You can save a byte by doing an augmented assignment to G instead of using N, e.g. =+Gd. – isaacg – 2015-08-14T08:43:43.213

@isaacg thanks. – Jakube – 2015-08-14T08:47:13.673

14

Pyth, 26 bytes

J+Gds@LJiR3c.<s.DR9xLJz1 2

Try it online in the Pyth Compiler/Executor: demo | test cases

Idea

Assume all input characters have already been mapped to the integers that step 2 specifies.

For every 3-digit ternary number, we have that xyz3 = 9x + 3y + z, so modular division by 9 yields quotient x and residue 3y + z.

If the input is abc3 def3 ghi3, applying modular division to each yields a, 3b + c, d, 3e + f, g, 3h + i.

After rotating the list from above one unit to the left, we can group the integers into pairs. This yields the list (3b + c, d), (3e + f, g), (3h + i, a).

Now, if we convert (3y + z, w) from base 3 to integer, we obtain 3(3y + z) + w = 9y + 3z + w = zyw3.

Thus, applying base conversion to the list of pairs gives us bcd3 efg3 hia3, which is precisely the result of rotating the concatenated ternary digits one unit to the left.

All that's left to do is mapping the resulting integers back to characters.

Code

J+Gd                        Concatenate "a...z" (G) with " " (d) and save in J.
                    L z     For each character in the input(z):
                   x J        Compute its index in J.
                 R          For each index I:
               .D 9           Compute (I / 9, I % 9).
              s             Concatenate the resulting pairs.
            .<         1    Rotate the resulting list one unit to the left.
           c             2  Split it back into pairs.
         R                  For each pair:
        i 3                   Perform conversion from base 3 to integer.
      L                     For each resulting integer:
     @ J                      Select the element of J at that index.
    s                       Concatenate the resulting characters.

Dennis

Posted 2015-08-13T16:52:40.320

Reputation: 196 637

Yeesh, in a few hours I got beaten by CJam and Pyth. :/ – kirbyfan64sos – 2015-08-13T21:05:57.410

Wow! Can you write an explanation of how it works? I'm curious. :) – The Turtle – 2015-08-13T23:13:34.163

@TheTurtle I've edited my answer. – Dennis – 2015-08-14T03:07:38.023

10

Python 2, 96

s=input()
r=y=''
for c in s+s[0]:x=(ord(c)-97)%91;r+=y and chr((y%9*3+x/9-26)%91+32);y=x
print r

Converts a character c to a value x as x=(ord(c)-97)%91, with the modulo affecting only space to convert it to 26. The reverse conversion is i to chr((i-26)%91+32), with the modulo only affecting i=26 to make it become spaces.

We loop through the characters, noting the current value x and the previous value y. We use the last two ternary digits of y, found as y%9, and the first ternary digit of x, found as x/9. The value of the concatenation is y%9*3+x/9. There's probably some optimizations combining this arithmetic with the shifting by 97 and fixing of space.

We make this loop around, we return to the first character of the string at the end. We also do one preparation loop to write in a previous value y, suppressing the character for the first loop when y has not yet been initialized.

xnor

Posted 2015-08-13T16:52:40.320

Reputation: 115 687

8

CJam, 39 29 bytes

The cool thing about this one is that it doesn't even use base conversion.

q'{,97>S+:XZZm*:Yere_(+3/YXer

Try it online.

I just realized I had exactly the same idea as Jakube's Pyth answer. I actually ported this CJam code to Pyth before seeing his post, ending up with 25 bytes. Given it was my first Pyth golf I guess it's not too bad.

Explanation

                              e# Z = 3
q                             e# Push input string
 '{,                          e# Push ['\0' ... 'z']
    97>                       e# Keep ['a' ... 'z']
       S+                     e# Append space
         :X                   e# Assign "a...z " to X
           ZZm*               e# Push 3rd cartesian power of [0 1 2]
                              e# i.e. all 3-digit permutations of 0, 1, 2
                              e# (in lexicographical order)
               :Y             e# Assign those permutations to Y
                 er           e# Translate input from X to Y
                   e_         e# Flatten resulting 2D array
                     (+       e# Rotate first element to the end
                       3/     e# Split back into 3-digit elements
                         YXer e# Translate from Y to X

Andrea Biondo

Posted 2015-08-13T16:52:40.320

Reputation: 1 452

7

CJam, 30 29 27 bytes

q'{,97>S+:Af#9fmd(+2/3fbAf=

Try it online in the CJam interpreter.

The approach is the same as in my other answer, which is a port of this code to Pyth.

How it works

q                           e# Read from STDIN.
 '{,                        e# Push ['\0' ... 'z'].
    97>                     e# Remove the first 97 elements (['\0' - '`']).
       S+:A                 e# Append a space and save in A.
           f#               e# Find the index of each input character in A.
             9fmd           e# Apply modular division by 9 to each index.
                 (+         e# Shift out the first quotient and append it.
                   2/       e# Split into pairs.
                     3fb    e# Convert each pair from base 3 to integer.
                        Af= e# Select the corresponding elements from A.

Dennis

Posted 2015-08-13T16:52:40.320

Reputation: 196 637

6

Javascript (ES6), 175 bytes

A one-liner!

"Overuse of variable v award, anyone?"

update: Now only uses variables called v, for total confusion!

Thanks @vihan for saving 6 bytes!

Thanks @Neil for saving 27 bytes!!

v=>(([...v].map(v=>(v<"V"?53:v.charCodeAt()-70).toString(3).slice(1)).join``)+v[0]).slice(1).match(/..?.?/g).map(v=>(v=String.fromCharCode(parseInt(v,3)+97))>"z"?" ":v).join``

Defines an anonymous function. To use, add v= before the code to give the function a name, and call it like alert(v("hello world"))

jrich

Posted 2015-08-13T16:52:40.320

Reputation: 3 898

You can use .slice(-3) to save 6 bytes, at which point you can use "00"+v to save another byte. (You could concatenate with a template but the resulting length is the same.) – Neil – 2015-08-14T20:20:49.050

Actually, you can save a whole bunch of bytes by adding 27 to your values before converting them to base three, as that guarantees enough digits. .map(v=>(v<"V"?26:v.charCodeAt()-97).toString(3)).map(v=>("000"+v).slice(v.length)) then becomes .map(v=>(v<"V"?53:v.charCodeAt()-70).toString(3).slice(1)). – Neil – 2015-08-14T20:22:31.547

@Neil Wow, that really shortened the code! It also made it a true 'one-liner', by removing the only intermediate variable. Thanks! – jrich – 2015-08-14T22:51:45.490

6

Pyth, 30 29 bytes

K+Gdsm@Kid3c.<sm.[Z3jxKd3z1 3

Saved 1 byte thanks to @Jakube.

Live demo and test cases.

kirbyfan64sos

Posted 2015-08-13T16:52:40.320

Reputation: 8 730

5

Julia, 149 137 bytes

My first golf!

s->(j=join;b=j([base(3,i==' '?26:i-'a',3)for i=s]);r=b[2:end]*b[1:1];j([i==26?" ":i+'a'for i=[parseint(r[i:i+2],3)for i=1:3:length(r)]]))

(partially) ungolfed:

f = s -> (
    # join the ternary represenations:
    b = join([base(3, i == ' ' ? 26 : i - 'a',3) for i = s]);
    # rotate:
    r = b[2:end] * b[1:1];
    # calculate the new numbers:
    n = [parseint(r[i:i+2],3) for i = 1:3:length(r)];
    # convert back to characters:
    join([i == 26 ? " " : 'a' + i for i = n])
)
assert(f("hello world") == "vnhhr nqzgj")
assert(f("the turtle")  == "dvo fh ego")
assert(f("python")      == "uudwqn")
assert(f("code golf")   == "hpjoytqgp")

kevinsa5

Posted 2015-08-13T16:52:40.320

Reputation: 181

You can use = rather than in for loops and you can use b[1] in place of b[1:1]. You also don't need a space between closing parens and for. – Alex A. – 2015-08-13T18:52:17.570

@AlexA. Cheers for =, but b[1] returns a character, which can't be appended to a string with *. – kevinsa5 – 2015-08-13T18:53:35.567

Oh right, forgot about that. – Alex A. – 2015-08-13T18:54:46.437

@AlexA. The for trick is nifty. You can also have it directly after a close quote. I didn't realize the parser was that flexible. – kevinsa5 – 2015-08-13T19:01:04.990

It can also directly follow a numeric literal, as can end. – Alex A. – 2015-08-13T19:02:15.850

You can compare characters to their integer equivalents, and you know the character with the lowest value will be ' ', so rather than ==' ', use <33 to save two characters. You can drop the asterisk between b[2:end] and b[1:1]. 26 is the largest value for i in the final operation, so use i>25 rather than i==26. – Glen O – 2015-08-15T13:32:05.473

@GlenO The <33 trick I saw in another answer, but didn't want to cheat and use it here. Thank you for the tips! – kevinsa5 – 2015-08-15T17:37:53.733

It's not cheating to learn methods of golfing from other answers, as long as it's regular golfing. My only rule with it is that I won't steal someone else's approach. Hence why I gave you some tips based on what improvements I could see quickly on yours, and then thought up my own approach to contribute. – Glen O – 2015-08-15T18:01:30.673

Oh, also, here's a nice way to improve on b[2:end]b[1:1] - it turns out you can do this: b[[2:end,1]], to save two more bytes. – Glen O – 2015-08-15T18:16:15.183

@GlenO Interesting! How did you find that syntax? My google-fu isn't working with "double square brace julia" variations. – kevinsa5 – 2015-08-16T02:06:12.913

It's not "double square brace". The outer square brace is the array referencing, the inner square brace is an actual array. [2:end,1] produces the array A=[2,3,4,5,...end-1,end,1], then b[A] is getting the letters at those indices. The end is automatically converted into length(b), as far as I can tell. – Glen O – 2015-08-16T03:59:10.860

4

Javascript (ES6), 178, 172, 170

p=>{p=p.replace(' ','{');c="";l=p.length;for(i=0;i<l;){c+=String.fromCharCode(((p.charCodeAt(i)-97)%9)*3+(((p.charCodeAt((++i)%l)-97)/9)|0)+97)}return c.replace('{',' ')}

Replaced Math.floor with a bitwise or. Created an anonymous function. If I'm understanding correctly, this should fix my noobishness somewhat (thanks Dennis!) and get me another 2 bytes down.

Tekgno

Posted 2015-08-13T16:52:40.320

Reputation: 91

3

Julia, 169 166 bytes

s->(J=join;t=J(circshift(split(J([lpad(i<'a'?"222":base(3,int(i)-97),3,0)for i=s]),""),-1));J([c[j:j+2]=="222"?' ':char(parseint(c[j:j+2],3)+97)for j=1:3:length(t)]))

Ungolfed + explanation:

function f(s::String)
    # Convert the input into a string in base 3, with space mapping to 222
    b = join([lpad(i < 'a' ? "222" : base(3, int(i) - 97), 3, 0) for i = s])

    # Split that into a vector of single digits and shift once
    p = circshift(split(b, ""), -1)

    # Join the shifted array back into a string
    t = join(p)

    # Convert groups of 3 back into characters
    c = [t[j:j+2] == "222" ? ' ' : char(parseint(t[j:j+2], 3) + 97) for j = 1:3:length(t)]

    # Return the joined string
    join(c)
end

Alex A.

Posted 2015-08-13T16:52:40.320

Reputation: 23 761

3

Haskell, 160 bytes

a!k|Just v<-lookup k a=v
x=['a'..'z']++" "
y="012";z=mapM id[y,y,y]
m(a:u:r:i:s)=[u,r,i]:m(a:s)
m[e,a,t]=[[a,t,e]]
main=interact$map(zip z x!).m.(>>=(zip x z!))

Ugh, this feels way too lengthy, but at least I'm... beating Python somehow. And Ruby.

Lynn

Posted 2015-08-13T16:52:40.320

Reputation: 55 648

3

Javascript (ES6), 141 124 120 bytes

Believe it or not.... :-)

(t,i=0,c=w=>(t.charCodeAt(w)-123)%91+26)=>String.fromCharCode(...[...t].map(k=>(c(i)%9*3+c(++i%t.length)/9+65|0)%91+32))

As with my other answer, this is an anonymous function, and needs to be assigned to a variable before it can be used. Try it here:

e=(t,i=0,c=w=>(t.charCodeAt(w)-123)%91+26)=>String.fromCharCode(...[...t].map(k=>(c(i)%9*3+c(++i%t.length)/9+65|0)%91+32));

input=document.getElementById("input");
p=document.getElementById("a");
input.addEventListener("keydown", function(){
  setTimeout(function(){p.innerHTML = e(input.value);},10);
})
<form>Type your text here: <input type="text" id="input" value="hello world"/><br>
Only space and lowercase letters are allowed.</form>

<h3>Output:</h3>
<p id="a">vnhhr nqzgj</p>

I thought I might be able to shave a couple bytes off my previous answer by using a different technique, so I started out with one similar to Tekgno's and golfed my head off from there. I initialized some variables in the function's argument section, and again stuffed everything into a .map function. Then I realized the String.fromCharCode would be much more efficient outside the .map. After all was said and done, I had shaved off more than 30 45 bytes!

Edit 1: Saved 17 bytes by getting rid of the .replaces, using a technique similar to xnor's Python solution.

OK, maybe it's time to move onto another challenge....

ETHproductions

Posted 2015-08-13T16:52:40.320

Reputation: 47 880

2

Python 2, 182 180 Bytes

This solution is not ideal, due to the replace being very costly.. Trying to figure out how to avoid that.

b=lambda k:k and b(k/3)*10+k%3
s=''.join('%03d'%b(ord(x)-6-91*(x>' '))for x in input())
print`[chr(int((s[1:]+s[0])[i:i+3],3)+97)for i in range(0,len(s),3)]`[2::5].replace('{',' ')

Input is like "hello world".

Kade

Posted 2015-08-13T16:52:40.320

Reputation: 7 463

You need to count 2 bytes for required quotation marks in the input, right? – mbomb007 – 2015-08-13T19:51:04.850

@mbomb007 That's what I had thought previously, but multiple people have told me I don't need to account for that. – Kade – 2015-08-13T20:10:27.720

2

Javascript (ES6), 179 bytes

s=>[...s+s[0]].map(q=>`00${(q<'a'?26:q.charCodeAt(0)-97).toString(3)}`.slice(-3)).join``.slice(1,-2).match(/..?.?/g).map(q=>q>221?' ':String.fromCharCode(parseInt(q,3)+97)).join``

Props to vihan for the .match regex.

Dendrobium

Posted 2015-08-13T16:52:40.320

Reputation: 2 412

2

Mathematica, 162 bytes

r=Append[#->IntegerDigits[LetterNumber@#-1,3]~PadLeft~3&/@Alphabet[]," "->{2,2,2}];StringJoin[Partition[RotateLeft[Characters@#/.r//Flatten,1],3]/.(#2->#1&@@@r)]&

(Re)Using a Rule to convert the digit lists to characters and back.

murphy

Posted 2015-08-13T16:52:40.320

Reputation: 635

1

Ruby, 177

Needs at least Ruby 1.9 for the each_char method

l=[*('a'..'z'),' '];n=(0..26).map{|m|m=m.to_s(3).rjust 3,'0'};s='';gets.chomp.each_char{|x|s+=n[l.index x]};puts("#{s[1..-1]}#{s[0]}".scan(/.../).map{|i|i=l[n.index i]}.join '')

David Bailey

Posted 2015-08-13T16:52:40.320

Reputation: 141

1

Java, 458 449 bytes

It made me a little sad to determine that I could shave off 10 bytes by not using Java 8 streams and the map() method.

Here is the golfed version:

import org.apache.commons.lang.ArrayUtils;class A{public static void main(String[]a){int b=0;String[] c=new String[27];for(;b<27;++b)c[b]=String.format("%03d",Integer.valueOf(Integer.toString(b,3)));String d=a[0],e="abcdefghijklmnopqrstuvwxyz ",f="",g="";for(b=0;b<d.length();++b)f+=c[e.indexOf(d.substring(b,b+1))];f=f.substring(1)+f.charAt(0);for(b=0;b<f.length();b+=3)g+=e.charAt(ArrayUtils.indexOf(c,f.substring(b,b+3)));System.out.println(g);}}

Here is a much less golfed version. It is intended to be readable, but I make no guarantees.

import org.apache.commons.lang.ArrayUtils;
class A {
    public static void main(String[] a) {
        int b=0;
        String[] c = new String[27];
        for (; b < 27; ++b)
            c[b] = String.format("%03d", Integer.valueOf(Integer.toString(b, 3)));
        String
            d = a[0],
            e = "abcdefghijklmnopqrstuvwxyz ",
            f = "",
            g = "";
        for (b = 0; b < d.length(); ++b)
            f += c[e.indexOf(d.substring(b, b + 1))];
        f = f.substring(1) + f.charAt(0);
        for (b = 0; b < f.length(); b += 3)
            g += e.charAt(ArrayUtils.indexOf(c, f.substring(b, b + 3)));
        System.out.println(g);
    }
}

This program takes the string to convert as a command-line argument. If you want to have spaces in your input, you have to surround it with double quotes.

I wanted to provide an example of using this from the command line, but I was unable to get this code to work outside of Eclipse. I never learned to use Java from the command line ^_^; You can probably get this running inside the IDE of your choice without too much trouble.

sadakatsu

Posted 2015-08-13T16:52:40.320

Reputation: 619

if you only use the ArrayUtils once using the fully qualified name inside the code is shorter than that import statement. see: http://codegolf.stackexchange.com/a/16100/10801 (bottom half of linked answer)

– masterX244 – 2015-09-28T11:40:57.347

1

Javascript (ES6), 181 180 bytes

t=>((x=[...t].map(k=>`00${(k<'!'?26:k.charCodeAt(0)-97).toString(3)}`.slice(-3)).join``).slice(1)+x[0]).match(/.../g).map(j=>j>221?' ':String.fromCharCode(parseInt(j,3)+97)).join``

This is an anonymous function, so it needs to be given a name before it can be used. (E.g. encrypt=t=>...) Try it out here:

e=t=>((x=[...t].map(k=>`00${(k<'!'?26:k.charCodeAt(0)-97).toString(3)}`.slice(-3)).join``).slice(1)+x[0]).match(/.../g).map(j=>j>221?' ':String.fromCharCode(parseInt(j,3)+97)).join``;

input=document.getElementById("input");
p=document.getElementById("a");
input.addEventListener("keydown", function(){
  setTimeout(function(){p.innerHTML = e(input.value);},10);
})
<form>Type your text here: <input type="text" id="input" value="hello world"/><br>
Only space and lowercase letters are allowed.</form>

<h3>Output:</h3>
<p id="a">vnhhr nqzgj</p>

I started out using multiple variables and for loops instead of .map. I then golfed it in every possible way without changing the algorithm, which put me somewhere around 217 bytes. After taking a look at UndefinedFunction's answer, I managed to get it down to 195, and some inspection of Dendrobium's answer resulted in another 14 golfed off.

As far as I'm aware, I can't go any further or my result would be practically identical to Dendrobium's (except for being one character shorter!). Can anyone find the place where I saved one char? :-)

As usual, suggestions are gladly welcome!

ETHproductions

Posted 2015-08-13T16:52:40.320

Reputation: 47 880

Thanks for the regex tip! I'm not sure how exactly the for-of loop could be worked into this one-line function, but perhaps it would save some space anyway. You can post your version if you like. – ETHproductions – 2015-08-14T15:09:46.300

0

Matlab, 113 bytes

x=dec2base(strrep(input('','s'),' ','{')-97,3)';strrep(char(base2dec(reshape(x([2:end 1]),3,[])',3)+97)','{',' ')

Input is through stdin.

Example:

>> x=dec2base(strrep(input('','s'),' ','{')-97,3)';strrep(char(base2dec(reshape(x([2:end 1]),3,[])',3)+97)','{',' ')
hello world
ans =
vnhhr nqzgj

Luis Mendo

Posted 2015-08-13T16:52:40.320

Reputation: 87 464

0

Julia - 92 87 61 54 bytes

s->join(32+(3(i=[s...]%91+579)%27+i[[2:end,1]]÷9)%91)

Ungolfed:

function f(s)
  t=[s...];       # Convert the string into a char array
                      #
  i=t%91+579          # Mod 91 drops the alpha characters to sit just
                      # below space, then 579 is added as a trick,
                      # equivalent to subtracting 6 and adding 9*65
  v1=3i%27            # This shifts the bottom two ternary digits up
                      # and removes the first ternary digit
  v2=i[[2:end,1]÷9    # This shifts the first ternary digit down and
                      # removes the bottom two ternary digits. [2:end,1]
                      # rotates the array to put the first value at the end
  N=(v1+v2)%91+32     # this combines the ternary digits, then returns
                      # the values to the correct ASCII values
  j=join(N)           # join the char array back to a string
  return j
end

The trick may confuse you. Subtracting 6 moves 'a' down to zero after the mod. Adding 9*65 is equivalent to adding 65 to v1+v2, which is part of the process of restoring the values to their ascii values. You could replace i=t%91+579 with i=t%91-6, and then replace N=(v1+v2)%91+32 with N=(v1+v2+65)%91+32 to get the same result, but it requires one extra character.

Glen O

Posted 2015-08-13T16:52:40.320

Reputation: 2 548