# Shift the letters, soldier?

## Context

We're at war! You need to transfer an important message to your general to inform them from an imminent assault. The thing is, your enemy knows a lot about cryptography : you will need to be more creative in order to encode your message...

Create a program that accepts an ascii message as input, and outputs the encoded message. The message should be encoded this way : each character should get its ascii value shifted by its position in the message.

For example, let's encode the message "Hello, world!"

H   e   l   l   o   ,       w   o   r   l   d   !     Original message

72  101 108 108 111 44  32  119 111 114 108 100 33    ASCII value

0   1   2   3   4   5   6   7   8   9   10  11  12    Place in the message

72  102 110 111 115 49  38  126 119 123 118 111 45    Encoded ascii (line 1 + line 2)

H   f   n   o   s   1   &   ~   w   {   v   o   -     Encoded message


The message Hello, world! should be encoded as Hfnos1&~w{vo-.

Sometimes the encoded ascii can go beyond printable character. In that case, the value loop back to 32 (read the rules for additionnal informations)

T   h   e       r   a   n   d   o   m       g   u   y      Original message

84  104 101 32  114 97  110 100 111 109 32  103 117 121    ASCII value

0   1   2   3   4   5   6   7   8   9   10  11  12  13     Place in the message

84  105 103 35  118 102 116 107 119 118 42  114 129 134    Encoded ascii (line 1 + line 2)

84  105 103 35  118 102 116 107 119 118 42  114 34  39    Corrected encoded ascii (looped back to 32)

T   i   g   #   v   f   t   k   w   v   *   r   "   '


The random guy is then converted into Tig#vftkwv*r"'

Using the same strat, zzzzzzzzz will be converted into z{|}~ !"# (ascii values converted into 122 - 123 - 124 - 125 - 126 - 32 - 33 - 34 - 35)

## Rules

• The input message will be composed of printable ascii character (between 32 and 126)

• The message should be encoded as described before.

• The ascii values of the encoded message should be set between 32 and 126.

• The first character of the message should be at position 0.

• If the new ascii value goes beyond the limit, it should loop back to 32.

• Every character should be encoded. This includes punctuation, spaces etc.

• No standard loopholes allowed.

• This is codegolf, so the shortest code wins.

• Meta Jun 3 '20 at 7:44
• Suggested test case: 'zzzzzzzzz', to catch the correct wrapping point
– PaMu
Jun 3 '20 at 8:11
• @Adám yes, every character in the input message will be set between 32 and 126 Jun 3 '20 at 8:15
• You may want to spell out that your positions are 0-based.
Jun 3 '20 at 8:15
• "Your enemy knows a lot about cryptography" Evidently not if this simple code is enough to confound them. ;-p Jun 3 '20 at 17:39

# Charcoal, 9 bytes

⭆Ｓ§γ⁺κ⌕γι


Try it online! Link is to verbose version of code. Explanation:

 Ｓ          Input string
⭆           Map over characters and join
ι   Current character
⌕     Find position in
γ    Printable ASCII
⁺       Plus
κ      Current index
§         Cyclically indexed into
γ        Printable ASCII
Implicitly print


# Python 3.8, 55 54 bytes

Output is a list of characters.

lambda s,d=33:[chr((ord(c)-(d:=d-1))%95+32)for c in s]


Try it online!

# J, 22 bytes

(95|<:+#\)&.(_32+3&u:)


Try it online!

Almost word-to-word translation of my dzaima/APL solution.

### How it works

(95|<:+#\)&.(_32+3&u:)  NB. Input: string S
(   X    )&.(   Y    )  NB. The "Under" operator; do Y, do X and undo Y
_32+3&u:   NB. Convert chars to codepoints and subtract 32
#\               NB. One-based index
<:+                 NB. Add to the codepoints minus 1
95|                    NB. Modulo 95
_32+3&u:   NB. Undo this: add 32 and convert to chars


# R, 56 57 bytes

function(s)intToUtf8((utf8ToInt(s)-33+1:nchar(s))%%95+32)


Try it online!

Edit: thanks to Giuseppe for bug-spotting!

I am beginning to despise string manipulations in R, and the intToUtf8() / utf8ToInt() function names in particular...

• this will fail for a single character input "a" for instance. You can save it at a cost of 2 bytes -- wasn't sure if that would actually work until I tried it! Jun 3 '20 at 18:03
• and yes, R's string manipulation is abysmal. Jun 3 '20 at 18:03
• There's also a 57 byte solution if you get rid of seq Jun 3 '20 at 18:07
• Aargh! Well-spotted for the single-character-input bug, and thanks for the suggestion (that's a nice 4-byte shortcut for seq_along that I didn't know about!). Jun 3 '20 at 19:11
• The 57-byte solution is what I originally had... I was smugly thinking how cleverly I'd saved a byte until you pointed-out that it didn't actually work! Jun 3 '20 at 19:12

# APL (dzaima/APL), 21 bytes

{95|⍵+⍳≢⍵}⍢(¯32+⎕UCS)


Try it online!

Just trying out the experimental Under operator ⍢ because the task is screaming for it.

### How it works

{95|⍵+⍳≢⍵}⍢(¯32+⎕UCS)  ⍝ Input: string S
⍢(¯32+⎕UCS)  ⍝ Convert S to Unicode codepoints and subtract 32
{   ⍵+⍳≢⍵}             ⍝ Add the index to each char
95|                   ⍝ Modulo 95
⍢(¯32+⎕UCS)  ⍝ Undo the operation:
⍝ Add 32 and convert back to Unicode chars

• That operator looks like it is really happy to be used Jun 3 '20 at 8:56

# 05AB1E, 1610 9 bytes

žQDIkā<+è


-1 byte by porting @Neil's Charcoal answer, so make sure to upvote him!

I/O as a list of characters.

Explanation:

žQ          # Push the printible ASCII string builtin
D         # Duplicate it
I        # Push the input-list of characters
k       # Get each index in the ASCII string
ā      # Push the list [1, length] (without popping)
<     # Decrease it by 1 to make it a 0-based range [0, length)
+    # Add the values at the same positions in the lists together
è   # Index each into the ASCII string (0-based and with automatic wraparound)
# (after which the resulting list of characters is output implicitly)


# Perl 5 (-p), 32 bytes

-1 byte thanks to @Abigail

s/./chr 32+($x++-32+ord$&)%95/ge


Try it online!

• from the test case it seems it's 94 Jun 3 '20 at 9:07
• you're correct the post was updated 41 min ago Jun 3 '20 at 9:18
• Save a byte by using ($x++-32+ord$&) instead of (-32+$x+++ord$&). Jun 3 '20 at 9:51
• @Abigail +++ looks cooler though!
– Neil
Jun 3 '20 at 18:49

# C (gcc), 48 47 46 bytes

Saved a byte thanks to 640KB!!!

Saved a byte thanks to dingledooper!!!

i;f(char*s){for(i=32;*s;)*s++=(*s-i--)%95+32;}


Try it online!

• @dingledooper Nice one - thanks! :-) Jun 4 '20 at 8:13

# APL (Dyalog Unicode), 2824 22 bytes SBCS

-4 bytes thanks to @Adám; -2 bytes thanks to @ngn;

Monadic function expecting a string:

⎕ucs 32+95|⎕ucs-32-⍳∘≢


Try it online! Assumes ⎕IO←0. How the 24-byter works:

32(⎕ucs⊣+95|⊢--∘⍳∘≢)⎕ucs  ⍝ monadic function taking a character vector on the right
⎕ucs  ⍝ convert to unicode code points
32(                 )      ⍝ and then evaluate the expression with 32 as left argument and the code points as right arg
-∘⍳∘≢        ⍝ do 32 minus (-) the range 0 1 ... [length of input string] (⍳∘≢)
⊢-            ⍝ take the right argument (⊢) [the codepoints] and subtract the previous calculation from those [effectively adding the positions and subtracting 32]
95|               ⍝ and take those numbers modulu 95.
⊣+                  ⍝ Take the left (⊣) argument [32] and add it to the numbers we just did mod 95
⎕ucs                     ⍝ and convert the new code points to characters.


@Bubbler has a similar answer but making use of an operator that hasn't been implemented in Dyalog APL yet, check it out.

• Yours actually consumes 42 bytes (UTF-8) Jun 3 '20 at 8:28
• @JohnBrookfields I know, I'm on my mobile so I took a bit longer to link the appropriate encoding. C.f. my edited answer
– RGS
Jun 3 '20 at 8:30
• 24: 32(⎕ucs⊣+95|⊢--∘⍳∘≢)⎕ucs
Jun 3 '20 at 8:37

# Retina 0.8.2, 19 bytes

{*\M!^.
^.

T~pp


Try it online! Link includes test cases. Explanation:

{


Repeat until the input is empty.

*\M!^.


Output the first character.

^.


Remove the first character.

T~pp


Cyclically increment the remaining characters.

12 bytes in Retina 1:

1,Tv~pp.+


Try it online! Link includes test cases. Explanation:

v.+


Create overlapping matches that start at each character and end at the end of the string.

1,


Ignore the match of the whole input.

T~pp


Cyclically shift each character according to the number of times it was matched.

{c$32+95!x-32-!#x}  Try it online! # Java (OpenJDK 8), 80 60 bytes s->{int i=0;for(char n:s)s[i]+=i-(n+i++>126?95:0);return s;}  Try it online! Thanks for help from Kevin Cruijssen • Looks like this gives the wrong output for "The random guy" (should be Tig#vftkwv*r"') -- I think your 94 should be 95, that seems to fix it Jun 4 '20 at 3:46 • -1 by combining the s[i]+= with the s[i]-= like this: s[i]+=i-(i+s[i++]>126?95:0). Also, you can use a lambda in Java 8+, so the char[]a(char[]s) can be s->: try it online - 64 bytes Jun 4 '20 at 14:43 • If you've never used lambdas before in Java, here are some brief examples of different lambdas and how to use it in codegolf. In general, you almost always want to use lambdas in Java codegolfing, unless you need a recursive function, which would still be a regular method. Jun 4 '20 at 14:46 • 48 bytes Jun 5 '20 at 13:27 • The input object is the output object. It happens all the time in programming. Not every function is pure. And yes, we accept it as is here on Code Golf. Jun 5 '20 at 13:35 # Haskell, 55 bytes g '~'=' ' g c=succ c i!c=iterate g c!!i zipWith(!)[0..]  Try it online! The TIO link has f=, but that doesn't contribute to the byte count because I defined it point-free. It's mostly there so that the code compiles. I didn't play around much with using a point-free definition instead of !, so that might be a place where some bytes can be shaved off. I just figured that the parens and dots would add up. I also want to get rid of the call to iterate, but I'm not sure how. I want something like mtimes... # Haskell + -XParallelListComp, 55 bytes g '~'=' ' g c=succ c f s=[iterate g c!!i|c<-s|i<-[0..]]  Try it online! Unfortunately this isn't any shorter, but I thought it was a cool usage of a pragma. It seems most of the time that pragmas aren't too helpful in golfing. # Explanation -- g gives the successor of each character according to the specification g :: Char -> Char -- the successor of '~' is ' ' (wrap around) g '~'=' ' -- all other characters have their normal successor g c=succ c -- (!) is an infix function that enciphers a character, given an int (!) :: Int -> Char -> Char -- iterate produces an infinite list of 'g' applied to 'c' repeatedly, -- and '!!' indexes into that list at index 'i'. This has the effect -- of applying 'g' to 'c' 'i' times. i!c=iterate g c!!i -- Point-free definition that applies '!' to each character of the input along with its index zipWith(!)[0..]  • Nice idea to try a pragma to substitute zipWith. I did find two shorter approaches, though using ParallelListComp results in the same byte count for those as well. Jun 17 '20 at 16:00 # x86-16 machine code, IBM PC DOS, 17 16 bytes Binary: Build STL.COM using xxd -r: 00000000: b120 b408 cd21 2ac1 d45f 0420 cd29 e0f2 . ...!*.._. .)..  Listing: B1 20 MOV CL, 32 ; set up offset / position counter CLOOP: B4 08 MOV AH, 8 ; use DOS API get char from STDIN function CD 21 INT 21H ; read input char into AL 2A C1 SUB AL, CL ; subtract offset D4 5F AAM 95 ; AL = AL % 95 04 20 ADD AL, 32 ; restore ASCII offset CD 29 INT 29H ; output AL to console E0 F2 LOOPNZ CLOOP ; keep looping until break, decrement CL  Standalone IBM PC DOS executable program. Input via STDIN, output to console. Runtime: # Haskell, 52 51 bytes zipWith(%)[-32..] n%c=toEnum$32+mod(fromEnum c+n)95


Try it online!

# Haskell, 52 bytes

zipWith(%)[0..]
n%c=snd(span(<c)$cycle[' '..'~'])!!n  Try it online! ### Explanation • zipWith(%)[0..] calls the infix function % on each character of the input string along with its index. • cycle[' '..'~'] builds a list where the ASCII chars are repeated infinitely. • span(<c) partitions this list into a prefix of chars smaller than the current character c and a remainder. • snd drops the prefix, so only the list of ASCII chars starting with c remains. • !!n returns the nth element from that list. # Ruby, 42 bytes ->s{i=33;s.map{((_1.ord-i-=1)%95+32).chr}}  Takes input and returns output as an array of characters. ### 44 byte version because TIO doesn't support ruby 2.7's _1 syntax ->s{i=33;s.map{|c|((c.ord-i-=1)%95+32).chr}}  Try it online! # APL (Dyalog Extended), 22 bytes (SBCS) Full program. Requires ⎕IO←0 ⍞(⊢⊇⍨95|⍳⍨+~⍋⊣)' '…'~'  Try it online! ' '…'~' the printable ASCII range ⍞() with the input as left argument, apply the following tacit function to that: ⊣ the left argument (the input) ⍋ the sorting permutation to sort according to the following order: ~ the input without any printable ASCII, i.e. an empty string (this means leave all in current positions) ⍳⍨ the indices of the input characters in the printable ASCII 95| division remainder when divided by 95 ⊇⍨ use those indices to select from: ⊢ the printable ASCII # Befunge-93, 25 bytes :~:1+!#@_" "-+"_"%" "+,1+  Try it online! Keeps the character count on the bottom of the stack. Then in a loop, reads a character at the time, subtracts 32 to the character, adds the character count, mods it with 95, adds 32 again, then prints the character. Finally, it adds 1 to the character count. # T-SQL, 100 bytes Added some line changes to make it readable DECLARE @x INT=0 WHILE @x<len(@) SELECT @=substring(@,2,999)+char((ascii(@)+@x-32)%95+32), @x+=1 PRINT @  Try it online # Ly, 25 bytes ir84*sp[l-l,sp(95)%84*+o]  Try it online! # JavaScript, 77 bytes Iterative! s=>[...s].map((c,i)=>String.fromCharCode((c.charCodeAt()+i-32)%95+32)).join  Try it online! # JavaScript, 77 bytes Outer recursive! f=(s,i=0)=>s[i]?String.fromCharCode((s.charCodeAt(i)+i-32)%95+32)+f(s,i+1):''  Try it online! # JavaScript, 77 bytes Inner recursive! s=>(F=i=>s[i]?String.fromCharCode((s.charCodeAt(i)+i-32)%95+32)+F(i+1):'')(0)  Try it online! # JavaScript (Node.js), 42 bytes s=>Buffer(s).map((c,i)=>(c+i-32)%95+32)+''  Try it online! # Jelly, 9 bytes O+J_32ịØṖ  Try it online! ### How? O+J_32ịØṖ - Link: list of characters, S - e.g. "zzzzzzzzz" O - cast (S) to ordinal values [122,122,122,122,122,122,122,122,122] J - range of length (S) [ 1, 2, 3, 4, 5, 6, 7, 8, 9] + - add (vectorises) [123,124,125,126,127,128,129,130,131] 32 - thirty-two 32 _ - subtract [ 91, 92, 93, 94, 95, 96, 97, 98, 99] ØṖ - printable ASCII characters " !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_abcdefghijklmnopqrstuvwxyz{|}~"
ị   - index into (1-based & modular)      "z{|}~ !"#"


# C (gcc), 46 50 48 bytes

x;f(char*s){*s?*s=(*s+x++-32)%95+32,x=f(s+1):0;}


Try it online!

• This isn't legal, you can't depend on a variable being externally set outside of the function. Jun 3 '20 at 11:13
• I don't depend on it for the 1st iteration, only subsequent ones... (proof), is that also illegal? Jun 3 '20 at 11:41
• No, it is not legal. It has to work independently for any run, not just the first. In C this means, for instance, a function can't depend on global variables being set to 0 at the start of a program run. Jun 3 '20 at 12:12
• Can I say the function takes an extra argument that must always be 0 or is that illegal too? Jun 3 '20 at 12:24
• @Noodle9 Do you have a link to the rules thread? I can't seem to find it. Jun 3 '20 at 12:35

# Erlang (escript), 68 bytes

f(I,[H|T])->[(H+I-32)rem 95+32]++f(I+1,T);f(_,[])->[].
f(I)->f(0,I).


Try it online!

# Stax, 9 bytes

éñÇöo♣j0♦


Run and debug it

# Wolfram Language, 68 bytes

FromCharacterCode@Mod[#&~Array~Length@#+#-1,95,32]&@*ToCharacterCode


Uses a little function composition to make it shorter, but other than that, does pretty much what it says on the tin. Converts the string to character codes, adds the proper offset to each, wraps around if needed using Mod (there's an optional argument for offset that I use here), then converts back to a string.

• I believe #&~Array~Length@# can be replaced with Range@Length@# for a 3-byte improvement. Jun 6 '20 at 4:34

# Keg, 19 bytes

0&(⑻+:\~>[\~% +;],⑹


Try it online!

Woooo! I managed to beat APL somehow! This is a very literal interpretation of the challenge, except for the part where overflow values are decremented after modulusing.

# Befunge-98 (FBBI), 20 bytes

'!v
-1<,+ '%_'-\~@#:


Try it online!

Initially pushes d=33 on the stack. On every iteration, d is reduced by one and (input-d)%95+32` is printed.