Example #1
0
        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);
        }
Example #2
0
        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);
        }
Example #3
0
        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());
        }
Example #4
0
        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));
        }