121 lines
3.3 KiB
Ada
121 lines
3.3 KiB
Ada
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;
|