You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 lines
3.7 KiB

4 years ago
4 years ago
  1. using System;
  2. using static System.Console;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using Xunit;
  7. namespace AdventOfCode {
  8. public class Program {
  9. static string RootDir =
  10. Environment.GetEnvironmentVariable("HOME") + "/src/adventofcode/2020/";
  11. static List<int> ReadInts(string filename) {
  12. string[] lines = File.ReadAllLines(filename);
  13. return lines.Select(int.Parse).ToList();
  14. }
  15. static int Day1Part1(List<int> numbers) {
  16. for (var i = 0; i < numbers.Count; i++) {
  17. for (var j = i + 1; j < numbers.Count; j++) {
  18. if (numbers[i] + numbers[j] == 2020) {
  19. return numbers[i] * numbers[j];
  20. }
  21. }
  22. }
  23. throw new ArgumentException("no pair of numbers summed to 2020");
  24. }
  25. static int Day1Part2(List<int> numbers) {
  26. for (var i = 0; i < numbers.Count; i++) {
  27. for (var j = i + 1; j < numbers.Count; j++) {
  28. for (var k = j + 1; k < numbers.Count; k++) {
  29. if (numbers[i] + numbers[j] + numbers[k] == 2020) {
  30. return numbers[i] * numbers[j] * numbers[k];
  31. }
  32. }
  33. }
  34. }
  35. throw new ArgumentException("no triple of numbers summed to 2020");
  36. }
  37. [Fact]
  38. static void Day1Test() {
  39. var emptyInput = new List<int>();
  40. var bogusInput = new List<int>() {
  41. 111, 222, 333, 444, 555, 666, 777, 888, 999
  42. };
  43. var exampleInput = new List<int>() {
  44. 1721, 979, 366, 299, 675, 1456
  45. };
  46. var testInput = ReadInts(RootDir + "day1.txt");
  47. Assert.Throws<ArgumentException>(() => Day1Part1(emptyInput));
  48. Assert.Throws<ArgumentException>(() => Day1Part1(bogusInput));
  49. Assert.Equal(514579, Day1Part1(exampleInput));
  50. Assert.Equal(355875, Day1Part1(testInput));
  51. Assert.Throws<ArgumentException>(() => Day1Part2(emptyInput));
  52. Assert.Throws<ArgumentException>(() => Day1Part2(bogusInput));
  53. Assert.Equal(241861950, Day1Part2(exampleInput));
  54. Assert.Equal(140379120, Day1Part2(testInput));
  55. }
  56. static bool IsPasswordValid1(string spec) {
  57. string[] tokens = spec.Split(' ');
  58. string[] numbers = tokens[0].Split('-');
  59. int min = int.Parse(numbers[0]);
  60. int max = int.Parse(numbers[1]);
  61. char required = tokens[1][0];
  62. string password = tokens[2];
  63. int count = 0;
  64. for (int i = 0; i < password.Length; i++) {
  65. if (password[i] == required) {
  66. count++;
  67. }
  68. }
  69. return min <= count && count <= max;
  70. }
  71. static bool IsPasswordValid2(string spec) {
  72. string[] tokens = spec.Split(' ');
  73. string[] numbers = tokens[0].Split('-');
  74. int lowIndex = int.Parse(numbers[0]) - 1;
  75. int highIndex = int.Parse(numbers[1]) - 1;
  76. char required = tokens[1][0];
  77. string password = tokens[2];
  78. return
  79. (password[lowIndex] == required && password[highIndex] != required) ||
  80. (password[lowIndex] != required && password[highIndex] == required);
  81. }
  82. static int Day2Part1() {
  83. return File.ReadAllLines(RootDir + "day02.txt").Count(IsPasswordValid1);
  84. }
  85. static int Day2Part2() {
  86. return File.ReadAllLines(RootDir + "day02.txt").Count(IsPasswordValid2);
  87. }
  88. [Fact]
  89. static void Day2Test() {
  90. Assert.True(IsPasswordValid1("1-3 a: abcde"));
  91. Assert.False(IsPasswordValid1("1-3 b: cdefg"));
  92. Assert.True(IsPasswordValid1("2-9 c: ccccccccc"));
  93. Assert.Equal(603, Day2Part1());
  94. Assert.True(IsPasswordValid2("1-3 a: abcde"));
  95. Assert.False(IsPasswordValid2("1-3 b: cdefg"));
  96. Assert.False(IsPasswordValid2("2-9 c: ccccccccc"));
  97. Assert.Equal(404, Day2Part2());
  98. }
  99. static void Main(string[] args) {
  100. Day2Test();
  101. }
  102. }
  103. }