Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- void Main()
- {
- //test input test
- #region TestInput
- var input = new string[]
- {
- "Step C must be finished before step A can begin.",
- "Step C must be finished before step F can begin.",
- "Step A must be finished before step B can begin.",
- "Step A must be finished before step D can begin.",
- "Step B must be finished before step E can begin.",
- "Step D must be finished before step E can begin.",
- "Step F must be finished before step E can begin.",
- };
- #endregion
- if(solve(input, 1, 0).sequence != "CABDFE") throw new Exception("failed test a");
- if(solve(input, 2, 0) != ("CABFDE", 15)) throw new Exception("failed test b");
- //challenge
- var aoc = new AdventOfCode(2018, 7);
- aoc.SubmitAnswer(solve(aoc.InputLines, 1, 0).sequence, Part.A);
- aoc.SubmitAnswer(solve(aoc.InputLines, 5, 60).time, Part.B);
- }
- public (string sequence, int time) solve(string[] input, int workerCount, int extraTime)
- {
- //conver to (char, char)
- var lines = input.Select(x => x.ToArray()).Select(x => (x[5], x[36])).ToList();
- //items that still need work
- var stepsTodo = lines.SelectMany(x => new[] { x.Item1, x.Item2 }).Distinct().OrderBy(x => x).ToList();
- //store the result here
- string result = "";
- //keeps track of the time
- int time = 0;
- //track workers
- var activeWorkers = new List<(char workingOn, int timeLeft)>();
- //time stepsize
- int timestep = 1;
- //we return in here somwhere
- while(true)
- {
- //anything done?
- for(int i = 0; i < activeWorkers.Count; i++)
- {
- //move the worker forward in time
- activeWorkers[i] = (activeWorkers[i].workingOn, activeWorkers[i].timeLeft - timestep);
- //done?
- if(activeWorkers[i].timeLeft == 0)
- {
- //remove from rules
- lines = lines.Where(x=> x.Item1 != activeWorkers[i].workingOn).ToList();
- //add to result
- result += activeWorkers[i].workingOn;
- //remove from items left todo
- stepsTodo.Remove(activeWorkers[i].workingOn);
- //free worker, and move index 1 back because of removal
- activeWorkers.RemoveAt(i--);
- //are we done? then return result
- if(stepsTodo.Count == 0)
- return (result, time);
- }
- }
- //check each possible step if there are workers
- for (int a = 0; a < stepsTodo.Count && activeWorkers.Count < workerCount; a++)
- {
- //check if a step can be done
- if (StepValidForWork(stepsTodo[a]))
- {
- //hand step to a worker
- activeWorkers.Add((stepsTodo[a], (stepsTodo[a] - 64) + extraTime));
- }
- }
- //determine when the next timePoint of check is
- timestep = activeWorkers.Min(x => x.timeLeft);
- //move forward
- time += timestep;
- }
- bool StepValidForWork(char b)
- {
- //check if its not being worked on
- for(int i = 0; i < activeWorkers.Count; i++)
- if(activeWorkers[i].workingOn == b) return false;
- //check if a rule prohibts starting
- foreach (var change in lines)
- if (change.Item2 == b && stepsTodo.Contains(b)) return false;
- //no reason not to start
- return true;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment