g | x | w | all
Bytes Lang Time Link
nanNibbles240716T140628ZDominic
066Haskell240710T211107ZDPD-
054Python240708T170630ZMukundan
013Jelly240710T020442ZJonathan
01905AB1E240709T080208ZKevin Cr
nanVyxal240709T051457Zlyxal
051JavaScript ES6240708T161437ZArnauld
023Charcoal240708T225518ZNeil
076Google Sheets240708T184726Zz..
076Python 3.8 prerelease240708T160948Zsquarero
030sed r240708T164928Zguest430
031Perl 5 p240708T162921ZXcali

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

Haskell, 70 66 bytes

h=(`elem`"yuiophjklnm").toLower
f(x:y:z)=h x/=h y&&f(y:z)
f x=x>[]

Try it online!

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!

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.

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)

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.

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!

Charcoal, 23 bytes

∧θ№…01⊕Lθ⭆θ№⁺⪫…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
  №                     Count of
          θ             Input word
         ⭆              Map over characters and join
           №            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

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

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!

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!

Perl 5 -p, 31 bytes

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

Try it online!

Assumes QWERTY layout.