From 03f0d3ed296ebe2b85c7bcfe09c06a388c5f1db0 Mon Sep 17 00:00:00 2001 From: Folkert Kevelam Date: Sat, 22 Mar 2025 14:47:45 +0100 Subject: [PATCH] Solution for day 4 part 1 and part 2 --- AoC/2015/day_4/day_4.adb | 209 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 AoC/2015/day_4/day_4.adb diff --git a/AoC/2015/day_4/day_4.adb b/AoC/2015/day_4/day_4.adb new file mode 100644 index 0000000..f41d493 --- /dev/null +++ b/AoC/2015/day_4/day_4.adb @@ -0,0 +1,209 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Interfaces; + +procedure Day_4 is + + type Uint32 is mod 2**32; + type Uint64 is mod 2**64; + type Uint128 is mod 2**128; + type Byte is range 0 .. 2**8 -1; + for Byte'Size use 8; + + package Uint128_IO is new Ada.Text_IO.Modular_IO( Uint128 ); + package Uint32_IO is new Ada.Text_IO.Modular_IO( Uint32 ); + + type Byte_Array is array (Natural range <>) of Byte; + + type Uint32_Array is array (Natural range <>) of Uint32; + + function Hex( Num : Uint32 ) return String is + Str : String( 1 .. 8 ); + Tally : Uint32 := Num; + Temp : Uint32; + begin + for I in reverse Str'Range loop + Temp := Tally mod 16; + case Temp is + when 0 .. 9 => Str(I) := Character'Val(48 + Temp); + when 10 .. 15 => Str(I) := Character'val(65 + (Temp - 10)); + when others => Str(I) := 'x'; + end case; + Tally := Tally / 16; + end loop; + + return Str; + end Hex; + + function Pad( Key : String ) return Byte_Array is + Size : Natural := Key'Length; + Mod_Size : Natural := Size mod 64; + Pad_Size : Natural; + Original : Uint64 := Uint64(Size) * 8; + begin + + if Mod_Size <= 55 then + Pad_Size := 55 - Mod_Size; + else + Pad_Size := (63 - Mod_Size) + 56; + end if; + + declare + B : Byte_Array( 0 .. Pad_Size + Size + 8); + begin + for I in Key'Range loop + B(I-1) := Byte(Character'Pos(Key(I))); + end loop; + + B(Key'Last) := 16#80#; + + for I in 1 .. Pad_Size loop + B(Key'Last + I) := 0; + end loop; + + for I in 0 .. 7 loop + B(B'Last - (7-I)) := Byte((Original / 2**(8*I)) and 16#FF#); + end loop; + + return B; + end; + + end Pad; + + function MD5( Key : String ) return Uint128 is + S : Uint32_Array( 0 .. 63 ) := ( + 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, + 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, + 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, + 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 + ); + + K : Uint32_Array( 0 .. 63 ) := ( + 16#d76aa478#, 16#e8c7b756#, 16#242070db#, 16#c1bdceee#, + 16#f57c0faf#, 16#4787c62a#, 16#a8304613#, 16#fd469501#, + 16#698098d8#, 16#8b44f7af#, 16#ffff5bb1#, 16#895cd7be#, + 16#6b901122#, 16#fd987193#, 16#a679438e#, 16#49b40821#, + 16#f61e2562#, 16#c040b340#, 16#265e5a51#, 16#e9b6c7aa#, + 16#d62f105d#, 16#02441453#, 16#d8a1e681#, 16#e7d3fbc8#, + 16#21e1cde6#, 16#c33707d6#, 16#f4d50d87#, 16#455a14ed#, + 16#a9e3e905#, 16#fcefa3f8#, 16#676f02d9#, 16#8d2a4c8a#, + 16#fffa3942#, 16#8771f681#, 16#6d9d6122#, 16#fde5380c#, + 16#a4beea44#, 16#4bdecfa9#, 16#f6bb4b60#, 16#bebfbc70#, + 16#289b7ec6#, 16#eaa127fa#, 16#d4ef3085#, 16#04881d05#, + 16#d9d4d039#, 16#e6db99e5#, 16#1fa27cf8#, 16#c4ac5665#, + 16#f4292244#, 16#432aff97#, 16#ab9423a7#, 16#fc93a039#, + 16#655b59c3#, 16#8f0ccc92#, 16#ffeff47d#, 16#85845dd1#, + 16#6fa87e4f#, 16#fe2ce6e0#, 16#a3014314#, 16#4e0811a1#, + 16#f7537e82#, 16#bd3af235#, 16#2ad7d2bb#, 16#eb86d391# + ); + + A0 : Uint32 := 16#67452301#; + B0 : Uint32 := 16#efcdab89#; + C0 : Uint32 := 16#98badcfe#; + D0 : Uint32 := 16#10325476#; + + Data : Byte_Array := Pad(Key); + + Output : Uint128 := 0; + + begin + + for I in 0 .. (Data'Length / 64) - 1 loop + declare + M : Uint32_Array( 0 .. 15 ); + A : Uint32 := A0; + B : Uint32 := B0; + C : Uint32 := C0; + D : Uint32 := D0; + F : Uint32; + G : Uint32; + begin + for J in 0 .. 15 loop + declare + Index : Integer := (I*64) + (J*4); + begin + M(J) := Uint32(Data(Index)); + M(J) := @ + Uint32(Data(Index + 1)) * 2**8; + M(J) := @ + Uint32(Data(Index + 2)) * 2**16; + M(J) := @ + Uint32(Data(Index + 3)) * 2**24; + end; + end loop; + + + for J in 0 .. 63 loop + if J >= 0 and J <= 15 then + F := (B and C) or ((not B) and D); + G := Uint32(J); + elsif J >= 16 and J <= 31 then + F := (D and B) or ((not D) and C); + G := (5*Uint32(J) + 1) mod 16; + elsif J >= 32 and J <= 47 then + F := B xor C xor D; + G := (3*Uint32(J) + 5) mod 16; + else + F := C xor (B or (not D)); + G := (7*Uint32(J)) mod 16; + end if; + F := F + A + K(J) + M(Integer(G)); + A := D; + D := C; + C := B; + B := B + Uint32( + Interfaces.Rotate_Left( + Interfaces.Unsigned_32(F), Natural(S(J)))); + + end loop; + + A0 := @ + A; + B0 := @ + B; + C0 := @ + C; + D0 := @ + D; + end; + end loop; + + declare + Output_Arr : Uint32_Array := [A0, B0, C0, D0]; + begin + for I in 0 .. 3 loop + declare + Nibble : Uint32 := Output_Arr(I); + begin + for J in 0 .. 3 loop + Output := (@ * 2**8) + Uint128(Nibble mod 2**8); + Nibble := @ / 2**8; + end loop; + end; + end loop; + end; + + return Output; + + end MD5; + + Base_Key : String := "yzbqklnj"; + Index : Positive := 1; + + MD5_Hash : Uint128; + +begin + + Uint128_IO.Put(MD5("a"), Base => 16); + New_Line; + + loop + declare + Num : String := Index'Image; + begin + Put_Line("Testing: " & Base_Key & Num(Num'First + 1 .. Num'Last)); + MD5_Hash := MD5(Base_Key & Num( Num'First + 1 .. Num'Last)); + Uint128_IO.Put(MD5_Hash, Base => 16); + New_Line; + end; + + exit when (MD5_Hash and 16#FFFFFF00000000000000000000000000#) = 0; + + Index := @ + 1; + end loop; + + Put_Line("Key is" & Index'Image); + +end Day_4;