# ASCII reflections in a box

You probably all know the Law of Reflection, in this challenge you'll visualize the trajectory of a ball in a box.

You're given three integer pairs W,H, x,y and dx,dy - the first represents the size of the box, the second the starting position and the third pair is the direction in which the ball starts moving.

The task is to visualize the movement of the ball until it stops rolling, this happens as soon as the ball is at a position that it was before or it hits a corner.

The character * shall visualize the trajectory of the ball and + marks its final position, the rest of the box must consist of (whitespace).

### Examples

To lay it out a bit clearer, in these examples _ will represent a whitespace. Also the intermediate stages are only here for clarification, you'll only need to output the last stage, these examples are 1-indexed.

Given W = 3, H = 5, x = 3, y = 2 and dx = -1, dy = 1:

___    ___    ___    ___
__*    __*    __*    __*
___ -> _*_ -> _*_ -> _+_
___    *__    *__    *_*
___    ___    _*_    _*_

• Ball starts at point (3,2) and
• moves in direction (-1,1), hits the wall at (1,4) and
• gets reflected, new direction is (1,1). It hits the wall again at (2,5)
• where it gets gets reflected. The new direction is (1,-1) and it hits the wall immediately at (3,4),
• again it gets reflected into the direction (-1,-1). It would now travel through points (2,3),(1,2), reflected etc. but since it already visited the position (2,3) it stops there.

This example demonstrates, what happens if a ball hits a corner. For this let W = 7, H = 3, x = 1, y = 3 and dx = 1, dy = -1:

_______    __*____    __*____    __*___+
_______ -> _*_____ -> _*_*___ -> _*_*_*_
*______    *______    *___*__    *___*__

• Start position is (1,3),
• the ball now travels in direction (1,-1) until it hits the wall at (3,1)
• where it gets reflected into the new direction (1,1).
• At (5,3) it gets reflected and travels into the new direction (1,-1). It comes to an abrupt stop at (7,1) because that's a corner.

Given W = 10, H = 6, x = 6, y = 6 and dx = 1, dy = 1:

__________    __________    ________*_    ________*_    ________*_    __*_____*_    __*_____*_
__________    _________*    _________*    _______*_*    _______*_*    _*_____*_*    _*_*___*_*
__________ -> ________*_ -> ________*_ -> ______*_*_ -> *_____*_*_ -> *_____*_*_ -> *___*_*_*_
__________    _______*__    _______*__    _____*_*__    _*___*_*__    _*___*_*__    _*___+_*__
__________    ______*___    ______*___    ____*_*___    __*_*_*___    __*_*_*___    __*_*_*___
_____*____    _____*____    _____*____    ___*_*____    ___*_*____    ___*_*____    ___*_*____


### Input specification

The input consists of the three integer pairs W,H, x,y and dx,dy, you may take input in any format that makes most sense for your programming language and the order doesn't matter. However the accepted input must not encode more information than these pairs contain (see this answer for an example).

• W,H >= 1
• x,y are either 1-indexed (1 <= x <= W and 1 <= y <= H) or 0-indexed (0 <= x < W and 0 <= y < H), please specify what indexing you chose
• dx,dy are always either -1 or 1

Invalid input can be ignored.

### Output specification

1. No leading whitespaces are allowed
2. Trailing whitespaces may be omitted
3. Trailing whitespaces are not allowed if they don't fit the box
4. Trailing newlines (after all output related lines) are allowed

Let's take the first example:

       (good by 2)
__*
_+     (good by 2)
_*_
(good by 4)


### Test cases

Assuming the input has the format (W,H,x,y,dx,dy) and 1-indexing was chosen, here are some test cases (again _ is here to represent whitespaces!):

Input: 1,1,1,1,1,1

Output:

+


Input: 3,3,3,3,1,1

Output:

___
___
__+


Input: 3,3,3,3,-1,-1

Output:

+__
_*_
__*


Input: 7,3,1,3,1,-1

Output:

__*___+
_*_*_*_
*___*__


Input: 10,6,6,6,1,1

Output:

__*_____*_
_*_*___*_*
*___*_*_*_
_*___+_*__
__*_*_*___
___*_*____


Input: 21,7,6,4,-1,-1

Output:

__*_______*_______*__
_*_*_____*_*_____*_*_
*___*___*___*___*___*
_*___*_*_____*_*___*_
__*___*_______+___*__
___*_*_________*_*___
____*___________*____


This is , so the shortest program/function wins, but any effort is appreciated.

• I suspect one of the 2D languages (Turtle?) might do really well with this challenge. Commented Jul 14, 2017 at 16:00
• Would it be allowed to encode the four possible dx/dy values as four consecutive odd integers? How important is it that x and y are 1-indexed?
– Neil
Commented Jul 14, 2017 at 16:30
• I'll drop the 1-indexed constraint if you like(?) About that first question, not sure what you mean but it sounds ok. I guess anything that is a bijection ({-1,1}x{-1,1} ≡ "Your space") would be good. Commented Jul 14, 2017 at 16:36
• Edited in the indexing, can you be more specific on your other question? Commented Jul 14, 2017 at 16:46
• I want to see a charcoal answer for this lol. Commented Jul 14, 2017 at 17:05

# Charcoal, 50 bytes

ＵＯＮＮ ＪＮＮ↷ＮＷ⁼ ＫＫ«*¿¬ＫＫ«↷²¶*¿¬ＫＫ«↷²¶↷²*¿¬ＫＫ«↷²¶»»»»+


Try it online! Link is to verbose version of code. Takes five inputs: w, h, x, y, a. x and y are zero-indexed. a represents dx and dy according to the following encoding:

a mod 8 == 1 => dx = 1, dy = 1
a mod 8 == 3 => dx = -1, dy = 1
a mod 8 == 5 => dx = -1, dy = -1
a mod 8 == 7 => dx = 1, dy = -1


Explanation:

ＵＯＮＮ


(note trailing space) Fills the background with spaces to the input width and height. (Normally each square of the background is an empty string, which is then converted to a space on output.)

ＪＮＮ


Moves the cursor to the initial coordinates.

↷Ｎ


Rotates to the initial angle.

Ｗ⁼ ＫＫ«


Repeats as long as the current square is a space.

    *


Prints an asterisk and moves forward in the current direction.

    ¿¬ＫＫ«


If the cursor moved outside of the original oblong,

        ↷²¶*


Rotate the direction, then print a newline (which conveniently takes us back to the previous square) and an asterisk, which moves in the new direction.

        ¿¬ＫＫ«


If the cursor moved back outside of the original oblong,

            ↷²¶↷²*


Take the cursor back to the previous square, then rotate again, thus printing the asterisk in the other direction.

            ¿¬ＫＫ«


If the cursor is still outside of the oblong, we must be at a corner.

                ↷²¶


So go back to the previous square and give up.

»»»»+


When we can't move any more, print a "+" sign and stop.

• Nice! Here's a TIO for those that want to try it. Commented Jul 14, 2017 at 18:44
• @BruceForte Thanks, but I didn't want to link to TIO until I had a solution using Peek() (which I do now).
– Neil
Commented Jul 15, 2017 at 0:33
• Oops, Peek works again now Commented Jul 27, 2017 at 1:58

# Desmos Calculator - Non Competing to Help Further Knowledge

Try it online!

Inputs:

X as X position to Start
Y as Y position to Start
s as slope -> -1 for dX/dY = -1, +1 for dX/dY = +1
h as height of box, with 0-indexing
w as width of box, with 0-indexing


Intermediates:

Let b = gcd(h,w),
Let c = |b-(X-sY)%2b| Or |b-mod(X-sY,2b)|


Formula, abbreviated:

(|b-(x+y)%2b|-c)(|b-(x-y)%2b|-c)=0


Outputs:

x as x position, 0-indexed, where the ball will land when released
y as y position, 0-indexed, where the ball will land when released


How it Works:

(|b-(x+y)%2b|-c)*(|b-(x-y)%2b|-c)=0
^ OR operation - |b-(x+y)%2b|-c=0 or |b-(x-y)%2b|-c=0
|b-(x+/-y)%2b|-c = 0
|b-(x+/-y)%2b| = c
|b-(x+/-y)%2b| = c means (b-(x+/-y))%2b = + or -c
b-(x+/-y)%2b = +/- c -> b +/- c = (x+/-y)%2b -> (x+/-y) = n*2*b + b +/- c
Where n is integer.  This will force patterns to repeat every 2b steps in x and y.
Initial pattern n=0: (x +/- y) = b +/- c -> y = +/- x + b +/- c
In the x positive and y positive plane only, these correspond to lines of positive and
negative slope, set at intercept b, offset by c on either side.


Program fails to meet final criterion - stopping at intersection point and marking with a +, so is submitted as non-competitive for information to help others complete the challenge. Note that to get Desmos to work when c = 0 or c=b, a small offset factor of 0.01 was introduced, as Desmos seems to have bounds of Mod(A,B) of (0,B) instead of [0,B)

• I suppose you have seen this? Commented Jul 20, 2017 at 20:41
• Actually, I self nerd sniped and lost about 4 days of my at-home time. I really, really liked this problem.
– Mark
Commented Jul 20, 2017 at 20:43
• You're welcome ;P Also, relevant. Commented Jul 20, 2017 at 20:47

# Python 3, 293 279 bytes

w,h,x,y,i,j=map(int,input().split());x-=1;y-=1;l=[x[::]for x in[[' ']*w]*h]
while 1:
a,b=((x,i)in[(0,-1),(w-1,1)]),((y,j)in[(0,-1),(h-1,1)])
if a and b or l[y][x]!=' ':l[y][x]='+';break
i,j=i*(-a*2+1),j*(-b*2+1);l[y][x]='*';x+=i;y+=j
print('\n'.join([''.join(x) for x in l]))



Try it online!

• Nice! You can save a few bytes by shortening fx,fy and replacing True by something like 1, see here Commented Jul 27, 2017 at 11:09
• @BruceForte thanks! I forgot to replace these. Commented Jul 27, 2017 at 12:02
• -13 bytes by turning it into a function. Commented Jan 5, 2020 at 16:34
• Wait, just seen how old this question is... Yet I got here from HNQ... Commented Jan 5, 2020 at 16:36