Euler Problem 144 – Laser Bounce

This one is interesting because its a real world application, albeit perhaps a little simplified from the real world so that it fits into the Euler framework. Here a great explanation and solution of the problem using Java. For me the challenge is in translating from imperative to functional, which I found to be pretty fun. Had to wrap my brain around using tuples larger than a pair and how to redefine iterative variables.

I came up with a recursive routine to calculate all the bounces with the data contained in list of tuples. The routine reads the last coordinates from the list, and calculates new coordinates. If the results are within the exit range, return the list as is, otherwise add new coordinates to list and loop. The main function just counts the length of the list. Easy.

quad :: Double -> Double -> Double -> Double
quad m2 n x2
	| dx1 > dx2 = ans1
	| otherwise = ans2
	where
		a = 4 + m2 * m2
		b = 2 * m2 * n
		c = n * n - 100
		ans1 =  (-b + sqrt (b * b - 4 * a * c)) / (2 * a)
		ans2 =  (-b - sqrt (b * b - 4 * a * c)) / (2 * a)
		dx1 = abs (x2 - ans1)
		dx2 = abs (x2 - ans2)

bounce :: [(Double, Double, Double, Double)] -> [(Double, Double, Double, Double)]
bounce coords
	| y2 > 0 && x2 > -0.01 && x2 < 0.01 = coords
	| otherwise = bounce $ coords ++ [(x1, y1, x2, y2)]
	where
		(x1', y1', x2', y2') = last coords
		m0 = (y2' - y1') / (x2' - x1')
		m1 = -4 * x2' / y2'
		tempX = x2'
		tempY = y2'
		bigX = (m0 - m1) / ( 1 + m0 * m1)
		m2 = (m1 - bigX) / ( 1 + bigX * m1)
		b = (y2' - m2 * x2')
		(x1, y1, x2, y2) = (tempX, tempY, quad m2 b x2', m2 * x2 + b)
	
main = print $ length $ bounce [(0, 10.1, 1.4, -9.6)]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s