Learning/AoC/2024/day_3/day_3.adb
2025-03-16 18:14:03 +01:00

238 lines
7.7 KiB
Ada

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;