TransWikia.com

Are These Scores Possible?

Code Golf Asked on October 27, 2021

Background

In the sport of Table Tennis (aka Ping-Pong or Whiff Whaff), two opponents play a sequence of rounds, where each round consists of players hitting a ball back and forth until one player (may or may not be the server) gains a point.

Table Tennis has some official rules that make for a good game, but we will use a different set of rules for a better challenge.

The modified rules are as follows:

  1. The score is announced directly before each serve as a pair (current server's score, other player's score).
  2. Person A serves for 5 points, then Person B serves for 5 points, then back to A. Hence, A serves whenever the total score A+B is 0-4 mod 10.
  3. After each serve, either A scores a point or B scores a point. A and B both start with 0 points.
  4. For simplicity, games never end.

Following is an example game:

(A starts serving, so the scores are read as (A,B))
0,0; A scores a point
1,0; B scores a point
1,1; A scores a point
2,1; A scores a point
3,1; A scores a point
(B is now serving, so the scores are read as (B,A))
1,4; A scores a point
1,5; B scores a point
2,5; B scores a point
3,5; B scores a point
4,5; B scores a point
(A is now serving, so the scores are read as (A,B))
5,5; B scores a point 
5,6 …
(game continues)

Task

Given a pair of unique score readouts, determine if they can be announced in the same game.

Your program/function may take input as any reasonable way equivalent to an ordered pair of numbers.

The output can follow your language’s convention for truthy/falsey or use any two distinct values to represent true/false.

Examples

Given (4,5), (1,4), the output should be truthy. The example game is one where this score set occurs.

Given (4,2), (3,5), the output should be falsey. They occur at point totals 6 and 8 respectively, so B is serving in both readouts, so both are reported as (B,A). It is impossible for B‘s score to decrease from 4 to 3 while A‘s score increases from 2 to 5, so this situation is impossible.

Given (3,1), (1,5), the output should be truthy. (3,1) is reported as (A,B), while (1,5) is reported as (B,A), so the game can transition from (3,1) to (1,5) if A scores 2 points.

Test Cases

Truthy:
(4,5), (1,4)
(3,1), (1,5)
(0,0), (0,1)
(0,0), (45,54)
(6,9), (11,9)

Falsey:
(12,5), (11,6)
(4,2), (3,5)
(3,3), (5,2)
(2,1), (4,1)
(17,29), (17,24)

12 Answers

Javascript , 70 bytes

(a,b,c,d)=>(~~((a+b)%10/5)==~~((c+d)%10/5)?(c-a)*(d-b):(d-a)*(c-b))>=0

Input: is 4 numbers representing two pairs in order.

Output: true/false

Try it online

Answered by SomoKRoceS on October 27, 2021

Jelly, 26 23 20 bytes

Thanks to fireflame241, I was able to shave off a few bytes already.

S€%⁵:5E¬µ³U⁸¡Ðo_/ṠIỊ

Original:

S€%ȷ1<5E¬©µ³Ṛ€®¡Ðo_/ṠIA=2¬

Try it online!

Here's my Jelly solution. It's my first Jelly program, so it can definitely be improved a lot, especially at the part where I use the register. I don't quite understand how argument flow works yet.

Here's how it works:

S€%⁵:5E¬µ³U⁸¡Ðo_/ṠIỊ - Example input:                     [[4,5],[1,4]]

S€%⁵<5               - Figure out who is serving each time
S€                   - Calculates sum of each inner list: [9, 5]
  %⁵                 - Modulo 10:                         [9, 5]
    <5               - Vectorized less than 5?:           [0, 0]

      E¬µ³U⁸¡Ð       - If server is different, reverse list 1
      E              - Checks if all elements are equal:  1
       ¬             - Logical not:                       0
        µ            - Start a monadic chain
         ³           - Get first input:                   [[4,5],[1,4]]
          U          - Reverse order of inner lists
             Ðo      - At odd indices (ie. the first list)
           ⁸¡        - {left argument, ie. 0} times:      [[4,5],[1,4]]

               _/ṠIỊ - Calculate difference in score per player. 
                       If one decreased and the other increased,
                       it's not a possible score
               _/    - Vectorized subtract:               [3, 1]
                 Ṡ   - Get sign:                          [1, 1]
                  I  - Difference between elements:       0
                   Ị - abs(x) <= 1:                       0
```

Answered by pslessard on October 27, 2021

Jelly, 11 bytes

ṚS:5Ɗ¡€Ṣ>/E

A monadic Link accepting a list of the to pairs which yields a 1 if valid, or a 0 if not.

Try it online! Or see the test-suite.

How?

ṚS:5Ɗ¡€Ṣ>/E - Link: list, S            e.g. [[17,29],[17,24]]
      €     - for each (pair in S):
     ¡      -   repeat...
Ṛ           -   ...what: reverse
    Ɗ       -   ...number of times: last three links as a monad:
 S          -       sum                       46     41
   5        -       five                       5      5
  :         -       integer division           9      8  -> [[29,17],[17,24]]
       Ṣ    - sorted                                        [[17,24],[29,17]]
         /  - reduce by:
        >   -   is greater than?       ([17>?29, 24>?17])   [0,1]
          E - all equal?                                    0

Answered by Jonathan Allan on October 27, 2021

C (gcc), 58 bytes

f(a,b,A,B){a=(A-a)*(B-b)<(a-b)*(A-B)*((a+b)/5+(A+B)/5&1);}

Try it online!

Port of xnor's Python answer.
Outputs $0$ if they can be announced in the same game and $1$ otherwise.

Answered by Noodle9 on October 27, 2021

Java 8, 116 63 54 bytes

(a,b,A,B)->(A-a)*(B-b)<((a+b)/5+(A+B)/5)%2*(a-b)*(A-B)

Whopping -53 bytes thanks to @NahuelFouilleul as a port from his Perl answer, so make sure to upvote him!!
Additional -9 bytes by porting @xnor's first Python answer.

Takes the inputs as four loose integers.
Outputs false for truthy; and true for falsey.

Try it online.

Explanation:

(a,b,A,B)->   // Method with four integer parameters and boolean return-type
  (A-a)*(B-b) //   Get the difference between the values of the two pairs,
              //   and take the product of those two differences
  <           //  And check that this is smaller than:
   ((a+b)     //     The sum of the first pair
     /5       //     integer-divided by 5
    +         //    Plus:
     (A+B)/5) //     The sum of the second pair, integer-divided by 5 as well
   %2         //   Check if these two added together are odd (1 if odd; 0 if even)
   *(a-b)     //   Multiplied by the reduced by subtraction of the first pair
   *(A-B)     //   Multiplied by the reduced by subtraction of the second pair

Answered by Kevin Cruijssen on October 27, 2021

R, 65 59 57 bytes

(or 56 bytes by outputting FALSE for Truthy and TRUE for Falsey)

function(a,b)prod(a-b[(0:1+sum(a)/5-sum(b)%/%5)%%2+1])>=0

Try it online!

Edit: -6 bytes by flipping b elements using indexing, instead of using if-else

Edit 2: -2 bytes by not bothering to do integer division for both a and b, since indexing will only use the integer part anyway.

Commented version:

validscores=function(a,b){
    b=b[                    # Select elements from b
    (0:1+                   # with index of: zero or 1, plus 
    sum(a)%/%5              # changes of serve until first score
    -sum(b)%/%5)            # minus changes of serve until second score
    %%2+1]                  # modulo 2, plus 1.
                            # This will flip the elements of b if there
                            # have been an odd number of changes of serve, 
                            # & otherwise leave b as it was).
    prod(a-b)>=0            # a-b now gives changes in each players points:
}                           # so if the second score came after the first, 
                            # both changes must be >=0, otherwise both must be <=0.
                            # So, either way, the product must be >=0

Answered by Dominic van Essen on October 27, 2021

Python 2, 58 bytes

lambda a,b,A,B:(A-a)*(B-b)<(a-b)*(A-B)*((a+b)/5+(A+B)/5&1)

Try it online!

Outputs True/False reversed

59 bytes

lambda a,b,A,B:A*B+a*(b-A-B)<(b-a)*[A,B][(a+b)/5+(A+B)/5&1]

Try it online!

59 bytes

lambda a,b,A,B:A*B+b*a<[A*b+B*a,a*A+b*B][(a+b)/5+(A+B)/5&1]

Try it online!

62 bytes

a,b,A,B=input()
if(a+b)/5+(A+B)/5&1:a,b=b,a
print(A-a)*(B-b)<0

Try it online!

Answered by xnor on October 27, 2021

Charcoal, 30 bytes

UMθEι§ι⁺÷Σι⁵쬛⁰ΠE²⁻§§θ⁰駧θ¹ι

Try it online! Link is to verbose version of code. Takes a pair of pairs of integers and outputs a Charcoal boolean, i.e. - for possible, nothing for impossible. Explanation:

UMθEι§ι⁺÷Σι⁵μ

Cyclically rotate each pair by one fifth of its sum.

¬›⁰ΠE²⁻§§θ⁰駧θ¹ι

Check that the product of the differences between the pairs is not negative.

Answered by Neil on October 27, 2021

Perl 5 -p -Minteger, 77, 73 bytes

/ (.*) (.*) /;$_=($`-$2)*($1-$')>=(($`+$1)/5+($2+$')/5)%2*($`-$1)*($2-$')

Try it online!

2 bytes saved using xnor approach, and 2 other bytes using integer division, explanation is (renaming: $` -> a, $1 -> b, $2 -> c, $' -> d), first answer was:

  • (a-B)(b-A)>=0 if scores are in reversed order ((a+b)/5%2^(A+B)/5%2==1)
  • (a-A)(b-B)>=0 otherwise

as (a-B)(b-A)>=0 is equivalent to (a-A)(b-B)>=(a-b)(A-B)

  • (a-B)*(b-A)>=0 <=> ab+AB-aA-bB>=0 <=> ab+AB-aB-Ab>=aA+bB-aB-bA <=> (a-A)(b-B)>=(a-b)(A-B)

answer can be

  • (a-A)(b-B)>=0 if (a+b)/5%2^(A+B)/5%2==1
  • (a-A)(b-B)>=(a-b)(A-B) if (a+b)/5%2^(A+B)/5%2==0

or

  • (a-A)(b-B)>=(a-b)(A-B)*((a+b)/5%2^(A+B)/5%2)

or with integer division

  • (a-A)(b-B)>=(a-b)(A-B)*((a+b)/5+(A+B)/5)%2

Answered by Nahuel Fouilleul on October 27, 2021

APL (Dyalog) 18.0, 19 18 17 bytes

0≤×.-⍥(⌊⍤+.÷∘5⌽⊢)

Try it online!

This makes use of the new operators over () and atop (), both of which are very good for golfing. TIO is still on 17.0, so this doesn't work, but I've tested it locally for the given test cases. Takes the two inputs as the left and right parameters.

Answered by Jo King on October 27, 2021

APL (Dyalog Extended), 15 bytes

≡⍥⍋∘⌽⍨⌊⍤+.÷∘5⌽⊢

Try it online!

≤⌿⍣2⍤∧⌊⍤+.÷∘5⌽⊢

Try it online!

It took a long time to shave one byte from 16. You can see a long history of alternative solutions in the TIO link.

Both solutions take a 2×2 matrix as single input, where each row is a score readout. The first one would also work in Dyalog APL 18.0, since it only uses 17.x features plus ⍥⍤.

How it works

≡⍥⍋∘⌽⍨⌊⍤+.÷∘5⌽⊢  ⍝ Input: 2×2 matrix
      ⌊⍤+.÷∘5    ⍝ For each row, divide each number by 5, sum, then floor
             ⌽⊢  ⍝ Rotate each row by that amount
   ∘⌽⍨           ⍝ Check for the above and its horizontal reverse...
≡⍥⍋              ⍝   Is the sorting order equal?

≤⌿⍣2⍤∧⌊⍤+.÷∘5⌽⊢  ⍝ Alternative solution
      ⌊⍤+.÷∘5⌽⊢  ⍝ Same as above up to here
    ⍤∧           ⍝ Ascending sort the rows
≤⌿⍣2             ⍝ 1st axis reduce by ≤ twice;
                 ⍝ Since the rows are sorted, first ≤⌿ gives [1 x]
                 ⍝ where x is 1 iff the 2nd column is also increasing
                 ⍝ Then the second ≤⌿ tests if x is 1

Answered by Bubbler on October 27, 2021

05AB1E, 15 14 12 bytes

εDO5÷FR]`-Pd

-2 bytes thanks to @Neil.

Try it online or verify all test cases.

Explanation:

ε        # Map both pairs in the (implicit) input to:
 D       #  Duplicate the pair
  O      #  Pop this duplicate and calculate its sum
   5÷    #  Integer-divide it by 5
     F   #  Loop that many times:
      R  #   Reverse the pair every iteration
         #   (the pair is reversed for odd sums; and remains unchanged for even sums)
]        # Close both the loop and map
         # (all pairs are now in the order [A,B])
 `       # Pop and push both pairs separated to the stack
  -      # Subtract the values of the pairs from one another at the same indices
   P     # Take the product of those two values
    d    # And check that it's non-negative / >=0 (thus no score is decreasing)
         # (after which the result is output implicitly)

Answered by Kevin Cruijssen on October 27, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP