public static int Part2(string input = null) { input ??= Input.ReadAllText(nameof(Day19)); var inputParts = input.Split("\n\n", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); var ruleStrings = inputParts[0].Split("\n"); var messages = inputParts[1] .Split("\n", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); var rules = CreateRules(ruleStrings); rules[11] = Rule.Parse("11: 42 31 | 42 11 31"); rules[8] = Rule.Parse("8: 42 | 42 8"); var valid = 0; foreach (var message in messages) { if (GenerateVariants(0, rules, message).Contains(message)) { valid++; } } return(valid); }
public static Dictionary <int, Rule> CreateRules(string[] ruleStrings) { var rules = new Dictionary <int, Rule>(); foreach (var ruleString in ruleStrings) { var rule = Rule.Parse(ruleString); rules.Add(rule.Id, rule); } return(rules); }
public int ComputePart1(IEnumerable <string> input = null) { input = input ?? LoadRawData(); var parts = string.Join("\n", input).Split("\n\n"); var rules = parts[0].Split("\n").Select(x => Rule.Parse(x)); var otherTickets = parts[2].Split("\n") .Skip(1) .Select(x => Ticket.Parse(x)) .ToArray(); var invalidValues = otherTickets .SelectMany(ticket => ticket.GetInvalidValues(rules)); return(invalidValues.Sum()); }
public long ComputePart2(IEnumerable <string> input = null) { input = input ?? LoadRawData(); var parts = string.Join("\n", input).Split("\n\n"); var rules = parts[0].Split("\n").Select(x => Rule.Parse(x)).ToArray(); var myTicket = Ticket.Parse(parts[1].Split("\n")[1]); var otherTickets = parts[2].Split("\n") .Skip(1) .Select(x => Ticket.Parse(x)) .ToArray(); var validTickets = otherTickets .Where(x => x.GetIsValid(rules)) .ToArray(); var ticketWidth = validTickets[0].Fields.Count(); var allPositions = (1 << ticketWidth) - 1; var powersOfTwo = Enumerable.Range(0, ticketWidth) .Select(x => 1 << x) .ToHashSet(); var ruleOptions = Enumerable .Repeat(allPositions, ticketWidth) .ToArray(); var found = 0; foreach (var ticket in validTickets) { foreach (var(rule, ruleNo) in rules.Select((r, idx) => (r, idx))) { var opts = ruleOptions[ruleNo]; if (!powersOfTwo.Contains(opts)) { opts = opts & ticket.MapRule(rule); } ruleOptions[ruleNo] = opts; if (powersOfTwo.Contains(opts)) { found = found | opts; } } found = ReduceOptions(ruleOptions, found, powersOfTwo); } ReduceOptions(ruleOptions, found, powersOfTwo); if (ruleOptions.Except(powersOfTwo).Any()) { throw new System.Exception("didn't filter them all!"); } var ruleIndexes = ruleOptions .Select(x => (int)System.Math.Log2(x)) .ToArray(); var rulesInOrder = ruleIndexes .Zip(rules, (idx, rule) => new { idx, rule }) .OrderBy(x => x.idx) .ToArray(); foreach (var(ticket, ticketIdx) in validTickets.Select((x, idx) => (x, idx))) { foreach (var(rule, val) in rulesInOrder.Zip(ticket.Fields, (r, v) => (r, v))) { if (!rule.rule.Contains(val)) { throw new System.Exception($"rule {rule.rule.Name} at position {rule.idx} does not match value {val} on ticket {ticketIdx + 1}"); } } } var departureRuleIndexes = rulesInOrder .Where(x => x.rule.Name.StartsWith("departure")) .Select(x => x.idx) .ToArray(); var departureValues = myTicket.Fields .Select((val, idx) => new { val, idx }) .Where(x => departureRuleIndexes.Contains(x.idx)) .Select(x => x.val) .ToArray(); return(departureValues.Aggregate(1L, (p, v) => p * v)); }