51
\$\begingroup\$

One of my favorite memes is the bouncing DVD logo. Yet silly but extremely satisfying, a DVD logo keeps bouncing on a screen and if you ever happened to watch this screensaver, you were most likely anxiously waiting for the logo to exactly hit the corner.

enter image description here

I know part of the fun is the waiting, but let's try to predict when the DVD logo will hit the corner of the screen.

Task

Given the dimensions and initial coordinates of the logo and the size of the grid, calculate when the logo will hit any corner for the first time.

Specs

  • In this challenge, the logo will be represented by a rectangle and the screen by a grid. The grid will always be bigger than the logo.
  • The logo's starting movement will be southeast. The logo only moves diagonally. Horizontal and vertical speeds are the same and stays the same.
  • The unit of time for this challenge is represented as a movement of 1 grid square in a certain direction.
  • If the logo already starts in a corner, the expected answer is 0 (the logo is already touching a corner).
  • The initial coordinates of the logo represents the top-left corner of the logo.
  • The starting logo position will not extend outside the grid.
  • You can assume for this challenge that the logo will eventually hit a corner.
  • Input is flexible, read it however you see fit for you.
  • Standard loopholes are not allowed.

Example

In the example below, the initial coordinates of the logo is i=(1,1), the size of the grid is g=(20,20), the dimensions of the dvd logo is d=(10,5).

It took 29 units of time to reach a corner.

enter image description here

Test Cases

Format: 
i , g , d --> output

#Special cases: logo starting in the four corners
(10,15), (20,20), (10,5) --> 0
(10,0), (20,20), (10,5) --> 0
(0,0), (20,20), (10,5) --> 0
(0,15), (20,20), (10,5) --> 0
#Special cases: logo starting glued to all walls
(0,7), (30,20), (7,12) --> 161
(7,0), (30,20), (7,12) --> 16
(23,3), (30,20), (7,12) --> 69
(11,8), (30,20), (7,12) --> 104
# Other test cases
(1,1), (20,20), (10,5) --> 29
(11,8), (24,50), (7,12) --> 448
(11,8), (50,24), (7,12) --> 376
(5,8), (48,39), (31,3) --> 352

This is , so shortest answers in bytes wins!

\$\endgroup\$
8
  • 5
    \$\begingroup\$ Are we guaranteed that the logo will in fact hit the corner? \$\endgroup\$
    – xnor
    Commented Sep 5, 2022 at 19:36
  • 1
    \$\begingroup\$ @xnor Yes, you can assume that for this problem. \$\endgroup\$ Commented Sep 5, 2022 at 19:38
  • 10
    \$\begingroup\$ The first gif doesn't hit the corner :( \$\endgroup\$ Commented Sep 6, 2022 at 16:54
  • 4
    \$\begingroup\$ Related :) \$\endgroup\$
    – DLosc
    Commented Sep 6, 2022 at 20:01
  • 2
    \$\begingroup\$ To confirm @Samathingamajig: At frame 187 out of 223, the gif hits the bottom border, and at frame 188 it hits the left border. \$\endgroup\$
    – Nzall
    Commented Sep 7, 2022 at 19:38

11 Answers 11

42
\$\begingroup\$

Wolfram Language (Mathematica), 27 bytes

ChineseRemainder[-#,#2-#3]&

Try it online!

This is the least \$t\ge0\$ such that \$i+t\equiv0\pmod{g-d}\$.

\$\endgroup\$
1
22
\$\begingroup\$

Python, 59 bytes

-1 thanks to @xnor

f=lambda i,I,g,G,d,D:i%(g-d)+I%(G-D)and-~f(i+1,I+1,g,G,d,D)

Attempt This Online!

Based on the observation that we can "unroll" the box and let the logo fly in a straight line.

\$\endgroup\$
1
  • 5
    \$\begingroup\$ Nice solution! Don't forget the f= and that you can do -~. \$\endgroup\$
    – xnor
    Commented Sep 5, 2022 at 20:09
8
\$\begingroup\$

C (gcc), 55 54 bytes

f(A,B,x,y,a,b){for(x-=a,a=0;A++%x|B++%(y-b);a++);b=a;}

Try it online!

Saved 1 thanks to @G B

f(A,B,x,y,a,b){ function tacking :

  • A B as position
  • x y as grid size
  • a b as logo size

for(x-=a,y-=b stretches grid to remove logo space.

A++%x|B++%y checks if both bounds are reached using positions % new grid sizes

\$\endgroup\$
2
  • \$\begingroup\$ -1 byte by using (y-b) inside the loop instead of y-=b at the beginning \$\endgroup\$
    – G B
    Commented Sep 7, 2022 at 5:23
  • \$\begingroup\$ A B as grid size, and x y as position would be nicer naming. :) \$\endgroup\$
    – Kaz
    Commented Sep 7, 2022 at 22:29
7
\$\begingroup\$

Jelly,  11  10 bytes

Followed att's description in their Mathematica answer.

_µ0+⁵ọẠʋ1#

A full program that accepts g, d, i and prints the result.

Try it online!

How?

_µ0+⁵ọẠʋ1# - Main Link: grid-dimensions (g), DVD-dimensions (d)
_          - g subtract d (vectorises)
 µ         - start a new monadic chain - f(g-d)
  0        - set the left argument "Step" to 0 (right argument is g-d by default)
         # - count up and find...
        1  - ...the first truthy result of:
       ʋ   -   last four links as a dyad - f(Step, g-d):
    ⁵      -     program's third argument -> initial-state (i)
   +       -     add to Step (vectorises)
     ọ     -     multiplicity (vectorises) (number of times each Step+i value
                                            divides the respective g-d value)
      Ạ    -     all? (are both non-zero?)
           - implicit print
\$\endgroup\$
0
6
\$\begingroup\$

Vyxal, 12 bytes

λ‹?+??-ḊA;ṅ‹

Try it online! Test suite.

Similar to @att's answer.

λ‹?+??-ḊA;ṅ‹
λ        ;ṅ   # Find the first positive integer t>0 such that:
 ‹?+   ḊA     #  t-1+x for each x in i are both divisible by, respectively...
    ??-       #  g[0]-d[0] and g[1]-d[1].
           ‹  # Subtract one from this.
\$\endgroup\$
6
\$\begingroup\$

Ruby, 56 ... 50 bytes

->r,c,h,w,d,v{a=-r%h-=d;a+=h while(c+a)%(w-v)>0;a}

Try it online!

How it works:

First, unwrap the box, and reduce the coordinates. It will take a steps to reach the vertical boundary, and after that it will take h-d steps to reach the next. So we only need to check if we hit the horizontal boundary every h-d steps.

\$\endgroup\$
3
\$\begingroup\$

Java, 73 69 bytes

(i,I,g,G,d,D)->{int r=0;for(;(i-r)%(d-g)+(I-r--)%(D-G)>0;);return~r;}

Port of @att's Mathematical answer.

Try it online.

Explanation:

(i,I,g,G,d,D)->{      // Method with 6 integer parameters and integer return-type
  int r=0;            //  Create a result-integer `r`, starting at 0
  for(;(i-r)%(d-g)    //  Loop as long as (i-r) modulo (d-g)
       +(I-r--)%(D-G) //  and (I-r) modulo (D-G) added together
       >0;);          //  is not 0 yet
                      //  (and decrease `r` by 1 after this check with `r--`)
  return~r;}          //  After the loop, return -r-1 as result
\$\endgroup\$
3
\$\begingroup\$

PARI/GP, 49 bytes

f(i,g,d,n)=lift(chinese([Mod(-i[n++],m)|m<-g-d]))

Attempt This Online!

A port of @att's Mathematica answer.


PARI/GP, 50 bytes

f(g,h,d,e)=t(i,j)=if(i%(g-d)+j%(h-e),1+t(i+1,j+1))

Attempt This Online!

A port of @loopy walt's Python answer. This is a curried function that takes input as f(g1,g2,d1,d2)(i1,i2).

\$\endgroup\$
2
\$\begingroup\$

Charcoal, 34 bytes

≔E²Nθ≔E²NηUMη⁻ιN≔⁰ζW⊙⁺θζ﹪κ§ηλ≦⊕ζIζ

Try it online! Link is to verbose version of code. Explanation:

≔E²Nθ

Input the initial coordinates of the logo.

≔E²Nη

Input the size of the grid.

UMη⁻ιN

Subtract the dimensions of the logo from the size of the grid.

≔⁰ζ

Start at 0 units of time.

W⊙⁺θζ﹪κ§ηλ

Move the logo by the current time and wrap it back into the grid. Until the sides of the logo line up with the sides of the grid...

≦⊕ζ

... increment the time.

Iζ

Output the final time.

\$\endgroup\$
2
\$\begingroup\$

05AB1E, 10 bytes

-U∞<.Δ+XÖP

Another port of @att's Mathematica answer, so make sure to upvote him as well!

Inputs in the order \$d,g,i\$.

Try it online or verify all test cases.

Explanation:

-        # Decrease the first two (implicit) inputs from one another: [g₁-d₁, g₂-d₂]
 U       # Pop and store this pair in variable `X`
∞        # Push an infinite positive list: [1,2,3,...]
 <       # Decrease each by 1 to make it a non-negative list: [0,1,2,...]
  .Δ     # Find the first integer `y` in this list which is truthy for:
    +    #  Add it to the third (implicit) input: [i₁+y, i₂+y]
     X   #  Push pair `X`
      Ö  #  Check if the pairs are divisible: [(i₁+y)%(g₁-d₁)==0, (i₂+y)%(g₂-d₂)==0]
       P #  Product to check if both are truthy: ((i₁+y)%(g₁-d₁)==0)*((i₂+y)%(g₂-d₂)==0)
         # (after which the found result is output implicitly)
\$\endgroup\$
0
0
\$\begingroup\$

Python 3 + SymPy, 127 bytes

A port of @att's answer.


Golfed version. Try it online!

from sympy.ntheory.modular import crt
from numpy import array as A
f=lambda i,g,d:crt((A(g)-A(d)).tolist(),(-A(i)).tolist())[0]

Ungolfed version. Try it online!

from sympy.ntheory.modular import crt
import numpy as np

def chinese_remainder(i, g, d):
    i_array = -np.array(i)
    gd_array = np.array(g) - np.array(d)
    return crt(gd_array.tolist(), i_array.tolist())[0]

test_cases = [
    ([10, 15], [20, 20], [10, 5]),
    ([10, 0], [20, 20], [10, 5]),
    ([0, 0], [20, 20], [10, 5]),
    ([0, 15], [20, 20], [10, 5]),
    ([0, 7], [30, 20], [7, 12]),
    ([7, 0], [30, 20], [7, 12]),
    ([23, 3], [30, 20], [7, 12]),
    ([11, 8], [30, 20], [7, 12]),
    ([1, 1], [20, 20], [10, 5]),
    ([11, 8], [24, 50], [7, 12]),
    ([11, 8], [50, 24], [7, 12]),
    ([5, 8], [48, 39], [31, 3])
]

# Use the test_cases list defined above
for input_tuple in test_cases:
    print(f"{input_tuple} -> {chinese_remainder(*input_tuple)}")
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.