Is the word typeable with keys adjacent to each other?

13

Before reading this I suggest reading this little puzzle: https://puzzling.stackexchange.com/questions/11408/longest-word-with-adjacent-letters-on-a-keyboard

I want you to make a program that takes one argument, a word (only lowercase letters), and outputs "Yes" if the word can be typed with adjacent keys on the keyboard (see the article) and "No" if the word can't be typed with adjacent letters.

Here's the keyboard layout used in this challenge:

 ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
 | Q | W | E | R | T | Y | U | I | O | P |
 └─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┘
   | A | S | D | F | G | H | J | K | L |
   └─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┘
     | Z | X | C | V | B | N | M |
     └───┴───┴───┴───┴───┴───┴───┘

Remember: this is codegolf so the the shortest answer wins!

Loovjo

Posted 2015-04-03T11:39:59.567

Reputation: 7 357

Can we assume that the input consists only of letters? Can we assume that they are all given in a single case? – Martin Ender – 2015-04-03T12:27:09.217

2I'm confused by this: "Two adjacent keys can max have 1.5 * the space of a key between them." Surely adjacent keys are actually adjacent, that is, they have no space between them, as in the linked puzzle? – Luke – 2015-04-03T12:51:47.547

How to take argument? STDIN? A function? – theonlygusti – 2015-04-03T16:58:43.007

Answers

9

Pyth, 66

?"Yes".Am>2sm^-.uk2Cm.Dx"qwertyuiopasdfghjkl*zxcvbnm"b9.5dC,ztz"No

Try it here.

I was surprised to learn Pyth doesn't have a hypotenuse function, so this will likely be beat by a different language. I'll propose a hypotenuse function to Pyth, so this atrocity won't happen in the future.

Explanation

I transform the keyboard into this:

┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
| Q | W | E | R | T | Y | U | I | O | P |
└─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┐
  | A | S | D | F | G | H | J | K | L | * |
  └─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴───┘
    | Z | X | C | V | B | N | M |
    └───┴───┴───┴───┴───┴───┴───┘

Which I then encode as "qwertyuiopasdfghjkl*zxcvbnm". Then I used divmod with modulo 9.5 to figure out the 2D coordinates of every key. Then I compute distances between consecutive keys, and check if the squared distance < 2.

orlp

Posted 2015-04-03T11:39:59.567

Reputation: 37 067

3

CJam, 83 75 74 bytes

l_1>]z["qwertyuiop asdfghjkl  zxcvbnm "[__B>]z+s_W%+_]zsf{\#)}:*"Yes""No"?

Try it online.

Explanation

The general approach is to produce a big adjacency string containing every pair of adjacent keyboard characters and then check that every pair of adjacent input characters is contained in that string.

I'm quite happy with how I managed to build the adjacency string, which uses very simple and compact logic.

l_1>]z          "Read a line of input and create a list of every pair of
                 adjacent input characters. There will be a trailing element
                 of just the final character, but that's okay since any single
                 lowercase letter can be found in the adjacency string.";
["qwertyuiop asdfghjkl  zxcvbnm "
              "^ Create the in-row forward adjacency string.";
[__B>]z         "Create the alternating-row forward adjacency string by
                 interleaving the in-row string with a substring of itself
                 starting with the middle row letters:
                   'q w e r t y u i o p   a s d f g h j k l  zxcvbnm '
                 + ' a s d f g h j k l     z x c v b n m  '[no interleave here]
                 -----------------------------------------------------
                   'qawsedrftgyhujikolp   azsxdcfvgbhnjmk l  zxcvbnm '";
+s              "Append the alternating-row forward adjacency string to the
                 in-row forward adjacency string.";
_W%+            "Append the reverse of the forward adjacency string (the
                 backward adjacency string) to the forward adjacency string.";
_]zs            "Double every character in the adjacency string so every
                 character is adjacent to itself.";
f{\#)}          "Map each pair of input characters to its 1-indexed location in
                 the adjacency string (0 if not found).";
:*              "Calculate the product of each pair's location in the adjacency
                 string. This will be nonzero if and only if every pair of
                 input characters are in fact adjacent.";
"Yes""No"?      "If the product is nonzero, produce 'Yes'; otherwise, produce
                 'No'.";
                "Implicitly print the result.";

Runer112

Posted 2015-04-03T11:39:59.567

Reputation: 3 636

That's it, I'm learning CJam. – Soham Chowdhury – 2015-04-04T03:17:33.537

@octatoan Looks like we'd both be better off learning Pyth, though. :P – Runer112 – 2015-04-04T11:26:57.090

Haha, maybe in this case, yes. – Soham Chowdhury – 2015-04-05T04:47:45.490

2

J, 77 bytes

No`Yes{::~[:*/2>+/"1@(2|@-/\3(|,.<.@%~+-:@|)'qazwsxedcrfvtgbyhnujmikXolX'i.])

Usage:

   f=.No`Yes{::~[:*/2>+/"1@(2|@-/\3(|,.<.@%~+-:@|)'qazwsxedcrfvtgbyhnujmikXolX'i.])

   f 'redresser'
Yes
   f 'qwergy'
No
   f 'ppcg'
No

Method:

For every input letter I generate it's 2D coordinate (similar to the image in the question) based on it's index in the string 'qazwsxedcrfvtgbyhnujmikXolX'. For every pair of letters in the input I check if their coordinates' Manhattan-distance is smaller than 2. If all are, I output Yes, No otherwise (by abusing the ` operator).

Try it online here.

randomra

Posted 2015-04-03T11:39:59.567

Reputation: 19 909

You forgot the letter p. – mbomb007 – 2015-04-03T21:17:06.567

@mbomb007 For none-found characters the i. operator returns the index of the last element + 1 so I can save 1 byte by not writing out p and still get it's correct index. – randomra – 2015-04-03T21:21:16.233

1

CJam, 75

r(1$+]z[1AB]"qwertyuiop asdfghjkl  zxcvbnm"f/:zSff+s_W%+f{\_|#}W&"No""Yes"?

Try it here (Firefox here).

Overlooked the Yes/No part... Fixed.

jimmy23013

Posted 2015-04-03T11:39:59.567

Reputation: 34 042