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.

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.

Input:

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.

Output:

The same sentence, shifted along by N.

Examples:

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.

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

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]);
}
puts(s);
}


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.

• @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. – Reto Koradi May 17 '15 at 23:39

Pyth, 126 bytes

XjdPczdsJc"~!@#$%^&*()_+ 1234567890-= qwertyuiop[]\ QWERTYUIOP{}| asdfghjkl;, ASDFGHJKL:\" zxcvbnm,./ ZXCVBNM<>?")sm.<dvecz)J  Try it online: Demonstration or Test Suite Explanation:  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 *i,s=input().split() r=["1234567890-=","qwertyuiop[]\\","asdfghjkl;'","zxcvbnm,./","~!@#$%^&*()_+","QWERTYUIOP{}|",'ASDFGHJKL:"',"ZXCVBNM<>?"]
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)]))

• Remove the unnecessary spaces in " " for c in " " – mbomb007 May 17 '15 at 21:57

Python 3, 271 255 bytes

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

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

• I think you should delete this. Let other people work out their own strategies... – mbomb007 May 17 '15 at 21:58
• @mbomb007 it's not very golfed, and I used it to create them... I think it's fair enough to post it, personally. – Tim May 18 '15 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)~!@#$%^&*()_+ 1234567890-= QWERTYUIOP{}| qwertyuiop[]\\ ASDFGHJKL:" asdfghjkl;' ZXCVBNM<>? zxcvbnm,./.replace(/.+/g,r=>(p=r.indexOf(c))<0?0:q=r[(p+d)%r.length],q=c)&&q].join('') // less golfed x=(t,d)=> [for(c of t) '~!@#$%^&*()_+ 1234567890-= QWERTYUIOP{}| qwertyuiop[]\\ ASDFGHJKL:" asdfghjkl;\' ZXCVBNM<>? zxcvbnm,./'
.split(' ')
.map(r=>(p=r.indexOf(c))<0?0:q=r[(p+d)%r.length],q=c)&&q
].join('')

// TEST

out=x=>O.innerHTML+=x+'\n'

;[['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 asdfghjkl []\qwertyuiop"N/_32ff^+.+_@fm>s\ser  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.