Program.cs 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Security.Cryptography;
  4. using System.Text;
  5. namespace D14._1
  6. {
  7. class Program
  8. {
  9. static byte[] ToB(string str) => Encoding.ASCII.GetBytes(str);
  10. static string ToS(byte[] b) => BitConverter.ToString(b).Replace("-", "").ToLower();
  11. static bool HasQuintuplet(string str, char c)
  12. {
  13. for (int i = 4; i < str.Length; ++i)
  14. 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)
  15. return true;
  16. return false;
  17. }
  18. static char? HasTriplet(string str)
  19. {
  20. for (int i = 2; i < str.Length; ++i)
  21. if (str[i - 2] == str[i - 1] && str[i - 1] == str[i])
  22. return str[i];
  23. return null;
  24. }
  25. static void Main(string[] args)
  26. {
  27. if (args.Length < 1) throw new ArgumentException();
  28. string input = args[0];
  29. int index1 = GetHashes(input, 0);
  30. Console.WriteLine($"Index for Part 1 is : {index1}");
  31. int index2 = GetHashes(input, 2016);
  32. Console.WriteLine($"Index for Part 2 is : {index2}");
  33. }
  34. static Dictionary<int, string> cache = new Dictionary<int, string>();
  35. private static int GetHashes(string input, int stretching)
  36. {
  37. cache.Clear();
  38. int index = -1;
  39. using (var md5 = MD5.Create())
  40. {
  41. var found = 0;
  42. while (found < 64)
  43. {
  44. index++;
  45. string hash = TryGetHash(input, index, md5, stretching);
  46. var triplet = HasTriplet(hash);
  47. if (triplet.HasValue == false) continue;
  48. for (var i = index + 1; i < index + 1000; ++i)
  49. {
  50. string h = TryGetHash(input, i, md5, stretching);
  51. if (HasQuintuplet(h, triplet.Value))
  52. {
  53. found++;
  54. break;
  55. }
  56. }
  57. }
  58. }
  59. return index;
  60. }
  61. private static string TryGetHash(string input, int index, MD5 md5, int stretching)
  62. {
  63. if (cache.ContainsKey(index)) return cache[index];
  64. var hash = GetHash(input, index, md5, stretching);
  65. cache.Add(index, hash);
  66. return hash;
  67. }
  68. private static string GetHash(string input, int index, MD5 md5, int stretching)
  69. {
  70. var hash = ToS(md5.ComputeHash(ToB($"{input}{index}")));
  71. for (var i = 0; i < stretching; ++i) hash = ToS(md5.ComputeHash(ToB(hash)));
  72. return hash;
  73. }
  74. }
  75. }