The Challenge:

Given any input that can be typed on a keyboard, move the text along by N chars.

Here is the QWERTY keyboard to be used. You can ignore the modifier keys (Shift, Caps, Enter, Delete and Tab). Once you reach one side (for example |) loop back round, so | goes to Q if N = 1.

enter image description here

Spaces do not have to be moved along (they go back round to space as you skip modifiers). If shift was used to type the character (e.g. ! and @) the changed character should also be typed using shift (i.e. ! goes to @ not 2 if N = 1).

UK keyboards are different to this, but please use this so that we can compare.


Any sentence that can be typed on the above keyboard followed by a positive integer. There is no maximum to the size of this integer.


The same sentence, shifted along by N.


My name is Tim 3
?o .f/y [g I[/
Hello World 7
Spgge Oe[g;
I Wi5h I h4d b3773r C@d3ing ski{{s 3
{ T[8l { l7h ,6006u N%h6[.k g'[QQg

This is code golf, so shortest code wins.

  • \$\begingroup\$ Can we assume that N<= 13 as you will need to shift at most 13 in order to return to the original character? \$\endgroup\$
    – flawr
    May 17, 2015 at 10:30
  • 1
    \$\begingroup\$ @flawr nope, sorry. It can be any positive value. \$\endgroup\$
    – Tim
    May 17, 2015 at 10:31
  • \$\begingroup\$ Shouldn't the "Hello World 7" example be "Spggr Oe[g;"? \$\endgroup\$ May 17, 2015 at 16:16
  • \$\begingroup\$ Shouldn't the Hello World 7 example be Spgge Oe[g;? The two o should map to the same character \$\endgroup\$
    – edc65
    May 17, 2015 at 20:17

9 Answers 9


C, 217 bytes

char*t=" @A$%^*a)_(~.=/z-234567890\"'>`?Z#SNVFRGHJOKL:<MP{WTDYIBECUX]q\\&=1snvfrghjokl;,mp[wtdyibecux}Q|!";l,d,k;f(char*s){for(l=strlen(s);s[--l]-32;);d=atoi(s+l);for(s[l]=0;d--;)for(k=l;k--;s[k]=t[s[k]-32]);puts(s);}

Readable version with whitespace, includes, etc:

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

char* t = " @A$%^*a)_(~.=/z-234567890\"'>`?Z#SNVFRGHJOKL:<MP{WTDYIBECUX]q\\&=1snvfrghjokl;,mp[wtdyibecux}Q|!";
int l, d, k;

void f(char* s) {
    l = strlen(s);
    for( ; s[--l] - 32; );
    d = atoi(s + l);
    s[l] = 0;
    for ( ; d--; ) {
        for (k = l; k--; s[k] = t[s[k] - 32]);

The code pretty much speaks for itself. Just a lookup table that maps from each character to the next character, which is applied the given number of times. Much of the code is actually for parsing the number out of the input.

  • \$\begingroup\$ @Ypnypn You can use undeclared functions in C. So the includes are not needed for it to build. It typically gives compiler warnings, but I've been told that this is allowed as long as it builds and runs. \$\endgroup\$ May 17, 2015 at 23:39

05AB1E, 61 bytes

-1 byte thanks to Kevin Cruijssen

žVDu«1ú`žhÀ“~!@#$%^&*()_+ `ÿ-=ÿ<>?ÿ:"ÿ{}|ÿ,./ÿ;'ÿ[]\“#vyy¹._‡

Try it online!


Pyth, 126 bytes

XjdPczdsJc"~!@#$%^&*()_+ `1234567890-= qwertyuiop[]\ QWERTYUIOP{}| asdfghjkl;, ASDFGHJKL:\" zxcvbnm,./ ZXCVBNM<>?")sm.<dvecz)J

Try it online: Demonstration or Test Suite


    czd                       split input by spaces
   P                          remove the last element
 jd                           join by spaces (=#1)

          "..."               string with the chars of each row
         c     )              split by spaces
        J                     assign to J
       sJ                     sum of J (=#2)

                       cz)    split input by spaces
                      e       take the last element
                     v        and evaluate it 
                 m        J   map each row d of J to:
                  .<d           rotate the row d by value
                s             sum (=#3)

X                             Take #1, and replace the chars in #2 by the chars in #3

Python 3, 311 bytes

print("".join([[x[int(s):]+x[:int(s)]for x in r][r.index([x for x in r if c in x][0])][([x for x in r if c in x][0]).index(c)]if c!=" "else " " for c in " ".join(i)]))
  • \$\begingroup\$ Remove the unnecessary spaces in " " for c in " " \$\endgroup\$
    – mbomb007
    May 17, 2015 at 21:57

Python 3, 271 255 bytes

Baseline, almost ungolfed, used to create the shifted words in the question.

x=' '.join(x[:-1])
l=['`1234567890-=','qwertyuiop[]\\',"asdfghjkl;'",'zxcvbnm,./', '~!@#$%^&*()_+','QWERTYUIOP{}|','ASDFGHJKL:"','ZXCVBNM<>?',' ']
for i in x:
 for q in l:
  if i in q:y+=q[(q.index(i)+n)%len(q)]


x=input().split()    # Get input
n=int(x[-1])         # Get N from input
x=' '.join(x[:-1])   # Get the words from input
                     # Create list of letters

l=['`1234567890-=', 'qwertyuiop[]\\',
   "asdfghjkl;'",   'zxcvbnm,./',
   '~!@#$%^&*()_+', 'QWERTYUIOP{}|',
   'ASDFGHJKL:"',   'ZXCVBNM<>?',
   ' ']

y=''                 # Blank string
for i in x:          # Loop through letters in input
    for q in l:      # Loop through items in list
        if i in q:   # Is letter of input in item of list?
            y+=q[                          # Append letter to y
                 (q.index(i)+n)            # locate the letter in item, and add N
                               %len(q)]    # % is modulus, loop to beginning if big
print(y)             # Print out the offset word.
  • \$\begingroup\$ I think you should delete this. Let other people work out their own strategies... \$\endgroup\$
    – mbomb007
    May 17, 2015 at 21:58
  • \$\begingroup\$ @mbomb007 it's not very golfed, and I used it to create them... I think it's fair enough to post it, personally. \$\endgroup\$
    – Tim
    May 18, 2015 at 7:19

JavaScript (ES6), 200 216

Using template strings, the newlines are significant and counted.

Note about replace: the two snippets string.split('x').map(w=>...) and string.replace(/[^x]+/g,w=>...) are equally valid ways to execute a function for each part in a string, using a separator. Using a newline as a separator is handy as the replace regexp becomes /.+/g, because the dot match any non-newline. And using templated strings the newlines have no extra cost.

f=(t,d)=>[for(c of t)`~!@#$%^&*()_+

// less golfed
  [for(c of t)
    '~!@#$%^&*()_+ 1234567890-= QWERTYUIOP{}| qwertyuiop[]\\ ASDFGHJKL:" asdfghjkl;\' ZXCVBNM<>? zxcvbnm,./'
    .split(' ')


;[['Hello World',7,],['My name is Tim',3],['I Wi5h I h4d b3773r C@d3ing ski{{s', 3]]
.forEach(p=>out(p+' -> '+f(p[0],p[1])))
<pre id=O></pre>


CJam, 107 bytes

lS/)~\S*\",./ ;'  <>? :\"  _+~!@#$%^&*() -=`"A,s(++S/"zxcvbnm

Try it online in the CJam interpreter.

How it works

lS/)   e# Read one line from STDIN, split at spaces and pop the last chunk.
~\S*\  e# Evaluate the popped chunk and join the remaining ones back together.
",./ ;'  <>? :\"  _+~!@#$%^&*() -=`"
       e# Push that string.
A,s(++ e# Concatenate it with "1234567890".
S/     e# Split at spaces.
"zxcvbnm asdfghjkl []\qwertyuiop"
       e# Push that string.
S/     e# Split at spaces. (`N/' would split at linefeeds.)
_32ff^ e# XOR each character of a copy with 32.
+      e# Concatenate the copies.
.+     e# Perform vectorized concatenation. This pushes the following array:
          [ ",./zxcvbnm" ";'asdfghjkl" "[]\qwertyuiop" "<>?ZXCVBNM"
           ":\"ASDFGHJKL" "{}|QWERTYUIOP" "_+~!@#$%^&*()" "-=`1234567890" ]
_@fm>  e# Rotate each chunk by the number of character specified in the input.
s\s    e# Flatten this array and the original.
er     e# Perform transliteration.

Jelly, 67 bytes

ØDṙ1ṭØQ;Øq;"“{}|“:"“<>?“-=`“[]\“;'“,./“~!@#$%^&*()_+“ ”

Try it online!

A dyadic link taking the string as its left argument and the number of places to shift as its right argument.


Python 2, 194 bytes

f=lambda s,n:n and f(''.join(B[B.find(c)+1]for c in s),n-1)or s
B='`1234567890-=`~!@#$%^&*()_+~'+A%('[]\\',";'",',./')+(A%('{}|',':"','<>?')).upper()+'  '

Try it online!


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.