# Pickleball Doubles Scoring

Pickleball doubles is a game where only the serving side can score. The server calls the score as a triple of numbers, the serving side's score, the receiving side's score, and $$\1\$$ or $$\2\$$ to indicate whether the server is the first or second of their side to serve. If the server's side wins a point, their score is incremented and the same player serves again. If the receiving side wins a point, no score is incremented but the serve transfers to the other player if the past server was the first or goes to the receiving side if the past server was the second of their team to serve. To even things out, the first serve is at $$\0,0,2\$$ so the serving side gets only one set of serves. Game is the first side to $$\11\$$ but the team must be leading by $$\2\$$ to win. There is a special state END where the game is over which is indicated here by $$\0,0,0\$$.

Write a routine that determines whether one score call can follow another. You will be given two lists of three numbers, which will be integers in the range $$\0-30\$$. The first list will be the score called before one serve, the second will be the score called before the next serve. You must return a truthy value if the second call can follow the first and a falsey value if the second call cannot follow the first.

If the first call is $$\a,b,1\$$ and the server's side wins the next call would be $$\a+1,b,1\$$ unless the server's side wins the game, which is when $$\a \ge 11\$$ and $$\a \gt b+1\$$. In that case the next call is END. If the first call is $$\a,b,1\$$ and the receiver's side wins the next call is $$\a,b,2\$$. If the first call is $$\a,b,2\$$ and the server's side wins the next call is $$\a+1,b,2\$$ unless the server's side wins the game, which is when $$\a \ge 11\$$ and $$\a \gt b+1\$$. In that case the next call is END. If the first call is $$\a,b,2\$$ and the receiver's side wins the next call is $$\b,a,1\$$. If the first call is END (the start of a game) the next call is $$\0,0,2\$$. If either call is not a legal call in any game you must return a falsey answer.

This code golf, so the usual rules apply. You may take your input and provide output in any convenient format.

## Test cases:

Input               Output
==============================
[0,0,0] [0,0,2]     True
[0,0,0] [0,0,1]     False
[0,0,0] [1,0,2]     False
[0,0,2] [1,0,2]     True
[0,0,2] [1,0,1]     False
[0,0,2] [0,1,2]     False
[0,0,2] [0,0,2]     False
[0,0,2] [0,0,1]     True
[3,4,1] [3,4,2]     True
[3,4,1] [4,4,1]     True
[3,4,2] [4,4,2]     True
[3,4,2] [4,3,1]     True
[3,4,2] [4,3,2]     False
[3,4,3] [4,4,3]     False
[3,4,1] [4,4,2]     False
[3,4,1] [4,3,2]     False
[10,3,1] [0,0,0]    True
[10,3,1] [10,3,2]   True
[10,3,2] [3,10,1]   True
[10,3,2] [3,10,2]   False
[10,10,1] [0,0,0]   False
[10,10,1] [11,10,1] True
[10,10,1] [10,10,2] True
[11,10,2] [10,11,1] True
[11,10,1] [11,10,2] True
[10,11,2] [11,11,2] True
[10,11,1] [0,0,0]   False
[18,18,1] [19,18,1] True
[19,18,1] [0,0,0]   True
[19,18,2] [18,19,1] True
[12,8,1]  [12,8,2]  False
[12,8,2]  [8,12,1]  False
[11,10,1] [12,10,1] False
[8,12,1]  [8,12,2]  False

• Nice challenge! [3,4,3] [4,4,3]  feels like an anomaly because the inputs are impossible for any game, not merely because they aren't adjacent. I personally think general input validation makes the challenge less interesting, but if it is a requirement you should specify exactly what ranges the inputs can take? Could there be negative numbers? Fractions? May 31 '21 at 18:35
• Thanks for using the sandbox, but next time you should probably leave your post there for a bit longer to gather feedback - at least 3 days I'd say. May 31 '21 at 18:46
• @pxeger: makes sense. May 31 '21 at 19:25
• Suggested test case: [11,10,1] [12,10,1] Jun 1 '21 at 15:21
• Also [8,12,1] [8,12,2]. Three of the four current answers fail to notice when the receiving side has already won. Jun 1 '21 at 15:29

# J, 87 84 95 92 91 95 bytes

e.(-.@w*]-:]**@{:+2<{:)#([:(*1-w=.((10<>.)*1<|@-)/@}:)]+#:@4),:(2={:){(+0 0 1*2^0={:),:1:2}2&A.


Try it online!

+11 thanks to Arnauld finding a case I'd missed in input validation, which was not covered by the original test cases

## the idea

• Generate all possible successors of the first list.
• Check if the second list is a member of those.
• To handle input validation, null out the successor list when the input is invalid.

## J details

• (2={:){(+0 0 1*2^0={:),:1:2}2&A. - Generate the "server lost" case:
• 1:2}2&A. - Sub-case 1: Serve changes. Swap elements 1 and 2 2&A. and reset the final element to 1 1:2}.
• (+0 0 1*2^0={:) - Sub-case 2: Serve increments. Add either 0 0 1, or, if the final element is 0 0={:, add 0 0 2.
• (2={:) - Choose sub-case 1 if the final element is 2, and sub-case 2 otherwise.
• ([:(*1-w=.10<{.*1<-/@}:)]+#:@4) - Generate the "server won" case:
• ]+#:@4) - Add 1 0 0 (4 in binary) to the input.
• Next, we'll transform the list to 0 0 0 if the game is over, and as a side effect store the "is game over?" function in w, so we can re-use it later for input validation.
• w=.((10<>.)*1<|@-)/@}:) - Check if this game is over: Is the absolute difference between the first two elements |@- greater than 1 1< and is * either element greater than 10 10<>.?
• *1- - Multiply the input by the inversion of that, so nothing happens when we haven't won, and the input becomes 0 0 0 when we have.
• (-.@w*]-:]**@{:+2<{:) Is the input valid?
• -.@w* The input is not a win and...
• ]-:]**@{:+2<{:) The input matches ]-: the input multiplied by the sign of the last element ]**@{: plus 1 more if the last element is greater than 2 2<{:. This means it will only be valid if it is 0 0 0 or if the last element is 1 or 2, and the game is not already won.
• The validation will now be 0 or 1.
• # Copy our successor list that many times, leaving it unchanged when the input is valid, or nulling it out when it's invalid. Since the second input list will never be an element of the empty list, our overall result (see next step) will always be 0 if the input is invalid.
• e. Is the second input list (taken as the left arg) an element of the possible successors? This is our final answer.
• I think this should be falsy. Jun 1 '21 at 0:14
• @Arnauld Thanks. The input validation made the challenge less fun :(. Jun 1 '21 at 0:38
• Yeah, that's pretty boring. And moreover the test cases do not cover all the things that can go wrong. You may want to check the last five ones I've added to my answer. Jun 1 '21 at 0:44
• Thanks. The other 4 are ok but I made a typo and am actually still failing the first one you linked. Fixing it now. EDIT: Fixed. Jun 1 '21 at 0:49

# JavaScript (ES6), 125 bytes

Returns $$\0\$$ or $$\1\$$.

([a,b,c],B,g=x=>a<11|a<b+2&&b<11|b<a+2&&c<3&x+''==B)=>c?(a>9&a>b?g0,0,0:g([a+1,b,c]))|g(c-1?[b,a,1]:[a,b,2]):!a&!b&g0,0,2


Try it online!

• Wow, only 22 bytes longer than the J answer... Jun 1 '21 at 10:36
• This gives the wrong answer for [11,10,1] [12,10,1] and [8,12,1] [8,12,2] Jun 1 '21 at 15:26
• @Nitrodon Thanks for reporting this. I think I've fixed the 1st one. But I'm not even sure how the 2nd one is supposed to be interpreted. Waiting for more official test cases from the OP. Jun 1 '21 at 15:39
• @Arnauld I just fixed mine too. My interpretation is that the 2nd example should be false since it represents invalid input (the game would have already finished). Jun 1 '21 at 15:47
• @Jonah Now fixed ... hopefully. Jun 1 '21 at 20:19

# Retina 0.8.2, 166 bytes

\d+
$* A^(1*),(?=11\1)1{11}|^(?=1{11})(1+)11+,\2,|111; ^(,,;,,11|(1{10},1{0,9}|1(1{10,}),\3),1+;,,|((1{0,9},1*|(1+),1*\6),1+);1\4|(.*),1;\7,11|(1*),(1*),11;\9,\8,1)$


Try it online! Link includes test cases. Explanation:

\d+
$*  Convert to unary. A^(1*),(?=11\1)1{11}|^(?=1{11})(1+)11+,\2,|111;  Remove some illegal starting calls, specifically: • ^(1*),(?=11\1)1{11} receiving side has already won • ^(?=1{11})(1+)11+,\2, serving side has already won • 111; illegal service number. ^(,,;,,11|(1{10},1{0,9}|1(1{10,}),\3),1+;,,|((1{0,9},1*|(1+),1*\6),1+);1\4|(.*),1;\7,11|(1*),(1*),11;\9,\8,1)$


Check whether any legal call remains, specifically:

• ,,;,,11 - Check for the start of a new game.

• (1{10},1{0,9}|1(1{10,}),\3),1+;,, Check for a win.

• ((1{0,9},1*|(1+),1*\6),1+);1\4 Check for a point that's not a win.

• (.*),1;\7,11 - Check for a second serve.

• (1*),(1*),11;\9,\8,1 - Check for a change of side.

I would have liked to use a conditional lookahead to determine whether the serving side is about to win or not and require that the second call matches ;,, if they are or that the serving side simply scores a point if not, but for some reason my conditional lookahead started failing when I changed the expression for what to match when the conditional lookahead fails, which seems buggy.

# Python 2, 135 bytes

Takes all six values as seperate arguments, returns a boolean.

lambda a,b,s,A,B,S:(9<a-1>b)|(9<A-1>B)<any([a|b|s|A|B<1<S<3,(a,b)==(B,A)[::s-2|1]!=S==3-s<3,3>s>0<[(a+1,S,b)==(A,s,B),A|B|S<1][9<a>b]])


Try it online!

9<a-1>b: serving side has won (invalid)
9<A-1>B: receiving side has won (invalid)
a|b|s|A|B<1<S<3: END -> START
(a,b)==(B,A)[::s-2|1]!=S==3-s<3: receiving side scores point
3>s>0<[(a+1,S,b)==(A,s,B),A|B|S<1][9<a>b]]: serving side scores