9
\$\begingroup\$

Keyboard Ping Pong

(This question was inspired by this post.)

Challenge

Given a string of letters, determine if the word "ping-pongs" across the keyboard. (Letters alternating between sides of the keyboard)

Use any established Latin-script keyboard layout that you would like (QWERTY, AZERTY, etc.) but please specify your choice in your answer.

Here is a graphic of the ping pong sides with QWERTY layout. The left hand side consists of the leftmost 5 letters, with the right hand side consisting of the remaining letters.


Test Cases (QWERTY)

skepticism - true
ENDOWMENT - true
quantity - true
dispel - true
kayaks - true
a - true
aa - false
test - false
WRONG - false
thiswillfail - false
ε - false

Comments:

  1. Strings of length 1 should return true. Represents an ace!
  2. Strings of length 0 should return false. A point would not be scored in a real ping pong game.
  3. Should be case-insensitive

This question is tagged , so the shortest answer in bytes wins!

Greg Martin
16.7k4 gold badges23 silver badges73 bronze badges
asked Jul 8, 2024 at 15:17
\$\endgroup\$
16
  • 10
    \$\begingroup\$ It seems questionable that the empty string is false. See vacuous truth. \$\endgroup\$ Commented Jul 8, 2024 at 15:43
  • 8
    \$\begingroup\$ I think this question would be improved by excluding the empty string as a possible input, and fixing the keyboard layout to QWERTY. "Established" is vague and "etc" is even vaguer — as it stands, it's simply unclear which keyboard layouts make for valid answers. Questions are ideally self-contained, so I suggest you include the letters for half of every acceptable layout as a string instead of linking to a graphic. \$\endgroup\$ Commented Jul 8, 2024 at 22:12
  • 7
    \$\begingroup\$ Maybe you can phrase the problem like: "Given a nonempty string of ASCII letters, decide if it alternates between letters among QWERTASDFGZXCVB and other letters, ignoring case." \$\endgroup\$ Commented Jul 8, 2024 at 22:18
  • 2
    \$\begingroup\$ I'm voting to close this because this have multiple issues: established keyboard layout is not well-defined, and it did not mention what output formats are acceptable. I'm happy to take it back after it is fixed. \$\endgroup\$ Commented Jul 9, 2024 at 12:54
  • 2
    \$\begingroup\$ Do you want us to look through a list of keyboard layouts to find the most favorable one for the challenge? This sounds extremely tedious, barely related to code golfing, and ambiguous enough to inevitably lead to disagreement on what's an established layout. \$\endgroup\$ Commented Jul 10, 2024 at 9:04

12 Answers 12

12
\$\begingroup\$

Perl 5 -p, 31 bytes

$_&&=!/[h-puy]{2}|[^h-puy]{2}/i

Try it online!

Assumes QWERTY layout.

answered Jul 8, 2024 at 16:29
\$\endgroup\$
7
\$\begingroup\$

Python, (削除) 69 (削除ここまで) (削除) 62 (削除ここまで) (削除) 60 (削除ここまで) (削除) 58 (削除ここまで) (削除) 55 (削除ここまで) 54 bytes

-7 bytes thanks to @xnor. I independently arrived at a similar solution (only the first -4 though) since I didn't notice their comment for a while.
-1 byte thanks to @Albert.Lang

Takes input as a bytestring

lambda x,n=35782400:len({(n:=~n)>>j%32&1for j in x})%2

Attempt This Online!

answered Jul 8, 2024 at 17:06
\$\endgroup\$
5
  • 1
    \$\begingroup\$ -4 bytes using the walrus \$\endgroup\$ Commented Jul 9, 2024 at 9:27
  • 1
    \$\begingroup\$ 55 bytes \$\endgroup\$ Commented Jul 9, 2024 at 9:38
  • 1
    \$\begingroup\$ -1:lambda x,n=35782400:len({(n:=~n)>>j%32&1for j in x})%2 \$\endgroup\$ Commented Jul 10, 2024 at 5:28
  • \$\begingroup\$ For comparison, a variant approach also gets me 54 bytes. \$\endgroup\$ Commented Jul 10, 2024 at 17:46
  • \$\begingroup\$ Would be 51 bytes if not for the empty string special case \$\endgroup\$ Commented Jul 10, 2024 at 17:49
5
\$\begingroup\$

sed -r, 30 bytes

/[^h-puy]{2}|[h-puy]{2}|^$/IQ1

Try it online!

nearly a port of @Xcali's answer. I originally had my own but my regex was worse. errors with exit code of 1 if it's invalid, exits normally if it's ping pong

I just saw that we can use any keyboard we want, so here's my keyboard, colemak:

sed, 30 bytes

/[^eh-uy]{2}|[eh-uy]{2}|^$/IQ1

Try it online!

here's dvorak, the most popular alternate layout:

sed, 42 bytes

/[aeijkopquxy]{2}|[^aeijkopquxy]{2}|^$/IQ1

Try it online!

and here's workman, the third choice for weird people:

sed, 40 bytes

/[^efi-lnopuy]{2}|[efi-lnopuy]{2}|^$/IQ1

Try it online!

answered Jul 8, 2024 at 16:49
\$\endgroup\$
1
  • \$\begingroup\$ (if you were wondering, I did go through the rest of the keyboards on that wiki page, but none were as short as qwerty and colemak.) \$\endgroup\$ Commented Jul 8, 2024 at 17:18
4
\$\begingroup\$

Charcoal, 23 bytes

∧θNo...01⊕Lθ⭆θNo+⪫...h¦qωuy↧ι

Try it online! Link is to verbose version of code. Outputs a Charcoal boolean, i.e. - if the word is ping-pong, nothing if not. Explanation:

 θ Input word
∧ Logical And
 No Count of
 θ Input word
 ⭆ Map over characters and join
 No Count of
 ι Current letter
 ↧ Lowercased
 ...h q In range `h`...`q` (exclusive)
 ⪫ ω Joined
 + Concatenated with
 uy Literal string `uy`
 01 In literal string `01`
 ... Cyclically extended to length
 θ Input word
 L Length
 ⊕ Incremented
 Implicitly print
answered Jul 8, 2024 at 22:55
\$\endgroup\$
4
\$\begingroup\$

JavaScript (ES6), 51 bytes

Expects an array of characters. Returns 0 for "ping-pong" or 1 for "empty or not ping-pong".

a=>a<1|a.some(q=c=>q-(q=/[h-puy]/i.test(c)^(a^=1)))

Try it online!


JavaScript (ES6), 39 bytes

@Xcali used a much more straightforward solution which can be ported as follows. Expects a string and returns a Boolean value (false for "ping-pong").

s=>/^$|[h-puy]{2}|[^h-puy]{2}/i.test(s)

Try it online!

answered Jul 8, 2024 at 16:14
\$\endgroup\$
3
\$\begingroup\$

Python 3.8 (pre-release), (削除) 89 (削除ここまで) (削除) 83 (削除ここまで) 76 bytes

-6 bytes by walrusing 'yuiophjklnm'.
-7 bytes by Mukundan314.

lambda x:x and all((i in(r:='yuiophjklnm'))^(j in r)for i,j in zip(x,x[1:]))

Try it online!

answered Jul 8, 2024 at 16:09
\$\endgroup\$
1
  • \$\begingroup\$ -7 bytes \$\endgroup\$ Commented Jul 8, 2024 at 16:33
3
\$\begingroup\$

Google Sheets, 76 bytes

=SORT(AND(1=LEN(IFERROR(SPLIT(REGEXREPLACE(A2,"(?i)[h-puy]"," 0ドル ")," "))))) 

enter image description here

Google Sheets, 47 bytes

Using @Xcali's idea

=REGEXMATCH(A2,"(?i)[h-puy]{2}|[^h-puy]{2}|^$")

enter image description here

answered Jul 8, 2024 at 18:47
\$\endgroup\$
3
\$\begingroup\$

05AB1E, (削除) 20 (削除ここまで) 19 bytes

žV5δôøJIlδå€üαßIgΘM

Input as a list of characters.
Uses the QWERTY keyboard.

Try it online or verify all test cases.

Explanation:

žV # Push ["qwertyuiop","asdfghjkl","zxcvbnm"]
 δ # Map over each string:
 5 ô # Split it into parts of size 5
 ø # Zip/transpose; swapping rows/columns
 J # Join the inner lists together:
 # ["qwertasdfgzxcvb","yuiophjklnm"]
I # Push the input-list
 l # Lowercase each inner character
 δ # Double-vectorized over the two lists:
 å # Contains-check
 € # Map over each inner list:
 ü # For each overlapping pair in this list:
 α # Take the absolute difference of the pair
 ß # Pop and push the flattened minimum
 # (1 if all are truthy; 0 if any are falsey; "" if empty)
Ig # Push the length of the input-list
 Θ # Check whether this length is exactly 1
M # Push a copy of the largest value of the stack
 # (which is output implicitly as result)
answered Jul 9, 2024 at 8:02
\$\endgroup\$
2
\$\begingroup\$

Haskell, (削除) 70 (削除ここまで) 66 bytes

  • -4 bytes thanks to xnor
h=(`elem`"yuiophjklnm").toLower
f(x:y:z)=h x/=h y&&f(y:z)
f x=x>[]

Try it online!

  • First we map each letter to a boolean based on the hand (the helper function)
  • Then we assert the sequence is alternate
  • The base cases of 0 and 1 elements are handled by the last line
answered Jul 10, 2024 at 21:11
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Nice answer! It looks like you can save a few bytes by applying the helper function directly to the elements, and writing x>[] in the base case: Try it online! \$\endgroup\$ Commented Jul 11, 2024 at 4:22
1
\$\begingroup\$

Vyxal, 121 bitsv2 , 15.125 bytes

[⇩ƛk•5vẇ∑vFT;f ̄AI

Try it Online!

Bitstring:

0110100000110010000101110000101100010110000010110110100110101011010101011111000101101010010111000001110111100000010110110

Outputs a space for true, an empty string for false. The footer in the link converts the result to 0 or 1 for convenience. Uses the qwerty layout.

Explained

[⇩ƛk•5vẇ∑vFT;f ̄AI­⁡​‎‎⁡⁠⁡‏‏​⁡⁠⁡‌⁢​‎‏​⁢⁠⁡‌⁣​‎‏​⁢⁠⁡‌⁤​‎‎⁡⁠⁢‏⁠‎⁡⁠⁣‏‏​⁡⁠⁡‌⁢⁡​‎‎⁡⁠⁤‏⁠‎⁡⁠⁢⁡‏‏​⁡⁠⁡‌⁢⁢​‎‎⁡⁠⁢⁢‏⁠‎⁡⁠⁢⁣‏⁠‎⁡⁠⁢⁤‏‏​⁡⁠⁡‌⁢⁣​‎‎⁡⁠⁣⁡‏‏​⁡⁠⁡‌⁢⁤​‎‎⁡⁠⁣⁢‏⁠‎⁡⁠⁣⁣‏⁠‎⁡⁠⁣⁤‏‏​⁡⁠⁡‌⁣⁡​‎‎⁡⁠⁣⁢‏⁠‎⁡⁠⁣⁣‏‏​⁡⁠⁡‌⁣⁣​‎‎⁡⁠⁤⁢‏⁠‎⁡⁠⁤⁣‏‏​⁡⁠⁡‌⁣⁤​‎‏​⁢⁠⁡‌⁤⁡​‎‏​⁢⁠⁡‌⁤⁢​‎‎⁡⁠⁤⁤‏‏​⁡⁠⁡‌⁤⁣​‎‎⁡⁠⁢⁡⁡‏‏​⁡⁠⁡‌­
[ # ‎⁡Only execute the following if the input isn't the empty string.
# ‎⁢Why else do you think false is represented as the empty string? :p
# ‎⁣It was easier to special case it
 ⇩ƛ # ‎⁤To each character in the lowercased input:
 k• # ‎⁢⁡Push a list of each row of qwerty
 5vẇ # ‎⁢⁢Split each into [first 5 characters, rest]
 ∑ # ‎⁢⁣And fold the list by addition. This gives a list of [left keys, right keys]
 vFT # ‎⁢⁤Determine whether the character is a left or right key.
 vF # ‎⁣⁡ Filter out the key from each side
 f ̄ # ‎⁣⁣Flatten that and get the forward differences
# ‎⁣⁤This will be used to determine whether there's a pattern of left/right or right/left. 
# ‎⁤⁡A 0 in this list means that two characters in a row are from the same side. 
 A # ‎⁤⁢Check whether all numbers are non-0, as per the above explanation of why. This will return either 0 or 1
 I # ‎⁤⁣Push that many spaces. This is to be consistent with the empty string output. 
💎

Created with the help of Luminespire.

answered Jul 9, 2024 at 5:14
\$\endgroup\$
1
\$\begingroup\$

Jelly, 13 bytes

ŒlØqiþ§>5IẠ«L

A monadic Link that accepts a list of characters from A-Za-z and yields 1 if ping-pong or 0 otherwise.

Try it online! Or see the test-suite.

answered Jul 10, 2024 at 2:04
\$\endgroup\$
1
\$\begingroup\$

Nibbles, 23 nibbles (11.5 bytes)

`^,`'`=@=$`D2~ fe00f740

Attempt This Online!

Outputs 0 (falsy) if the input is a ping-pong string, or a nonzero value (truthy) if it isn't.

Can be adapted for various keyboard layouts by adjusting the 32-bit mask (here fe00f740 for left-hand keys on a QWERTY layout). This can't be shortened, even if all the left-hand keys are bunched together, as it needs to be 32 bits long to achieve case-insensitivity by modular indexing.

`^,`'`=@=$`D2~ fe00f740
 `=@ # split input into chunks of same 
 = # modular index of 
 $ # codepoint of each character
 # in 
 `D2 fe00f740 # binary digits of fe00f740
 # (1 for left-hand letters, 0 otherwise);
 `' # now transpose this
 , # and get the length
 # (0 if input was empty,
 # 1 if input was ping-pong string,
 # >1 if any adjacent input characters were typed with the same hand)
`^ ~ # and bitwise-xor it with 1
answered Jul 16, 2024 at 14:06
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.