Skip to content

Instantly share code, notes, and snippets.

@gdeer81
Last active December 10, 2016 07:25
Show Gist options
  • Save gdeer81/2f6e7b43361c62a402c0282e7ecb568a to your computer and use it in GitHub Desktop.
Save gdeer81/2f6e7b43361c62a402c0282e7ecb568a to your computer and use it in GitHub Desktop.
bouncey ball problem with 2 different solutions
;;compare the two approaches to solving the same problem
;;A child plays with a ball on the nth floor of a big building the height of which is known
;;(float parameter "h" in meters, h > 0) .
;;He lets out the ball. The ball rebounds for example to two-thirds
;;(float parameter "bounce", 0 < bounce < 1)
;;of its height.
;;His mother looks out of a window that is 1.5 meters from the ground
;;(float parameters window < h).
;;How many times will the mother see the ball either falling or bouncing in front of the window
;;(return a positive integer unless conditions are not fulfilled in which case return -1) ?
;;(bouncing-balls 3 0.66 1.5) => 3
;;(bouncing-balls 30 0.66 1.5) => 15
;;the first approach is what you would typically see in a languages that encourages mutation
;;declare variables and then create a loop and bang on those variables until the loop ends
(defn bouncing-balls-with-ugly-mutation [h bounce window]
(if (not (< 0 bounce 1))
-1
(let [curr_height (atom h)
times (atom 0)]
(while (> @curr_height window)
(if (> (* bounce @curr_height) window)
(do (reset! curr_height (* @curr_height bounce)) (swap! times #(+ 2 %)) )
(do (reset! curr_height (* @curr_height bounce)) (swap! times inc))
))
@times)))
;;this approach could probably be cleaned up a little but it introduces NO mutable variables
;;the function keeps calling itself with new values until it reaches the base case
(defn bouncing-balls
([h bounce window] (bouncing-balls h bounce window 0))
([h bounce window bounces]
(if (not (< 0 bounce 1))
-1
(if (> window h)
bounces
(if (> (* bounce h) window)
(bouncing-balls (* h bounce) bounce window (+ 2 bounces))
(bouncing-balls (* h bounce) bounce window (inc bounces)))))))
;;this implementation is identicle to the one above but with more detailed naming convention >_<
(defn bouncing-balls2
([ball-position bounce-percentage mother-position] (bouncing-balls ball-position bounce-percentage mother-position 0))
([ball-position bounce-percentage mother-position times-mother-has-seen-the-ball]
(if (not (< 0 bounce-percentage 1))
-1
(let [mother-position-higher-than-current-ball-position? (> mother-position ball-position)
balls-next-position (* bounce-percentage ball-position)
balls-next-position-higher-than-mother-position? (> balls-next-position mother-position)
then-return-current-number-of-times-mother-has-seen-the-ball times-mother-has-seen-the-ball
increase-the-number-of-times-mother-has-seen-the-ball-by-two (+ 2 times-mother-has-seen-the-ball)
increase-the-number-of-times-mother-has-seen-the-ball-by-one (inc times-mother-has-seen-the-ball)
call-bouncing-balls-again-but (partial (bouncing-balls2 balls-next-position bounce-percentage mother-position))
]
(if mother-position-higher-than-current-ball-position? then-return-current-number-of-times-mother-has-seen-the-ball
(if balls-next-position-higher-than-mother-position?
(call-bouncing-balls-again-but increase-the-number-of-times-mother-has-seen-the-ball-by-two)
(call-bouncing-balls-again-but increase-the-number-of-times-mother-has-seen-the-ball-by-one)))))))
;;;this is the mathematician's solution
(defn bouncing-balls [h bounce window]
(if-not (and (> h 0) (< 0 bounce 1) (< window h)) -1
(-> (/ window h) Math/log (/ (Math/log bounce)) Math/ceil int (* 2) dec)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment