I am a robot. I bought this keyboard because of its easy rectangular layout:

~`   !1   @2   #3   $4   %5   ^6   &7   *8   (9   )0   _-   +=
tab  Qq   Ww   Ee   Rr   Tt   Yy   Uu   Ii   Oo   Pp   {[   }]    \|
     Aa   Ss   Dd   Ff   Gg   Hh   Jj   Kk   Ll   :;   "'   [-enter-]
          Zz   Xx   Cc   Vv   Bb   Nn   Mm   <,   >.   ?/
                         [========= space =========]

To print human text, I need to convert it to commands that my manipulators can interpret. My left manipulator hovers over the Shift key. My right manipulator, at the beginning, hovers over the ~ key. The commands that my manipulators understand are:

S      : press the shift key
s      : release the shift key
L      : move the right manipulator left by 1
R      : move the right manipulator right by 1
U      : move the right manipulator up by 1
D      : move the right manipulator down by 1
P      : press the key under the right manipulator
p      : release the key by the right manipulator

Write code to convert any ASCII message to a list of commands. The input can contain any number of the 95 printable ASCII characters; possibly also TAB and newline characters. The output should be the list of the commands to the manipulators.

So, for example, to type Hello World!, the commands are


I reset the manipulators to initial state before printing each message.

There are some mechanical hazards that should be avoided by proper programming:

  1. No moving (LRUD) allowed when printing (P) is engaged
  2. No jamming of manipulators: when a manipulator is engaged (S or P), the next command for this manipulator should be disengaging (s or p), and vice-versa
  3. No unnecessary shifting: between each two shift (s, S) commands, there should be a P command

    So, to print ~~, commands SPpPp are valid, while SPpsSPp are not

  4. No moving out of bounds: no movement command should try to move the right manipulator more than 13 spaces to the right or 4 to the bottom of the initial position (or any spot to the top or left)

Additional notes:

  • Pressing a disabled key (command sequence like DDPp) results in no keys pressed and is allowed.
  • Pressing Shift+Tab has no effect, but Shift+Space and Shift+Enter have the same effect as without Shift.
  • Pressing on any spot on the space bar and the Enter key has the same effect.
  • Whitespace keys in output have no meaning, but can be used to format it in a beautiful way.
  • \$\begingroup\$ Is speed a problem? Could we return the manipulators to their home position between each character (so long as it doesn't include unnecessary shifting, of course)? \$\endgroup\$ May 21, 2018 at 18:05
  • \$\begingroup\$ No problem. Maybe it could be more interesting without extra movement, but I don't like requiring the best possible output. \$\endgroup\$
    – anatolyg
    May 21, 2018 at 18:10
  • 1
    \$\begingroup\$ Related one, related two. \$\endgroup\$ May 21, 2018 at 18:11
  • 2
    \$\begingroup\$ You haven't actually defined the task... What character can input contain? What is the actual task (I'm going to guess it's the obvious based on the title, but you should specify nonetheless) \$\endgroup\$
    – hyper-neutrino
    May 21, 2018 at 18:19
  • 3
    \$\begingroup\$ Why bother with Pp? As far as I can see those are always a single action and neither P or p can appear on its own. \$\endgroup\$
    – orlp
    May 22, 2018 at 5:31

3 Answers 3


Python 2, 338 337 335 331 325 bytes

for c in input():p='`1234567890-=`	qwertyuiop[]|`asdfghjkl;\'\n```zxcvbnm,./``````` ~!@#$%^&*()_+~~QWERTYUIOP{}\\~ASDFGHJKL:"\n~~~ZXCVBNM<>?~~~~~~~ '.find(c);S=[p>61,s][c in' \n'];p%=62;Y=p/14;X=[max(x,12),min(max(x,5),10),p%14]['\n '.find(c)];print'sS'[S]*(s^S)+'LR'[X>x]*abs(X-x)+'UD'[Y>y]*abs(Y-y)+'Pp';x,y,s=X,Y,S

Try it online!

Moves directly from each character to the next.


  • S=[c in K,s][c in' \n'], checks if the next character should be Upper- or lowercase. If c is a space or newline, the case remains the same.

  • X=[max(x,12),min(max(x,5),10),p%15]['\n '.find(c)]. If c is a space or newline, the closest x-coordinate to the current is chosen(as the keys span multiple columns)

  • print'sS'[S]*(s!=S)+'LR'[X>x]*abs(X-x)+'UD'[Y>y]*abs(Y-y)+'Pp', prints the case switch, the number of x-coordinate moves, the number of y-coordinate moves, and finally Pp, for each character

Shorter version, if the shortest path is not required:

Python 2, 294 293 291 287 281 bytes

for c in input():p='`1234567890-=`	qwertyuiop[]|`asdfghjkl;\'\n```zxcvbnm,./``````` ~!@#$%^&*()_+~~QWERTYUIOP{}\\~ASDFGHJKL:"\n~~~ZXCVBNM<>?~~~~~~~ '.find(c);S=[p>61,s][c in' \n'];p%=62;X,Y=p%14,p/14;print'sS'[S]*(s^S)+'LR'[X>x]*abs(X-x)+'UD'[Y>y]*abs(Y-y)+'Pp';x,y,s=X,Y,S

Try it online!

  • \$\begingroup\$ Is it really required to use the shortest path to space / enter? \$\endgroup\$
    – Arnauld
    May 22, 2018 at 10:40
  • \$\begingroup\$ @Arnauld, I guest not, it wasn't specified but the example goes to the nearest space (after o) \$\endgroup\$
    – TFeld
    May 22, 2018 at 11:02

JavaScript (ES6), 263 bytes

Takes input as an array of characters.

${1e6}zZxXcCvVbBnNmM,<.>/?${1e13} `.indexOf(c))>>1),g=k=>'LRUD'[n=k?y/14:y%14,k^=n<0].repeat(n<0?-n:n))()+g(2)+['sS'[j-s&c!=' '&c!=`

Try it online!


.COM opcode, 108 104 bytes

0000h: B4 00 CD 16 BE 50 01 83 C6 03 3A 24 77 F9 0F B6
0010h: DC 03 5C 01 B4 02 CD 16 B4 02 68 00 01 A8 03 B2
0020h: 53 74 08 81 36 20 01 20 01 CD 21 84 DB 74 0B 4B
0030h: B2 52 E8 F4 FF B2 4C CD 21 C3 84 FF 74 0C FE CF
0040h: B2 44 E8 E4 FF B2 55 CD 21 C3 B2 50 CD 21 B2 70
0050h: CD 21 C3 0D FE 00 1B F1 00 1C F0 01 28 E3 01 29
0060h: D7 FF 35 D6 02 39 CC 03                        

Take input from keyboard with CapsLock off

Badly golfed though

        org 100h
        mov ah, 0
        int 16H
        mov si, table-3
tabing: add si, 3
        cmp ah, [si]
        ja tabing
        movzx bx, ah
        add bx, [si+1]
        mov ah, 2
        int 16H
        mov ah, 2
        push 100H
        test al, 3
        mov dl, 'S'
cmd:    jz fun
        xor [cmd-1], word 0x120
        int 21H
fun:    test bl, bl
        jz bl0
        dec bx
        mov dl, 'R'
        int 21H
        call fun
        mov dl, 'L'
        int 21H
bl0:    test bh, bh
        jz bh0
        dec bh
        mov dl, 'D'
        int 21H
        call fun
        mov dl, 'U'
        int 21H
bh0:    mov dl, 'P'
        int 21H
        mov dl, 'p'
        int 21H
macro key begin, end, U, L {
        db end
        dw U*256+L-begin
        key 0x02, 0x0D, 1, 0
        key 0x10, 0x1B, 1, 1
        key 0x1C, 0x1C, 2, 12
        key 0x1E, 0x28, 2, 1
        key 0x29, 0x29, 0, 0
        key 0x2C, 0x35, 3, 2
        key 0x39, 0x39, 4, 5
  • \$\begingroup\$ A great idea to do that without a LUT! \$\endgroup\$
    – anatolyg
    May 22, 2018 at 15:02
  • 1
    \$\begingroup\$ Take input from keyboard How is our robot friend, who is asking for help using his keyboard, to make use of this program? \$\endgroup\$
    – Shaun H
    May 22, 2018 at 19:04

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.