with Ada.Text_IO; use Ada.Text_IO; with Ada.Containers.Vectors; procedure Day_3 is type Mul is record X : Integer; Y : Integer; end record; type Muls is array (Natural range <>) of Mul; package mul_vec is new Ada.Containers.Vectors( Index_Type => Natural, Element_Type => Mul); procedure Find_Muls( S : String; Vec : in out mul_vec.Vector ) is type State_Machine is ( Start, Bracket_Open, First_Num, Second_Num ); State : State_Machine := Start; Index : Natural := S'First; Num_Start : Natural; FNum_Length, SNum_Length : Natural := 0; First, Second : Integer; begin State_Loop: while Index <= S'Last loop case State is when Start => if Index + 2 > S'Last then exit State_Loop; end if; if S(Index .. Index + 2) = "mul" then State := Bracket_Open; FNum_Length := 0; SNum_Length := 0; Index := @ + 2; end if; Index := @ + 1; when Bracket_Open => if S(Index) = '(' then State := First_Num; Num_Start := Index + 1; else State := Start; end if; Index := @ + 1; when First_Num => case S(Index) is when ',' => First := Integer'Value(S(Num_Start .. Index - 1)); State := Second_Num; Num_Start := Index + 1; Index := @ + 1; when '0' .. '9' => FNum_Length := @ + 1; Index := @ + 1; when others => State := Start; end case; if FNum_Length > 3 then State := Start; end if; when Second_Num => case S(Index) is when ')' => Second := Integer'Value(S(Num_Start .. Index - 1)); State := Start; Num_Start := Index + 1; Vec.Append( Mul'(X => First, Y => Second) ); Index := @ + 1; when '0' .. '9' => SNum_Length := @ + 1; Index := @ + 1; when others => State := Start; end case; if SNum_Length > 3 then State := Start; end if; end case; end loop State_Loop; end Find_Muls; procedure Find_Muls_Cond( S : String; Vec : in out mul_vec.Vector; Enabled : in out Boolean ) is type State_Machine is ( Start, Bracket_Open, First_Num, Second_Num ); State : State_Machine := Start; Index : Natural := S'First; Num_Start : Natural; FNum_Length, SNum_Length : Natural := 0; First, Second : Integer; begin State_Loop: while Index <= S'Last loop if Index + 7 < S'Last then if S(Index .. Index + 3) = "do()" then Put_Line(S(Index .. Index + 3)); Index := @ + 4; Enabled := True; elsif S(Index .. Index + 6) = "don't()" then Put_Line(S(Index .. Index + 6)); Enabled := False; State := Start; Index := @ + 7; end if; end if; case State is when Start => if Index + 2 > S'Last then exit State_Loop; end if; if S(Index .. Index + 2) = "mul" then State := Bracket_Open; FNum_Length := 0; SNum_Length := 0; Index := @ + 2; end if; Index := @ + 1; when Bracket_Open => if S(Index) = '(' then State := First_Num; Num_Start := Index + 1; else State := Start; end if; Index := @ + 1; when First_Num => case S(Index) is when ',' => First := Integer'Value(S(Num_Start .. Index - 1)); State := Second_Num; Num_Start := Index + 1; Index := @ + 1; when '0' .. '9' => FNum_Length := @ + 1; Index := @ + 1; when others => State := Start; end case; if FNum_Length > 3 then State := Start; end if; when Second_Num => case S(Index) is when ')' => Second := Integer'Value(S(Num_Start .. Index - 1)); State := Start; Num_Start := Index + 1; if Enabled then Put_Line("mul(" & First'Image & "," & Second'Image & ")"); Vec.Append( Mul'(X => First, Y => Second) ); else Put_Line("Disabled"); end if; Index := @ + 1; when '0' .. '9' => SNum_Length := @ + 1; Index := @ + 1; when others => State := Start; end case; if SNum_Length > 3 then State := Start; end if; end case; end loop State_Loop; end Find_Muls_Cond; function Read_File( File_Name : String; cond : Boolean ) return Muls is File : File_Type; Vec : mul_vec.Vector; Enabled : Boolean := True; begin Open(File, In_File, File_Name); while not End_Of_File(File) loop if cond then Find_Muls_cond(Get_Line(File), Vec, Enabled); else Find_Muls(Get_Line(File), Vec); end if; end loop; Close(File); return M : Muls( 0 .. Integer(Vec.Length) - 1) do for I in 0 .. Integer(Vec.Length) - 1 loop M(I) := Vec(I); end loop; end return; end Read_File; function Day_1_1( M : Muls ) return Integer is Sum : Integer := 0; begin For Mult of M loop Sum := @ + Mult.X * Mult.Y; end loop; return Sum; end Day_1_1; File_Name : String := "input_day_3.txt"; begin Put_Line(Day_1_1(Read_File(File_Name, False))'Image); Put_Line(Day_1_1(Read_File(File_Name, True))'Image); end Day_3;