Advent Of Code Day 10: Backtracking and Dynamic Programming
Howdy Everyone,
Catching up on the Advent of Code, I got to day 10 today, here it is: Day 10 - Advent of Code 2020.
Description is a little long and tedious but in the end you get the gist of it. Part 1 is looking for a simple path from 0 to max. I looked at the input size and it did not seem that large, so I thought backtracking would do the trick. Indeed a simple straightforward DFS backtracking from 0 to max works. Part 2 asks for the count of ALL paths. That's a little tricky, especially after reading this part of the description:
You glance back down at your bag and try to remember why you brought so many adapters; there must be more than a trillion valid ways to arrange them! Surely, there must be an efficient way to count the arrangements.
That should give you the hint that the "adventers" are looking for a Dynamic Programming (DP) solution. Luckily, this DP is super simple, and the way that I like to implement DP is by construction from 0..max. Basically I start solving the problems for n=0, 1, 2, ..., max, using previously solved (and stored) solutions. Also worked well. Make sure to use a long for your DP solution storage as the number of paths will grow rather quickly. Code is below, cheers, ACC.
static void Main(string[] args) { FileInfo fi = new FileInfo("input.txt"); StreamReader sr = fi.OpenText(); Hashtable volts = new Hashtable(); int max = 0; while (!sr.EndOfStream) { string str = sr.ReadLine().Trim(); if (!String.IsNullOrEmpty(str)) { int n = Int32.Parse(str); max = Math.Max(max, n); volts.Add(n, true); } } sr.Close(); int[] diff = new int[4]; //Ignore diff[0] int totalUsed = 0; if (AdaptationPartOne(volts, 0, ref totalUsed, ref diff)) { Console.WriteLine("Found a path!"); for (int i = 1; i <= 3; i++) { Console.WriteLine("Diff of {0}: {1}", i, diff[i]); } long sol = diff[1]; sol *= diff[3]; Console.WriteLine("Solution: {0}", sol); } else { Console.WriteLine("Not path found!"); } long sol2 = AdaptationPartTwo(volts, max); Console.WriteLine("Number of combinations: {0}", sol2); } public static long AdaptationPartTwo(Hashtable volts, int max) { if (!volts.ContainsKey(0)) volts.Add(0, true); long[] dp = new long[max + 1]; dp[0] = 1; for (int i = 1; i <= max; i++) { if (volts.ContainsKey(i)) { for (int d = 1; d <= 3; d++) { if (i - d >= 0) { dp[i] += dp[i - d]; } } } } return dp[max]; } public static bool AdaptationPartOne(Hashtable volts, int currentVoltage, ref int totalUsed, ref int[] diff) { if (totalUsed == volts.Count) { //Account for the last device... diff[3]++; return true; } for (int i = 1; i <= 3; i++) { int next = currentVoltage + i; if (volts.ContainsKey(next) && (bool)volts[next]) { volts[next] = false; diff[i]++; totalUsed++; if (AdaptationPartOne(volts, next, ref totalUsed, ref diff)) return true; totalUsed--; diff[i]--; volts[next] = true; } } return false; }
Comments
Post a Comment