public double Evaluate(IEnumerable <PieceData> pieces) { HashSet <PieceData> hasChecked = new HashSet <PieceData>(); List <int> counts = new List <int>(); foreach (var piece in pieces) { if (piece == null) { continue; } if (piece.m_shape != m_shape) { continue; } if (hasChecked.Contains(piece)) { continue; } HashSet <PieceData> group = CombinationUtility.GetGroup(piece, x => x.m_shape == m_shape); counts.Add(group.Count); hasChecked.UnionWith(group); } return((counts.Count == 0) ? 0 : counts.Average()); }
public double Evaluate(IEnumerable <PieceData> pieces) { HashSet <PieceData> hasChecked = new HashSet <PieceData>(); List <int> counts = new List <int>(); foreach (var piece in pieces) { if (piece == null) { continue; } if (piece.m_shape != m_shape) { continue; } if (hasChecked.Contains(piece)) { continue; } HashSet <PieceData> group = CombinationUtility.GetGroup(piece, x => x.m_shape == m_shape); counts.Add(group.Sum(x => x.m_positions.Length)); hasChecked.UnionWith(group); } OnGroupChecked?.Invoke(this, counts); var value = (counts.Count == 0) ? 0 : counts.Average(); OnEvaluated?.Invoke(this, value); return(value); }
public long CountViablePairsOfNodes() { List <Node> nodes = GetListOfNodes(); // Get all combinations var combinations = CombinationUtility.GetAllPermutationPairsOrderDoesNotMatter(nodes).ToList(); var matches = combinations.FindAll(t => (t.Item1.Used > 0 && t.Item2.Avail >= t.Item1.Used) || (t.Item2.Used > 0 && t.Item1.Avail >= t.Item2.Used)); return(matches.Count); }
public string ReversePasswordInstructions(string finalPassword) { // Brute force because my reverse logic was not working List <char> chars = finalPassword.ToList <char>(); var allPermutations = CombinationUtility.GetAllPermutationsToLength(chars, chars.Count); foreach (var set in allPermutations) { string potentialFirstPassword = string.Concat(set); string result = ProcessPasswordInstructions(potentialFirstPassword); if (result == finalPassword) { return(potentialFirstPassword); } } return(""); // Note that I ended up brute forcing the attempts as above. I originally tried to reverse the logic // but must have been missing something because I never got the correct solution, even though my individual // tests on the reversal worked. Leaving commented out for reference purposes. /* * string line; * List<string> instructions = new List<string>(); * StreamReader file = new StreamReader(@"TwentyOne\DayTwentyOneInput.txt"); * string password = initialPassword; * // Iterate over each line in the input * while ((line = file.ReadLine()) != null) * { * instructions.Add(line); * } * file.Close(); * * for (int i = instructions.Count - 1; i >= 0; i--) * { * password = HandleMovePosition(instructions[i], password, true); * password = HandleReverse(instructions[i], password); * password = HandleRotatePositionLetter(instructions[i], password, true); * password = HandleRotateSteps(instructions[i], password, true); * password = HandleSwapLetter(instructions[i], password); * password = HandleSwapPosition(instructions[i], password); * } * * return password; */ }
public long RecurseForSteps(List <Node> currentNodes, Node keyDataLocation, Node empty, long steps) { // Exit conditions if (keyDataLocation.Id == _target.Id) { return(1); } // Get all combinations of remaining valid moves to open a sector var combinations = CombinationUtility.GetAllPermutationPairsOrderDoesNotMatter(currentNodes).ToList(); var matches = combinations.FindAll(t => (t.Item1.CanMoveTo(t.Item2)) || (t.Item2.CanMoveTo(t.Item1))); foreach (var match in matches) { if (match.Item1.CanMoveTo(match.Item2)) { // Update values match.Item2.Used += match.Item1.Used; match.Item2.Avail -= match.Item1.Used; match.Item1.Used = 0; match.Item1.Avail = match.Item1.Size; empty = match.Item1; if (keyDataLocation.CanMoveTo(empty)) { Node holder = keyDataLocation; empty.Used += keyDataLocation.Used; empty.Avail -= keyDataLocation.Used; keyDataLocation.Used = 0; keyDataLocation.Avail = keyDataLocation.Size; keyDataLocation = empty; empty = holder; steps += 1; } steps += RecurseForSteps(currentNodes, keyDataLocation, empty, steps + 1); } if (match.Item2.CanMoveTo(match.Item1)) { // Update values match.Item1.Used += match.Item2.Used; match.Item1.Avail -= match.Item2.Used; match.Item2.Used = 0; match.Item2.Avail = match.Item2.Size; empty = match.Item2; if (keyDataLocation.CanMoveTo(empty)) { Node holder = keyDataLocation; empty.Used += keyDataLocation.Used; empty.Avail -= keyDataLocation.Used; keyDataLocation.Used = 0; keyDataLocation.Avail = keyDataLocation.Size; keyDataLocation = empty; empty = holder; steps += 1; } steps += RecurseForSteps(currentNodes, keyDataLocation, empty, steps + 1); } } return(steps); }