Valid Badminton Score?

Python 2, 97 95 75 72 71 70 69 64 55 54 52 51 50 48 bytes

lambda a,b:(b-61<~a<a>b/22*b-3)*~(19<b-(b<30)>a)

Try it online!

Takes input as pre-ordered a,b.

Returns -2, -1, 0 for ended, in play, invalid.

-1 byte, thanks to Kevin Cruijssen


Left part (b-61<~a<a>b/22*b-3) is a validity-check, and right part (19<b-(b<30)>a) is a check for game ended.


Python 2, 47 bytes

lambda a,b:[61>60-a>b<3+max(19,a)for b in-~b,b]

Try it online!

Outputs a list of two Booleans. Thanks to TFeld for writing a test suite in their answer that made it easy to check my solution.

ended: [False, True]
going: [True, True]
invalid: [False, False]

The key insight is that a valid score ends the game exactly if increasing the higher value b makes the score invalid. So, we just code up the validity condition, and check it for (a,b+1) in addition to (a,b) to see if the game has ended.

Validity is checked via three conditions that are chained together:

  • b<3+max(19,a): Checks that the higher score b isn't past winning, with either b<=21 or b<=a+2 (win by two)
  • 60-a>b: Equivalent to a+b<=59, ensuring the score isn't above (29,30)
  • 61>60-a: Equivalent to a>=0, ensures the lower score is non-negative

Python 2, 44 bytes

lambda a,b:[b-61<~a<a>b/22*b-3for b in-~b,b]

Try it online!

An improved validity check by TFeld saves 3 bytes. The main idea is to branch on "overtime" b>21 with b/22*b which effectively sets below-21 scores to zero, whereas I'd branched on a>19 with the longer max(19,a).


Python 2, 43 bytes

lambda a,b:a>>99|cmp(2+max(19,a)%30-a/29,b)

Try it online!

Outputs:

ended: 0
going: -1
invalid: 1

Assumes that the inputs are not below \$-2^{99}\$.


JavaScript (ES6),  55 53  48 bytes

Thanks to @KevinCruijssen for noticing that I was not fully assuming \$a\le b\$ (saving 5 bytes)

Takes input as (a)(b) with \$a\le b\$. Returns \$0\$ (valid), \$1\$ (ended) or \$2\$ (invalid).

a=>b=>a<0|a>29|b>30|b>21&b-a>2?2:b>20&b-a>1|b>29

Try it online!