with Ada.Text_IO; use Ada.Text_IO; with Ada.Containers; use Ada.Containers; with Ada.Containers.Hashed_Sets; procedure Day_3 is type Uint32 is mod 2**32; type Coordinate is record X : Uint32; Y : Uint32; end record; function "=" (A,B : Coordinate) return Boolean is begin return A.X = B.X and A.Y = B.Y; end "="; type Coordinates is array (Natural range <>) of Coordinate; function Hash(A : Uint32) return Uint32 is Key : Uint32 := A; begin Key := (not @) + (@ * 2**15); Key := @ or (@ / 2**12); Key := @ + (@ * 2**2); Key := @ or (@ / 2**4); Key := @ * 2057; Key := @ or (Key / 2**16); return Key; end Hash; function Hash(A : Coordinate) return Hash_Type is Result : UInt32 := Hash((53 + Hash(A.X)) * 53 + Hash(A.Y)); begin return Hash_Type(Integer(Result/2)); end Hash; package Set is new Ada.Containers.Hashed_Sets( Element_Type => Coordinate, Hash => Hash, Equivalent_Elements => "="); function Read_File(File_Name : String) return Set.Set is S : Set.Set; Base : Coordinate := ( X => 0, Y => 0); File : File_Type; begin S.Insert(Base); Open(File, In_File, File_Name); main_loop: while not End_Of_File(File) loop declare Line : String := Get_Line(File); begin for I in Line'Range loop case Line(I) is when '^' => Base.Y := @ + 1; when 'v' => Base.Y := @ - 1; when '>' => Base.X := @ + 1; when '<' => Base.X := @ - 1; when others => exit main_loop; end case; if not S.Contains(Base) then S.Insert(Base); end if; end loop; end; end loop main_loop; Close(File); return S; end Read_File; function Read_File_Part_Two(File_Name : String) return Set.Set is S : Set.Set; Base : Coordinates(0 .. 1) := (others => (X => 0, Y => 0)); File : File_Type; Santa : Natural := 0; begin S.Insert(Base(0)); Open(File, In_File, File_Name); main_loop: while not End_Of_File(File) loop declare Line : String := Get_Line(File); begin for I in Line'Range loop case Line(I) is when '^' => Base(Santa).Y := @ + 1; when 'v' => Base(Santa).Y := @ - 1; when '>' => Base(Santa).X := @ + 1; when '<' => Base(Santa).X := @ - 1; when others => exit main_loop; end case; if not S.Contains(Base(Santa)) then S.Insert(Base(Santa)); end if; Santa := (@ + 1) mod 2; end loop; end; end loop main_loop; Close(File); return S; end Read_File_Part_Two; File_Name : String := "input_day_3.txt"; S : Set.Set; begin Put_Line(Read_File_Part_Two(File_Name).Length'Image); end Day_3;