215 lines
7.3 KiB
Ada
215 lines
7.3 KiB
Ada
with Ada.Text_IO; use Ada.Text_IO;
|
|
|
|
procedure Day_6 is
|
|
|
|
Parse_Error : Exception;
|
|
|
|
type Instruction is (
|
|
None,
|
|
Turn_On,
|
|
Turn_Off,
|
|
Toggle);
|
|
|
|
type Instr is
|
|
record
|
|
Inst : Instruction := None;
|
|
X0, Y0, X1, Y1 : Natural;
|
|
end record;
|
|
|
|
function Read_Coordinates( Text : String ) return Instr is
|
|
Output : Instr;
|
|
Start_Num : Natural := Text'First;
|
|
|
|
Thr : String := "through";
|
|
Thr_Idx : Natural := Thr'First;
|
|
|
|
type State is (Start, X0, Y0, Through, X1, Y1);
|
|
|
|
St : State := Start;
|
|
begin
|
|
for I in Text'Range loop
|
|
case St is
|
|
when Start =>
|
|
case Text(I) is
|
|
when '0' .. '9' =>
|
|
Start_Num := I;
|
|
St := X0;
|
|
when others =>
|
|
raise Parse_Error with "Invalid character";
|
|
end case;
|
|
when X0 =>
|
|
case Text(I) is
|
|
when '0' .. '9' =>
|
|
null;
|
|
when ',' =>
|
|
Output.X0 := Natural'Value(Text(Start_Num .. I-1));
|
|
Start_Num := I+1;
|
|
St := Y0;
|
|
when others =>
|
|
raise Parse_Error with "Invalid character";
|
|
end case;
|
|
when Y0 =>
|
|
case Text(I) is
|
|
when '0' .. '9' =>
|
|
null;
|
|
when ' ' =>
|
|
Output.Y0 := Natural'Value(Text(Start_Num .. I-1));
|
|
St := Through;
|
|
when others =>
|
|
raise Parse_Error with "Invalid character";
|
|
end case;
|
|
when Through =>
|
|
if Thr_Idx > Thr'Last then
|
|
if Text(I) = ' ' then
|
|
St := X1;
|
|
Start_Num := I+1;
|
|
else
|
|
raise Parse_Error with "Invalid character";
|
|
end if;
|
|
else
|
|
if Text(I) = Thr(Thr_Idx) then
|
|
Thr_Idx := @ + 1;
|
|
else
|
|
raise Parse_Error with "Invalid character";
|
|
end if;
|
|
end if;
|
|
when X1 =>
|
|
case Text(I) is
|
|
when '0' .. '9' =>
|
|
null;
|
|
when ',' =>
|
|
Output.X1 := Natural'Value(Text(Start_Num .. I-1));
|
|
Start_Num := I+1;
|
|
St := Y1;
|
|
when others =>
|
|
raise Parse_Error with "Invalid character";
|
|
end case;
|
|
when Y1 =>
|
|
case Text(I) is
|
|
when '0' .. '9' =>
|
|
null;
|
|
when others =>
|
|
raise Parse_Error with "Invalid character";
|
|
end case;
|
|
if I = Text'Last then
|
|
Output.Y1 := Natural'Value(Text(Start_Num .. I));
|
|
end if;
|
|
end case;
|
|
end loop;
|
|
|
|
return Output;
|
|
end Read_Coordinates;
|
|
|
|
function Read_Instruction( Text : String ) return Instr is
|
|
Idx : Natural := Text'First;
|
|
Inst : Instr;
|
|
begin
|
|
if Text(Idx .. Idx + 3) = "turn" then
|
|
if Text(Idx + 5 .. Idx + 6) = "on" then
|
|
Inst := Read_Coordinates( Text( Idx + 8 .. Text'Last));
|
|
Inst.Inst := Turn_On;
|
|
elsif Text(Idx + 5 .. Idx + 7) = "off" then
|
|
Inst := Read_Coordinates( Text( Idx + 9 .. Text'Last));
|
|
Inst.Inst := Turn_Off;
|
|
else
|
|
raise Parse_Error with "no on/off found";
|
|
end if;
|
|
elsif Text(Idx .. Idx + 5) = "toggle" then
|
|
Inst := Read_Coordinates( Text( Idx + 7 .. Text'Last));
|
|
Inst.Inst := Toggle;
|
|
else
|
|
raise Parse_Error with "Illegal Instruction";
|
|
end if;
|
|
|
|
return Inst;
|
|
end Read_Instruction;
|
|
|
|
type BMatrix is array (Natural range <>, Natural range <>) of Boolean;
|
|
type IMatrix is array (Natural range <>, Natural range <>) of Natural;
|
|
|
|
function Day_1_1( File_Name : String ) return Natural is
|
|
Sum : Natural := 0;
|
|
Lights : Bmatrix(0 .. 999, 0 .. 999 ) := (others => (others => False));
|
|
File : File_Type;
|
|
begin
|
|
Open(File, In_File, File_Name);
|
|
|
|
while not End_Of_File(File) loop
|
|
declare
|
|
Inst : Instr := Read_Instruction(Get_Line(File));
|
|
begin
|
|
for I in Inst.X0 .. Inst.X1 loop
|
|
for J in Inst.Y0 .. Inst.Y1 loop
|
|
case Inst.Inst is
|
|
when None =>
|
|
raise Parse_Error with "Cannot have none instruction";
|
|
when Toggle =>
|
|
Lights(I,J) := @ xor True;
|
|
when Turn_On =>
|
|
Lights(I,J) := True;
|
|
when Turn_Off =>
|
|
Lights(I,J) := False;
|
|
end case;
|
|
end loop;
|
|
end loop;
|
|
end;
|
|
end loop;
|
|
|
|
for I in 0 .. 999 loop
|
|
for J in 0 .. 999 loop
|
|
if Lights(I,J) = True then
|
|
Sum := @ + 1;
|
|
end if;
|
|
end loop;
|
|
end loop;
|
|
|
|
Close(File);
|
|
|
|
return Sum;
|
|
end Day_1_1;
|
|
|
|
function Day_1_2( File_Name : String ) return Natural is
|
|
Sum : Natural := 0;
|
|
Lights : Imatrix(0 .. 999, 0 .. 999 ) := (others => (others => 0));
|
|
File : File_Type;
|
|
begin
|
|
Open(File, In_File, File_Name);
|
|
|
|
while not End_Of_File(File) loop
|
|
declare
|
|
Inst : Instr := Read_Instruction(Get_Line(File));
|
|
begin
|
|
for I in Inst.X0 .. Inst.X1 loop
|
|
for J in Inst.Y0 .. Inst.Y1 loop
|
|
case Inst.Inst is
|
|
when None =>
|
|
raise Parse_Error with "Cannot have none instruction";
|
|
when Toggle =>
|
|
Lights(I,J) := @ + 2;
|
|
when Turn_On =>
|
|
Lights(I,J) := @ + 1;
|
|
when Turn_Off =>
|
|
Lights(I,J) := Natural'Max(0, @ - 1);
|
|
end case;
|
|
end loop;
|
|
end loop;
|
|
end;
|
|
end loop;
|
|
|
|
for I in 0 .. 999 loop
|
|
for J in 0 .. 999 loop
|
|
Sum := @ + Lights(I,J);
|
|
end loop;
|
|
end loop;
|
|
|
|
Close(File);
|
|
|
|
return Sum;
|
|
end Day_1_2;
|
|
|
|
File_Name : String := "input_day_6.txt";
|
|
begin
|
|
Put_Line("Christmas lights on" & Day_1_1(File_Name)'Image);
|
|
Put_Line("Christmas lights on" & Day_1_2(File_Name)'Image);
|
|
end Day_6;
|