| Bytes | Lang | Time | Link |
|---|---|---|---|
| 033 | Octave | 230716T162655Z | loopy wa |
| 006 | Jelly | 230715T235217Z | Jonathan |
| 006 | Thunno 2 L | 230717T172157Z | The Thon |
| 007 | Pyth | 230717T143812Z | CursorCo |
| 008 | 05AB1E | 230717T112831Z | Kevin Cr |
| 058 | C gcc | 230715T165705Z | c-- |
| 005 | Nekomata | 230716T043545Z | alephalp |
| 018 | J | 230716T032841Z | south |
| 047 | Python | 230715T231010Z | Albert.L |
| 036 | JavaScript Node.js | 230715T163014Z | c-- |
| 015 | Charcoal | 230715T172135Z | Neil |
| 4948 | Python 3.8 prerelease | 230715T135112Z | user1609 |
| 210 | Racket | 230715T144850Z | Ed The & |
| 046 | JavaScript Node.js | 230715T123900Z | l4m2 |
| 050 | Python 3 | 230715T133011Z | gsitcia |
| 156 | Scala | 230715T132547Z | 138 Aspe |
Octave, 33 bytes
@(M,N,T)nnz(union(1:M:T,1:N:T))-1
Thanks to @Luis Mendo for -2.
Octave, 35 bytes
@(M,N,T)numel(union(1:M:T,1:N:T))-1
Port of @Albert.Lang's Python answer.
Jelly, 6 bytes
ḍƇⱮṖTL
A dyadic Link that accepts the dimensions on the left and the time on the right and yields the number of completed reflections.
How?
ḍƇⱮṖTL - Link: dimensions = [M, N, ...]; time = T
Ṗ - pop {T} -> Seconds=[1,2,3,...,T-1]
Ɱ - map {across S in Seconds} with:
Ƈ - keep {dimensions} that:
ḍ - divide {S}
T - truthy indices
L - length
Lots more sixes such as, TIO:
ṖÆDfƇL - Link: time = T; dimensions = [M, N, ...]
Ṗ - pop {T}
ÆD - divisors
Ƈ - keep those for which:
f - filter keep {dimensions}
L - length
RmFQL’ TIO
ḍẸ¥ⱮṖS TIO
×ⱮFQ<S, ×þFQ<S, ḍⱮṖṀƇL, ḍþṖṀƇL, ḍⱮṖṀ€S, ḍþṖṀ€S, ḍⱮṖẸ€S, ḍþṖẸ€S, ḍⱮṖẸƇL, ḍþṖẸƇL, Ḷ:€QL’, :þSṖṬS, ...
Thunno 2 L, 6 bytes
ėsȷ÷Uṫ
Port of alephalpha's Nekomata answer.
Explanation
ėsȷ÷Uṫ # Implicit input
ė # Push [1..t) to the stack
s # Swap so [m,n] is on top
ȷ # Outer product over:
÷ # Integer division
U # Uniquify the list
ṫ # Remove the last item
# Implicit output of length
Pyth, 7 bytes
tl{/R.Q
Port of @alephalpha's Nekomata answer.
Takes three inputs: time, width, height in that order.
Explanation
tl{/R.QQ # implicitly add Q
# implicitly assign Q = eval(input()) and .Q to a list of the remaining input
/R.QQ # map division over range(Q) with .Q as the second argument, this automatically vectorizes
{ # deduplicate
l # take the length
t # subtract 1
05AB1E, 8 bytes
<Lsδ÷Ùg<
Try it online or verify all test cases.
Explanation:
<L # Use the first (implicit) input, and push a list in the range [1,input-1]
s # Swap to push the second (implicit) input-pair
δ # Apply double-vectorized:
÷ # Integer-division
Ù # Uniquify this list of pairs
g # Pop and push the length
< # Decrease it by 1
# (after which the result is output implicitly)
C (gcc), 58 bytes
g(a,b){a=b?g(b,a%b):a;}f(M,N,T){T=--T/M+T/N-T*g(M,N)/M/N;}
Uses the formula:
\$ \lfloor \frac{T - 1}{M} \rfloor + \lfloor \frac{T - 1}{N} \rfloor - \lfloor \frac{T - 1}{lcm(M,N)} \rfloor\$
Nekomata, 5 bytes
ᵒ÷u#←
Takes input as [m,n],t.
ᵒ÷u#←
ᵒ÷ Generate a division table of [0,...,t-1] and [m,n]
u Uniquify
# Length
← Decrement
J, 18 bytes
<:@#@~.@(<.@%/~i.)
Uses the division table method used by others. Expects M N f T.
<:@#@~.@(<.@%/~i.)
( ) NB. Dyadic hook
i. NB. 0..y-1
/~ NB. Table with flipped arguments, execute a u b for every a in x and b in y
<.@% NB. Divide then floor
<:@#@~.@ NB. Then uniquify, length, and decrement
J, 19 bytes
+`-/@(<.@%[,*./)~<:
Uses the closed form from c--'s answer, so please go upvote!
Expects M N f T, where M N is a list.
The major form is two hooks, an inner and outer hook, (H F)~ G, which is equivalent to (G y) H (F x), with +`-/ tacked on at the end, where x and y are the left and right arguments, respectively.
+`-/@(<.@%[,*./)~<:
<: NB. Decrement T
( )~ NB. Flip the arguments for the inner hook
[,*./ NB. Append lcm(M,N) to the list of dimensions
<.@% NB. Divide T-1 by each item of the result then floor
+`-/@ NB. Then reduce by both + and -, i.e. +`-/ 6 3 1 = 6 + 3 - 1 = 8
Python, 47 bytes
lambda M,N,T:len({*range(M,T,M),*range(N,T,N)})
How?
Enumerates and counts all bouncing times using the Python set type for deduplication.
JavaScript (Node.js), 36 bytes
port of user1609012's Python answer
f=(M,N,T)=>--T&&!(T%M&&T%N)+f(M,N,T)
Explanation
Start from the end of the ray \$(t = T)\$, and count the number of times it bounced in it's way, that is, anytime \$t \equiv 1 \pmod M \lor t \equiv 1 \pmod N\$. It's easier to see if you extend the chamber infinitely and have the ray cross the chamber walls.
C (gcc), 39 bytes
port to C
f(M,N,T){T=--T?!(T%M&&T%N)+f(M,N,T):0;}
Charcoal, 15 bytes
≔…¹NθI№×﹪θN﹪θN⁰
Attempt This Online! Link is to verbose version of code. Takes T as the first parameter. Explanation:
… Exclusive range from
¹ Literal integer `1` to
N First input as a number
≔ θ Save in variable
θ Saved range
﹪ Vectorised modulo
N Second input as a number
× Pairwise multiplied by
θ Saved range
﹪ Vectorised modulo
N Third input as a number
№ Count of
⁰ Literal integer `0`
I Cast to string
Implicitly print
Python 3.8 (pre-release), 49 48 bytes
f=lambda M,N,T:(T:=T-1)and(T%M*(T%N)<1)+f(M,N,T)
-1 byte thanks to c--
Racket, 210 bytes
(define(r M N T[R 0][X 0][Y 0][x 1][y 1])(let*([A(+ X x)][B(+ Y y)][a(or(< A 0)(> A M))][b(or(< B 0)(> B N))])(if(= T 0)R(r M N(- T 1)(if(or a b)(+ R 1)R)(if a(- X x)A)(if b(- Y y)B)(if a(- x)x)(if b(- y)y)))))
Explanation
For starters, this will definitely not win. Looking at the other answers, there seems to be a simpler algorithm to solving this. But I don't want to just copy things without having any understanding on how or why they work, so I decided to use a bruteforcing method of actually running the simulation.
Our function receives our three inputs M, N and T. It also receives a predefined state for the recursive loop.
(define (reflect M N T
[reflections 0]
[x-pos 0] [y-pos 0]
[dx 1] [dy 1])
...)
We then calculate the next x and y position, and see whether the next position are out-of-bounds (-oob).
(let* ([next-x-pos (+ x-pos dx)]
[next-y-pos (+ y-pos dy)]
[next-x-oob (or (< next-x-pos 0) (> next-x-pos M))]
[next-y-oob (or (< next-y-pos 0) (> next-y-pos N))])
...)
Once those values are calculated, we check whether our simulation time T is equal to zero. If it is, we return the resulting number of reflections. Otherwise we repeat the loop with a new set of configurations:
- Same
MandNsizes. T- 1.- If the next X and Y positions are out of bounds,
reflections+ 1, elsereflections. - If the next X position is out of bounds, recalculate the next position by flipping
dx. - If the next Y position is out of bounds, recalculate the next position by flipping
dy. - If the previously calculated
next-x-posis out of bounds, flipdx. - If the previously calculated
next-y-posis out of bounds, flipdy.
(define (reflect M N T
[reflections 0]
[x-pos 0] [y-pos 0]
[dx 1] [dy 1])
(let* ([next-x-pos (+ x-pos dx)]
[next-y-pos (+ y-pos dy)]
[next-x-oob (or (< next-x-pos 0) (> next-x-pos M))]
[next-y-oob (or (< next-y-pos 0) (> next-y-pos N))])
(if (= T 0)
R
(reflect M N (- T 1)
(if (or next-x-oob next-y-oob)
(+ reflections 1)
reflections)
(if next-x-oob
(- x-pos dx)
next-x-pos)
(if next-y-oob
(- y-pos dy)
next-y-pos)
(if next-x-oob
(- dx)
dx)
(if next-y-oob
(- dy)
dy))))
Have an awesome weekend!
Scala, 156 bytes
Golfed version. Try it online!
def f(M:Int)(N:Int):(Int,Int,Int)=>Int={def g(T:Int,x:Int=0,y:Int=0):Int=if(T<1)-1 else if(x==0||y==0)1+g(T-1,(x+1)%M,(y+1)%N)else g(T-1,(x+1)%M,(y+1)%N);g}
Ungolfed version. Try it online!
object Main {
def f(M: Int)(N: Int): (Int, Int, Int) => Int = {
def g(T: Int, x: Int = 0, y: Int = 0): Int = {
if (T == 0) T-1
else if (x == 0 || y == 0) 1 + g(T - 1, (x + 1) % M, (y + 1) % N)
else g(T - 1, (x + 1) % M, (y + 1) % N)
}
g
}
def main(args: Array[String]): Unit = {
val testCases = Array(
(5, 4, 11),
(5, 4, 10),
(1, 1, 10),
(5, 1, 10),
(4, 5, 16),
(100, 100, 1),
(3, 2, 9),
(3, 2, 10),
(6, 3, 18),
(5, 3, 16),
(1, 1, 100),
(4, 4, 100),
(2398, 2308, 4),
(10000, 500, 501),
(500, 10000, 502)
)
testCases.foreach { case (a, b, c) =>
println(f(a)(b)(c, 0, 0))
}
}
}