|
|
@@ -0,0 +1,90 @@
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Security.Cryptography;
|
|
|
+using System.Text;
|
|
|
+
|
|
|
+namespace D14._1
|
|
|
+{
|
|
|
+ class Program
|
|
|
+ {
|
|
|
+ static byte[] ToB(string str) => Encoding.ASCII.GetBytes(str);
|
|
|
+ static string ToS(byte[] b) => BitConverter.ToString(b).Replace("-", "").ToLower();
|
|
|
+
|
|
|
+ static bool HasQuintuplet(string str, char c)
|
|
|
+ {
|
|
|
+ for (int i = 4; i < str.Length; ++i)
|
|
|
+ if (str[i - 4] == str[i - 3] && str[i - 3] == str[i - 2] && str[i - 2] == str[i - 1] && str[i - 1] == str[i] && str[i] == c)
|
|
|
+ return true;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ static char? HasTriplet(string str)
|
|
|
+ {
|
|
|
+ for (int i = 2; i < str.Length; ++i)
|
|
|
+ if (str[i - 2] == str[i - 1] && str[i - 1] == str[i])
|
|
|
+ return str[i];
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ static void Main(string[] args)
|
|
|
+ {
|
|
|
+ if (args.Length < 1) throw new ArgumentException();
|
|
|
+ string input = args[0];
|
|
|
+
|
|
|
+ int index1 = GetHashes(input, 0);
|
|
|
+ Console.WriteLine($"Index for Part 1 is : {index1}");
|
|
|
+
|
|
|
+ int index2 = GetHashes(input, 2016);
|
|
|
+ Console.WriteLine($"Index for Part 2 is : {index2}");
|
|
|
+ }
|
|
|
+
|
|
|
+ static Dictionary<int, string> cache = new Dictionary<int, string>();
|
|
|
+ private static int GetHashes(string input, int stretching)
|
|
|
+ {
|
|
|
+ cache.Clear();
|
|
|
+ int index = -1;
|
|
|
+
|
|
|
+ using (var md5 = MD5.Create())
|
|
|
+ {
|
|
|
+ var found = 0;
|
|
|
+
|
|
|
+ while (found < 64)
|
|
|
+ {
|
|
|
+ index++;
|
|
|
+
|
|
|
+ string hash = TryGetHash(input, index, md5, stretching);
|
|
|
+
|
|
|
+ var triplet = HasTriplet(hash);
|
|
|
+ if (triplet.HasValue == false) continue;
|
|
|
+
|
|
|
+ for (var i = index + 1; i < index + 1000; ++i)
|
|
|
+ {
|
|
|
+ string h = TryGetHash(input, i, md5, stretching);
|
|
|
+ if (HasQuintuplet(h, triplet.Value))
|
|
|
+ {
|
|
|
+ found++;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return index;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static string TryGetHash(string input, int index, MD5 md5, int stretching)
|
|
|
+ {
|
|
|
+ if (cache.ContainsKey(index)) return cache[index];
|
|
|
+ var hash = GetHash(input, index, md5, stretching);
|
|
|
+ cache.Add(index, hash);
|
|
|
+ return hash;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static string GetHash(string input, int index, MD5 md5, int stretching)
|
|
|
+ {
|
|
|
+ var hash = ToS(md5.ComputeHash(ToB($"{input}{index}")));
|
|
|
+ for (var i = 0; i < stretching; ++i) hash = ToS(md5.ComputeHash(ToB(hash)));
|
|
|
+ return hash;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|