diff --git a/AoC/2015/day_6/day_6.adb b/AoC/2015/day_6/day_6.adb new file mode 100644 index 0000000..e98a331 --- /dev/null +++ b/AoC/2015/day_6/day_6.adb @@ -0,0 +1,214 @@ +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;