Walk Across a Keyboard

21

2

Given a word (or any sequence of letters) as input, you must interpolate between each letter such that each adjacent pair of letters in the result is also adjacent on a QWERTY keyboard, as if you typed the input by walking on a giant keyboard. For example, 'yes' might become 'ytres', 'cat' might become 'cxzawert'.

Rules:

  • This is the keyboard format you should use:

    qwertyuiop
    asdfghjkl
      zxcvbnm

    Any pair of keys which is touching in this layout is considered adjacent. For instance, 's' and 'e' are ajacent, but 's' and 'r' are not.

  • The input "word" will consist of any sequence of letters. It will have only letters, so you don't have do deal with special characters.
  • The input can be in any convenient form: stdin, a string, a list, etc. Letter case does not matter; you can take whatever is more convenient.
  • The output can be in any convenient form: stdout, a string, a list, etc. Letter case does not matter, and it does not need to be consistent.
  • Any path across the keyboard is valid, except that you cannot cross the previous letter again before getting to the next letter. For example, 'hi' could become 'hji' or 'hjnbgyui', but not 'hbhui'.
  • A letter is not ajacent with itself, so 'poll' cannot become 'poll'. Instead it would need to become something like 'polkl'.
  • No output letters are allowed before or after the word. For example, 'was' cannot become 'trewas' or 'wasdfg'.

This is code golf, the shortest answer in bytes wins.

Vaelus

Posted 2018-12-06T21:08:47.027

Reputation: 417

So we're outputting any valid 'walk' per input? This seems like it'd be better as given two inputs, determine if it's a valid walk. – Veskah – 2018-12-06T21:17:37.877

It seems like dewqwerty is a valid path for dy. Could you confirm that? – Arnauld – 2018-12-06T21:27:43.783

@Arnauld yes, it is. – Vaelus – 2018-12-06T21:47:22.107

@Veskah That's right; output any valid walk for an input. This is to allow for optimizations which might not be possible if, for instance, it had to be a shortest walk. – Vaelus – 2018-12-06T21:48:57.883

Answers

6

Japt -g, 23 bytes

;D·ÎÔ+D·Årí)pUl)fUq".*?

Try it online!

Takes input as an array of capital letters. Very similar to the other answers otherwise.

Explanation:

;                          :Set D to the keyboard layout
 D·Î                       :Get the first row of keys
    Ô                      :Reversed
     +                     :Concat
      D·Å                  :The other two rows
         rí)               :Interleaved
            p              :Repeat that string
             Ul)           : A number of times equal to the length of the input
                f          :Get the substrings that match
                 U         : The input
                  q".*?    : joined with ".*?"
                           :Implicitly output just once of the matches

Kamil Drakari

Posted 2018-12-06T21:08:47.027

Reputation: 3 461

14

Python 2, 83 bytes

lambda s:re.findall('.*?'.join(s),'qwertyuioplkmnjhbvgfcxdsza'*len(s))[0]
import re

Try it online!

Walks the entire keyboard until the word is written.

TFeld

Posted 2018-12-06T21:08:47.027

Reputation: 19 246

2How come the import re comes after the code, not before? – BruceWayne – 2018-12-07T20:44:01.607

@BruceWayne The re.findall would be evaluated when the lambda runs, so importing after the lambda's definition is ok. That being said, it is clearer to import before, there's just no need to – pushkin – 2018-12-07T23:17:58.117

@pushkin ah, I didn't know that thanks for clarifying! Did you import after just as a personal preference/choice or does it help with byte count at all? – BruceWayne – 2018-12-07T23:25:11.873

2@BruceWayne It's a bit of a convention for this forum. It's just so that it works with the way the TiO site organizes the code. Try clicking on the "Try it online!" link to see what I mean. – mypetlion – 2018-12-07T23:27:44.077

8

Python 2, 274 bytes (optimal solution)

296 300 302 308 315 319 324 327 328 430 432 bytes

-4 bytes thanks to mypetlion

from networkx import*
i=input()
M,z='qwertyuiop  asdfghjkl   zxcvbnm'.center(55),i[:1]
G=from_edgelist([(M[e],M[e+h])for h in[-1,1,11,12,-11,-12]for e in range(44)if' '!=M[e]and' '!=M[e+h]])
for y,x in zip(i,i[1:]):z+=[shortest_path(G,y,x)[1:],list(G[y])[0]+y][x==y]
print z

Try it online!

This solution gives the shortest possible output. The keyboard is transformed into a graph used to find the shortest path to compute the output string:

puzzles     --> poiuhbvcxzazxcvbhjklkiuytres
programming --> poiuytrtyuioijhgtresasdcvbnmkmkijnbg
code        --> cvbhjioijhgfde
golf        --> ghjiolkjhgf
yes         --> ytres
hi          --> hji
poll        --> polpl

mdahmoune

Posted 2018-12-06T21:08:47.027

Reputation: 2 605

274 bytes: Try it online!

– mypetlion – 2018-12-11T20:17:48.933

1@mypetlion u made an important reduction, u can update the answer :) – mdahmoune – 2018-12-11T20:56:37.077

4

JavaScript (ES6), 70 bytes

Same strategy as TFeld.

s=>'qazsxdcfvgbhnjmklpoiuytrew'.repeat(s.length).match(s.join`.*?`)[0]

Try it online!

Arnauld

Posted 2018-12-06T21:08:47.027

Reputation: 111 334

3

05AB1E, 43 bytes

ü)Jε©žVćRs`.ιJ«D«Œʒg≠yн®нQyθ®θQ**}yªн¨}JIθ«

Not the right language for this challenge, since it cannot use regex like the other answers did..

Try it online or verify all test cases.

Explanation:

ü)               # Split the input into overlapping pairs
                 #  i.e. "poll" → ["p","o"],["o","l"],["l","l"]]
  J              # Join each inner list together
                 #  i.e. ["p","o"],["o","l"],["l","l"]] → ["po","ol","ll"]
   ε             # Map each to:
    ©            #  Store the current value in the register
    žV           #  Push ["qwertyuiop","asdfghjkl","zxcvbnm"]
    ćR           #  Extract the head, and reverse it
                 #   i.e. ["qwertyuiop","asdfghjkl","zxcvbnm"] → "poiuytrewq"
    s`           #  Swap to take the remainder, and push them to the stack
      .ι         #  And then interweave them with each other
                 #   i.e. ["asdfghjkl","zxcvbnm"]
                 #    → ["a","z","s","x","d","c","f","v","g","b","h","n","j","m","k","l"]
        J        #  Join the list to a single string
                 #   i.e. → "azsxdcfvgbhnjmkl"
         «       #  Merge them together
                 #   i.e. "qwertyuiop" and "azsxdcfvgbhnjmkl"
                 #    → "poiuytrewqazsxdcfvgbhnjmkl"
          D«     #  Duplicate it, and append it to itself
                 #   i.e. "poiuytrewqazsxdcfvgbhnjmkl"
                 #    → "poiuytrewqazsxdcfvgbhnjmklpoiuytrewqazsxdcfvgbhnjmkl"
            Π   #  Get all substrings of this strings
                 #   i.e. → ["p","po","poi",...,"k","kl","l"]
ʒ              } #  Filter this list by:
 g≠              #   Where the length is NOT 1 (otherwise pair "ll" would result in "l")
              *  #   and
   yн®нQ         #   Where the first character of the substring and pair are the same
             *   #   and
        yθ®θQ    #   Where the last character of the substring and pair are the same
                 #    i.e. "po" → []
                 #    i.e. "ll" → ["lazsxdcfvgbhnjmkl"]
yª               #  After filtering, append the current pair to the filtered list
                 #   i.e. [] → ["po"]
                 #   i.e. ["lazsxdcfvgbhnjmkl"] → ["lazsxdcfvgbhnjmkl","ll"]
  н              #  Get the first item
                 #   ["po"] → "po"
                 #   ["lazsxdcfvgbhnjmkl","ll"] → "lazsxdcfvgbhnjmkl"
   ¨             #  Remove the last character
                 #   i.e. "po" → "p"
                 #   i.e. "lazsxdcfvgbhnjmkl" → "lazsxdcfvgbhnjmk"
}                # Close the map
 J               # Join everything together
                 #  i.e. ["p","o","lazsxdcfvgbhnjmk"] → "polazsxdcfvgbhnjmk"
  Iθ«            # And append the last character of the input
                 # (and output the result implicitly)
                 #  i.e. "polazsxdcfvgbhnjmk" and "poll" → "polazsxdcfvgbhnjmkl"

Kevin Cruijssen

Posted 2018-12-06T21:08:47.027

Reputation: 67 575

3

Charcoal, 48 bytes

≔”&⌈″⌊5EWXVNa…-εW¶ζR”η≔⌕η§θ⁰ζFθF⊕﹪⁻⌕ηιζ²⁶«§ηζ≦⊕ζ

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

≔”&⌈″⌊5EWXVNa…-εW¶ζR”η

Get the string qwertyuioplkmjnhbgvfcdxsza.

≔⌕η§θ⁰ζ

Find the position of the first character of the word. This index is normally one past the character just reached, but this value fakes out the first iteration of the loop to print the first character of the word.

Fθ

Loop over each character.

F⊕﹪⁻⌕ηιζ²⁶«

Compute how many characters to print to include the next character of the word and loop that many times.

§ηζ≦⊕ζ

Print the next character cyclically indexed and increment the index.

Neil

Posted 2018-12-06T21:08:47.027

Reputation: 95 035

Have you tried rotating the string “qwertyuioplkmjnhbgvfcdxsza” and seeing if any of the rotations happen to be more compressible? I'm not familiar with charcoal's compression; maybe this isn't possible. – Vaelus – 2018-12-08T00:06:21.760

@Vaelus I don't know either so I tried all 26 rotations but they all compress to 20 bytes. Of course, those aren't all of the possible walks... – Neil – 2018-12-08T01:04:00.193