180 lines
5.4 KiB
Ada
180 lines
5.4 KiB
Ada
with Ada.Text_IO; use Ada.Text_IO;
|
|
with Ada.Numerics.Elementary_Functions; use Ada.Numerics.Elementary_Functions;
|
|
with Ada.Containers.Generic_Array_Sort;
|
|
with Ada.Containers.Vectors;
|
|
|
|
procedure Day_1 is
|
|
|
|
type Index is new Natural;
|
|
type Input is array ( Index range <>) of Integer;
|
|
type Count is new Natural;
|
|
|
|
type Counted_Data is
|
|
record
|
|
Data : Integer;
|
|
Data_Count : Count;
|
|
end record;
|
|
|
|
type Count_Array is array (Index range <> ) of Counted_Data;
|
|
|
|
function Day_1_1( Left, Right : Input ) return Integer is
|
|
Sorted_Left : Input := Left;
|
|
Sorted_Right : Input := Right;
|
|
|
|
Score : Integer := 0;
|
|
|
|
procedure Sort is
|
|
new Ada.Containers.Generic_Array_Sort(Index, Integer, Input);
|
|
begin
|
|
|
|
Sort(Sorted_Left);
|
|
Sort(Sorted_Right);
|
|
|
|
for I in Sorted_Left'Range loop
|
|
Score := @ + abs(Sorted_Left(I) - Sorted_Right(I));
|
|
end loop;
|
|
|
|
return Score;
|
|
|
|
end Day_1_1;
|
|
|
|
function Sort_And_Deduplicate( Arr : Input ) return Count_Array is
|
|
Sorted : Input := Arr;
|
|
Out_Arr : Count_Array( Index'First .. Arr'Length );
|
|
Arr_Index : Index := Index'First;
|
|
In_Index : Index := Index'First;
|
|
|
|
procedure Sort is
|
|
new Ada.Containers.Generic_Array_Sort(Index, Integer, Input);
|
|
begin
|
|
Sort(Sorted);
|
|
|
|
Out_Arr(Arr_Index).Data := Sorted(Index'First);
|
|
Out_Arr(Arr_Index).Data_Count := 0;
|
|
|
|
for I in Index'First .. (Index'First + Arr'Length - 1) loop
|
|
if( Sorted(I) = Out_Arr(Arr_Index).Data) then
|
|
Out_Arr(Arr_Index).Data_Count := @ + 1;
|
|
else
|
|
Arr_Index := @ + 1;
|
|
Out_Arr(Arr_Index).Data := Sorted(I);
|
|
Out_Arr(Arr_Index).Data_Count := 1;
|
|
end if;
|
|
end loop;
|
|
|
|
return Out_Con : Count_Array(Index'First .. Arr_Index) do
|
|
for I in Index'First .. Arr_Index loop
|
|
Out_Con(I) := Out_Arr(I);
|
|
end loop;
|
|
end return;
|
|
end Sort_And_Deduplicate;
|
|
|
|
function Find( Num : Integer; Arr : Count_Array ) return Count is
|
|
Lower_Bound : Index := Index'First;
|
|
Upper_Bound : Index := Arr'Length - 1;
|
|
Upper : Integer := 1 + Integer(Log(Float(Arr'Length), 2.0));
|
|
Mid : Index;
|
|
begin
|
|
for I in 0 .. Upper loop
|
|
if Upper_Bound - Lower_Bound <= 1 then
|
|
if Num = Arr(Upper_Bound).Data then
|
|
return Arr(Upper_Bound).Data_Count;
|
|
elsif Num = Arr(Upper_Bound).Data then
|
|
return Arr(Upper_Bound).Data_Count;
|
|
else
|
|
return 0;
|
|
end if;
|
|
end if;
|
|
|
|
Mid := (Upper_Bound + Lower_Bound) / 2;
|
|
if Num > Arr(Mid).Data then
|
|
Lower_Bound := Mid;
|
|
elsif Num < Arr(Mid).Data then
|
|
Upper_Bound := Mid;
|
|
else
|
|
return Arr(Mid).Data_Count;
|
|
end if;
|
|
end loop;
|
|
|
|
return 0;
|
|
end Find;
|
|
|
|
function Day_1_2( Left, Right : Input ) return Integer is
|
|
C_Left : Count_Array := Sort_And_Deduplicate(Left);
|
|
C_Right : Count_Array := Sort_And_Deduplicate(Right);
|
|
Score : Integer := 0;
|
|
begin
|
|
|
|
for I in C_Left'Range loop
|
|
declare
|
|
D : Integer := Integer(Find(C_Left(I).Data, C_Right));
|
|
C : Integer := Integer(C_Left(I).Data_Count);
|
|
begin
|
|
Score := @ + D * C * C_Left(I).Data;
|
|
end;
|
|
end loop;
|
|
|
|
return Score;
|
|
|
|
end Day_1_2;
|
|
|
|
type Array2( Count : Index ) is
|
|
record
|
|
Left : Input( 0 .. Count);
|
|
Right : Input( 0 .. Count);
|
|
end record;
|
|
|
|
function Read_Arrays_Into_File( Filename : String ) return Array2 is
|
|
File : File_Type;
|
|
|
|
package Vec is new Ada.Containers.Vectors( Index, Integer );
|
|
use Vec;
|
|
|
|
Left : Vec.Vector;
|
|
Right : Vec.Vector;
|
|
begin
|
|
Open(File, In_File, Filename);
|
|
|
|
while not End_Of_File(File) loop
|
|
declare
|
|
Line : String := Get_Line(File);
|
|
Start_First : Integer := Line'First;
|
|
End_First : Integer := 0;
|
|
Start_Second : Integer := 0;
|
|
End_Second : Integer := Line'Last;
|
|
Index : Integer := Line'First;
|
|
begin
|
|
while Line(Index) /= ' ' loop
|
|
Index := @ + 1;
|
|
end loop;
|
|
End_First := Index - 1;
|
|
while Line(Index) = ' ' loop
|
|
Index := @ + 1;
|
|
end loop;
|
|
Start_Second := Index;
|
|
Left.Append(
|
|
Integer'Value(Line(Start_First .. End_First)));
|
|
Right.Append(
|
|
Integer'Value(Line(Start_Second .. End_Second)));
|
|
end;
|
|
end loop;
|
|
|
|
Close(File);
|
|
|
|
return Out_Arr : Array2( Index(Left.Length) ) do
|
|
for I in Left.First_Index .. Left.Last_Index loop
|
|
Out_Arr.Left(I) := Left(I);
|
|
Out_Arr.Right(I) := Right(I);
|
|
end loop;
|
|
end return;
|
|
|
|
end Read_Arrays_Into_File;
|
|
|
|
Filename : String := "input_day_1_1.txt";
|
|
|
|
Data : Array2 := Read_Arrays_Into_File(Filename);
|
|
begin
|
|
Put_Line("Sum score: " & Day_1_1(Data.Left, Data.Right)'Image);
|
|
Put_Line("Simi score: " & Day_1_2(Data.Left, Data.Right)'Image);
|
|
end Day_1;
|