예제 #1
0
        protected override PartialResult SolveFirst()
        {
            var(Rules, _, NearbyTickets) = ParseInput(_input);

            var result = 0L;

            NearbyTickets.SelectMany(l => l.Select(n => n))
            .ToList()
            .ForEach(n => result += Rules.Values.SelectMany(l => l.Select(r => r))
                                    .All(r => !InRange(n, r)) ? n : 0);

            return(new PartialResult(1, result, Stopwatch.Elapsed));
        }
예제 #2
0
        protected override PartialResult SolveSecond()
        {
            var(Rules, MyTicket, NearbyTickets) = ParseInput(_input);

            // add my ticket to the nearby tickets
            NearbyTickets.Add(MyTicket);

            // remove the invalid tickets from collection of nearby's
            NearbyTickets.SelectMany(l => l.Select(n => n))
            .Where(n => Rules.Values.SelectMany(l => l.Select(r => r)).All(r => !InRange(n, r)))
            .ToList()
            .ForEach(n => NearbyTickets.RemoveAll(r => r.Contains(n)));

            // match each ticket column (number index) with each corresponding rule
            // there will be columns that matches several rules
            var rules = new Dictionary <string, List <int> >();

            foreach (var index in Enumerable.Range(0, Rules.Count()))
            {
                var column = NearbyTickets.Select(ticket => ticket[index]);

                foreach (var rule in Rules)
                {
                    if (column.All(n => rule.Value.Any(r => InRange(n, r))))
                    {
                        if (rules.ContainsKey(rule.Key))
                        {
                            rules[rule.Key].Add(index);
                        }
                        else
                        {
                            rules.Add(rule.Key, new List <int> {
                                index
                            });
                        }
                    }
                }
            }

            // as long as there are rules which can be applied to more than one ticket column,
            // eliminate them one by one until there are only rules that applies to one
            // ticket column only (hence the use of single - fail fast if something un-
            // predicted should occur)
            while (rules.Select(r => r.Value).Any(l => l.Count() > 1))
            {
                foreach (var rule in rules.Where(r => r.Value.Count() == 1))
                {
                    rules.Where(kv => kv.Value.Contains(rule.Value.Single()) && kv.Value.Count() > 1)
                    .Select(r => r.Key)
                    .ToList()
                    .ForEach(key => rules.Where(r => Equals(key, r.Key))
                             .Select(r => r.Value)
                             .ToList()
                             .ForEach(l => l.Remove(rule.Value.Single())));
                }
            }

            // it's time to extract out result - find the rules who begins with the word
            // "departure". for each of those corresponding indexes - multiply the ticket
            // value for each said index from MyTicket
            var result = 1L;

            rules.Where(r => r.Key.StartsWith("departure"))
            .SelectMany(r => r.Value.Select(n => n))
            .ToList()
            .ForEach(n => result *= MyTicket[n]);

            return(new PartialResult(2, result, Stopwatch.Elapsed));
        }