Didn’t see a thread for this yet, so figured I would start one. I’ve only worked on part 1. I did like that I could come up with various methods of doing this right off the bat. I decided on an algorithmic approach .
Yes, there are various methods to solve this problem.
I also followed an algorithmic approach for part 1, just for fun. I solved part two with the bc
calculator: sqrt(T^2-4*D)
.
I solved both approaches with the quadratic formula (@rocher what calls the bc calculator is part of it). The difficulties I had with this problem are that it’s been so long since I used Ada’s digits
type and the Numerics.Elementary_Functions
crate that I had to spend some time reading up on those, experimenting with them, and, once the inevitable bug arose, figuring out what I’d misunderstood.
My general solution:
I kept the times and distances as integers to make the math at the end a bit easier (comparing floats has a lot of edge cases to consider). I converted them all to Floats for the quadratic equation match, found the X intercepts, rounded the result (casting rounds in Ada), use the integer version of the X intercepts to calculate the corresponding distance and then compared the distances to the record to see if the x intercepts rounded past the values I needed (in which case I adjusted them).
type Race_Time is new Positive;
type Race_Distance is new Positive;
type Ways_To_Win is new Natural;
-- Calculation that lets all execptions propagate
function Calculate_Ways_To_Win_Unhandled
(Max_Time : Race_Time;
Distance_Record : Race_Distance)
return Ways_To_Win
is
-- Hold time can never be 0 nor can it be the maximum time
-- or the boat would never move
subtype Hold_Time is Race_Time range 1..Max_Time-1;
-- (Max_Time - Hold_Time) * Hold_Time > Distance_Record
--
-- -(Hold_Time**2) + Max_Time * Hold_Time - Distance_Record > 0
--
-- -B +- SQRT(B**2 - 4*A*C)
-- => ------------------------ = X intercepts
-- 2*A
-- Where:
-- A = -1
-- B = Max_Time
-- C = - (Distance_Record)
--
-- Inverted quadratic means all integer values between X intercepts are
-- win conditions
A : constant := -1.0;
B : constant Float := Float(Max_Time);
C : constant Float := -1.0 * Float(Distance_Record);
Square_Root : constant Float := Sqrt((B**2) - (4.0 * A * C));
-- Calculate X intercepts as rounded integers, where X is the hold time
-- Values may be outside the range of Hold_Time initially, so temporarily
-- use Hold_Time'Base for intermediate calculations. Note that converting
-- from Float to Hold_Time'Base does a rounding operation
x1 : constant Hold_Time'Base := Hold_Time'Base((((-1.0) * B) + Square_Root ) / (2.0 * A));
x2 : constant Hold_Time'Base := Hold_Time'Base((((-1.0) * B) - Square_Root ) / (2.0 * A));
-- Calculate corresponding y values for integer x intercepts
-- Values may be outside the range of Race_Distance initially, so temporarily
-- use Race_Distance'Base for intermediate calculations
x1_Distance : constant Race_Distance'Base := Race_Distance'Base((Max_Time - x1) * x1);
x2_Distance : constant Race_Distance'Base := Race_Distance'Base((Max_Time - x2) * x2);
-- Rounding may have pushed x1 and x2 out of range.
-- Adjust values based on how y values compared to the record
-- This assignment should ensure the results are in the correct
-- range of the Hold_Time type.
First : constant Hold_Time :=
(if x1_Distance > Distance_Record then
x1
else
x1 + 1); -- A little too far left, so adjust
Last : constant Hold_Time :=
(if x2_Distance > Distance_Record then
x2
else
x2 - 1); -- A little too far right, so adjust
begin
-- since these are essentially integers, the number of ways to win
-- is just the number of integers in the range of values
-- or the length of the range;
return Ways_To_Win((Last - First) + 1);
end Calculate_Ways_To_Win_Unhandled;
function Calculate_Ways_To_Win
(Max_Time : Race_Time;
Distance_Record : Race_Distance)
return Ways_To_Win
is begin
return Calculate_Ways_To_Win_Unhandled
(Max_Time => Max_Time,
Distance_Record => Distance_Record);
exception
when others => return 0; -- Means no solution
end Calculate_Ways_To_Win;
Yep, that was my approach