SO MANY ENUMS
Here is a HAC solution…
My Solution for Day 2:
with Ada.Containers.Vectors; -- Top Level package package Day_02 is -- Chosen hand shape type Shape is (Rock, Paper, Scissors); -- How the game concluded type Outcome is (Loss, Draw, Win); -- Overall score is any natural value type Score is new Natural; -- Determines the outcome of the round function Round_Outcome(You, Opponent : Shape) return Outcome; -- Scores a round based on the shapes you and your opponent chose function Score_Round(You, Opponent : Shape) return Score; -- Scores a round based on the shape you chose and the round outcome function Score_Round (Shape : Day_02.Shape; Outcome : Day_02.Outcome) return Score; -- Holds information about each round type Round is record Your_Shape : Shape := Rock; Opponents_Shape : Shape := Rock; Total_Score : Score := 0; end record; -- Using vectors for simplicity package Round_Vectors is new Ada.Containers.Vectors (Index_Type => Positive, Element_Type => Round); -- List of rounds subtype Rounds is Round_Vectors.Vector; -- Parses the supplied file and returns a list of rounds function Parse_File(Filename : String) return Rounds; -- Takes in a rounds lists and adds them all together function Score_All_Rounds(Rounds : Day_02.Rounds) return Score; end Day_02;
with Ada.Text_IO; with Ada.Strings.Fixed; with Ada.Exceptions; with Ada.Command_Line; package body Day_02 is -- Enables checking Static_Predicate, Pre, Post, etc. pragma Assertion_Policy (Check); -- Score Constants Used_Rock : constant := 1; Used_Paper : constant := 2; Used_Scissors : constant := 3; Game_Lost : constant := 0; Game_Tied : constant := 3; Game_Won : constant := 6; -- Individual score for each shape used in the game subtype Shape_Score is Score range Used_Rock..Used_Scissors; -- Individual score for each game subtype Outcome_Score is Score with Static_Predicate => Outcome_Score in Game_Lost | Game_Tied | Game_Won; -- Returns the assigned score based on the shape function Get_Score(Shape : Day_02.Shape) return Shape_Score with Inline; -- Returns the assigned score based on how the game concluded function Get_Score(Outcome : Day_02.Outcome) return Outcome_Score with Inline; -- Array used to convert a shape to its corresponding score To_Shape_Score : constant array(Day_02.Shape) of Shape_Score := [Rock => Used_Rock, Paper => Used_Paper, Scissors => Used_Scissors]; -- Array used to convert an outcome to its corresponding score To_Outcome_Score : constant array(Day_02.Outcome) of Outcome_Score := [Loss => Game_Lost, Draw => Game_Tied, Win => Game_Won]; function Get_Score(Shape : Day_02.Shape) return Shape_Score is (To_Shape_Score(Shape)); function Get_Score(Outcome : Day_02.Outcome) return Outcome_Score is (To_Outcome_Score(Outcome)); -- Maps <your_shape>,<opponents_shape> to an outcome To_Outcome : constant array (Shape,Shape) of Outcome := [Rock => [Rock => Draw, Paper => Loss, Scissors => Win], Paper => [Rock => Win, Paper => Draw, Scissors => Loss], Scissors => [Rock => Loss, Paper => Win, Scissors => Draw]]; function Round_Outcome(You, Opponent : Shape) return Outcome is (To_Outcome(You,Opponent)); function Score_Round(You, Opponent : Shape) return Score is ( Score_Round (Shape => You, Outcome => Round_Outcome (You => You, Opponent => Opponent))); function Score_Round (Shape : Day_02.Shape; Outcome : Day_02.Outcome) return Score is (To_Shape_Score(Shape) + To_Outcome_Score(Outcome)); -- Encryption of round info subtype Opponents_Character is Character range 'A'..'C'; subtype Delimiter_Character is Character range ' '..' '; subtype Your_Character is Character range 'X'..'Z'; -- Decrypts opponent shape info To_Opponents_Shape : constant array(Opponents_Character) of Shape := ['A' => Rock, 'B' => Paper, 'C' => Scissors]; -- Decrypts your shape info To_Your_Shape : constant array(Your_Character) of Shape := ['X' => Rock, 'Y' => Paper, 'Z' => Scissors]; function Parse_File(Filename : String) return Rounds is File : Ada.Text_IO.File_Type; Round : Day_02.Round; Result : Rounds; Opponent : Opponents_Character; Dummy_Delimiter : Delimiter_Character; -- Named dummy to avoid GNAT warning You : Your_Character; begin Ada.Text_IO.Open (File => File, Name => Filename, Mode => Ada.Text_IO.In_File); while not Ada.Text_IO.End_Of_File(File) loop declare Line : constant String := Ada.Strings.Fixed.Trim (Source => Ada.Text_IO.Get_Line(File), Side => Ada.Strings.Both); begin -- Only look at lines that could have the correct format. -- Ignore empty lines if Line'Length = 3 then Opponent := Line(Line'First + 0); Dummy_Delimiter := Line(Line'First + 1); You := Line(Line'First + 2); Round.Your_Shape := To_Your_Shape(You); Round.Opponents_Shape := To_Opponents_Shape(Opponent); Round.Total_Score := Score_Round (You => Round.Your_Shape, Opponent => Round.Opponents_Shape); Result.Append(Round); -- Lines not exactly 3 characters or not empty are ill formatted elsif Line'Length /= 0 then raise Ada.Text_IO.Data_Error with "Line longer than expected: " & Line; end if; end; end loop; Ada.Text_IO.Close(File); return Result; exception -- If an exception was raised, it means there is an -- input file error. Print out some debug and return -- an empty list when e : others => Ada.Text_IO.Put_Line("Input File Error"); Ada.Text_IO.Put_Line(Ada.Exceptions.Exception_Information(e)); if Ada.Text_IO.Is_Open(File) then Ada.Text_IO.Close(File); end if; return Round_Vectors.Empty_Vector; end Parse_File; function Score_All_Rounds(Rounds : Day_02.Rounds) return Score is Result : Score := 0; begin for Round of Rounds loop Result := @ + Round.Total_Score; end loop; return Result; end Score_All_Rounds; -- Program variables Filename : constant String := (if Ada.Command_Line.Argument_Count = 0 then "input.txt" else Ada.Command_Line.Argument(1)); Round_List : constant Rounds := Parse_File(Filename); Total_Score : constant Score := Score_All_Rounds(Round_List); Total_Rounds : constant Ada.Containers.Count_Type := Round_List.Length; use type Ada.Containers.Count_Type; begin if Total_Rounds = 0 then Ada.Text_IO.Put_Line("No rounds in file"); else Ada.Text_IO.Put_Line("Total # of rounds:" & Total_Rounds'Image); Ada.Text_IO.Put_Line("Total Score:" & Total_Score'Image); end if; end Day_02;
I just withed Day_02 in a blank main file.
Indeed enums were very helpful. They did all the work for me!
Yep! I like pairing enums with arrays indexed by those enums to make it do all the logic work too, which is nice.
Wow, that is nice! This is very short solution!
I ended up using enums as well, with a multidimensional array as a lookup table (kind of). I love the solutions with 'Val, I keep forgetting that I can do that!
Here’s my solution: adventofcode/day2.adb at 9683a101a7532e2deaf632354091dae421287dce · AJ-Ianozi/adventofcode · GitHub