This year, I’m posting my solutions to the puzzles in the Advent of Code.
Click the link to view the puzzle and code, along with a link to the solution on Github.
And now, on with the solution:
Day 21, part 1
Simplified Problem:
Modify a string based on the instructions in your puzzle input. Valid instructions are:
swap position X with position Y
means that the letters at indexesX
andY
(counting from0
) should be swapped.swap letter X with letter Y
means that the lettersX
andY
should be swapped (regardless of where they appear in the string).rotate left/right X steps
means that the whole string should be rotated; for example, one right rotation would turnabcd
intodabc
.rotate based on position of letter X
means that the whole string should be rotated to the right based on the index of letterX
(counting from0
) as determined before this instruction does any rotations. Once the index is determined, rotate the string to the right one time, plus a number of times equal to that index, plus one additional time if the index was at least4
.reverse positions X through Y
means that the span of letters at indexesX
throughY
(including the letters atX
andY
) should be reversed in order.move position X to position Y
means that the letter which is at indexX
should be removed from the string, then inserted such that it ends up at indexY
.
Following the instructions in the puzzle input, what is the output of scrambling abcdefgh
?
Day 21, Part 2
Using the same instructions, what was the input that produced fbgdceah?
Solution
For part 2, the inverse rotation code was taken from Reddit:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
class Program { #region Fields private static List<char> Input = "abcdefgh".ToList(); private static readonly string[] Instructions = File.ReadAllLines("input.txt"); private static readonly Regex NumberRegex = new Regex(@"\d+"); private static bool _isPartTwo; #endregion static void Main(string[] args) { // Part 1 foreach (string instruction in Instructions) { ProcessInstruction(instruction); } string message = $"Scrambled password: {new string(Input.ToArray())}"; Console.WriteLine(message); Debug.WriteLine(message); // Part 2 Input = "fbgdceah".ToList(); _isPartTwo = true; foreach (string instruction in Instructions.Reverse()) { ProcessInstruction(instruction); } message = $"Decrypted password: {new string(Input.ToArray())}"; Console.WriteLine(message); Debug.WriteLine(message); Console.ReadKey(); } static void ProcessInstruction(string instruction) { MatchCollection matches = NumberRegex.Matches(instruction); // Can't use a switch statement on substring. if (instruction.StartsWith("swap position")) { SwapPosXPosY(Convert.ToInt32(matches[0].Value), Convert.ToInt32(matches[1].Value)); return; } if (instruction.StartsWith("swap letter")) { string[] words = instruction.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries); SwapLetterWithLetter(words[2][0], words[5][0]); return; } if (instruction.StartsWith("rotate left")) { int steps = Convert.ToInt32(matches[0].Value); if (_isPartTwo) { RotateRight(steps); } else { RotateLeft(steps); } return; } if (instruction.StartsWith("rotate right")) { int steps = Convert.ToInt32(matches[0].Value); if (_isPartTwo) { RotateLeft(steps); } else { RotateRight(steps); } return; } if (instruction.StartsWith("rotate based")) { RotateOnPosition(instruction.Last()); return; } if (instruction.StartsWith("reverse")) { ReversePositionsXThroughY(Convert.ToInt32(matches[0].Value), Convert.ToInt32(matches[1].Value)); return; } // Only one instruction left - move position x to position y MovePosXToPosY(Convert.ToInt32(matches[_isPartTwo ? 1 : 0].Value), Convert.ToInt32(matches[_isPartTwo ? 0 : 1].Value)); } #region Scramblers static void SwapPosXPosY(int x, int y) { char temp = Input[x]; Input[x] = Input[y]; Input[y] = temp; } static void SwapLetterWithLetter(char a, char b) { int indexA = Input.IndexOf(a); int indexB = Input.IndexOf(b); char temp = Input[indexA]; Input[indexA] = Input[indexB]; Input[indexB] = temp; } static void RotateLeft(int steps) { for (var i = 0; i < steps; i++) { char temp = Input[0]; Input.RemoveAt(0); Input.Add(temp); } } static void RotateRight(int steps) { int index = Input.Count - 1; for (var i = 0; i < steps; i++) { char temp = Input[index]; Input.RemoveAt(index); Input.Insert(0, temp); } } static void RotateOnPosition(char c) { int index = Input.IndexOf(c); int steps = index + (index >= 4 ? 2 : 1); // Rotate index+1, +1 again if index>= 4 if (_isPartTwo) { // Inverse rotation - https://www.reddit.com/r/adventofcode/comments/5ji29h/2016_day_21_solutions/dbgkbpv/ switch (index) { case 0: case 1: RotateLeft(1); break; case 2: RotateRight(2); break; case 3: RotateLeft(2); break; case 4: RotateRight(1); break; case 5: RotateLeft(3); break; case 6: RotateRight(steps); break; case 7: RotateRight(4); break; } } else { RotateRight(steps); } } static void ReversePositionsXThroughY(int x, int y) { // Reverse parameters are index,count. // Without the +1, Reverse() misses a character. Input.Reverse(x, (y - x) + 1); } static void MovePosXToPosY(int x, int y) { char temp = Input[x]; Input.RemoveAt(x); Input.Insert(y, temp); } #endregion } |
You can find the full solution on Github