13
\$\begingroup\$

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!

\$\endgroup\$
3
  • \$\begingroup\$ Can we assume that the input consists only of letters? Can we assume that they are all given in a single case? \$\endgroup\$ Apr 3, 2015 at 12:27
  • 2
    \$\begingroup\$ I'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? \$\endgroup\$
    – Luke
    Apr 3, 2015 at 12:51
  • \$\begingroup\$ How to take argument? STDIN? A function? \$\endgroup\$ Apr 3, 2015 at 16:58

4 Answers 4

9
\$\begingroup\$

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.

\$\endgroup\$
3
\$\begingroup\$

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.";
\$\endgroup\$
3
  • \$\begingroup\$ That's it, I'm learning CJam. \$\endgroup\$ Apr 4, 2015 at 3:17
  • \$\begingroup\$ @octatoan Looks like we'd both be better off learning Pyth, though. :P \$\endgroup\$
    – Runer112
    Apr 4, 2015 at 11:26
  • \$\begingroup\$ Haha, maybe in this case, yes. \$\endgroup\$ Apr 5, 2015 at 4:47
2
\$\begingroup\$

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.

\$\endgroup\$
2
  • \$\begingroup\$ You forgot the letter p. \$\endgroup\$
    – mbomb007
    Apr 3, 2015 at 21:17
  • \$\begingroup\$ @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. \$\endgroup\$
    – randomra
    Apr 3, 2015 at 21:21
1
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.