238 lines
7.7 KiB
Ada
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;
|