public List <LuggageRule> ParseRules(List <string> rules)
    {
        var luggageRules = new List <LuggageRule>();

        foreach (var line in rules)
        {
            var parts           = line.Split("bags contain");
            var color           = parts[0].Trim();
            var luggageRule     = new LuggageRule(color);
            var requiredContent = parts[1].Split(",");
            foreach (var requiredBag in requiredContent)
            {
                if (requiredBag.Contains("no other bags"))
                {
                    continue;
                }
                var bagParts            = requiredBag.Trim(' ').Split(" ");
                var requiredBagQuantity = Int32.Parse(bagParts[0]);
                var bagColor            = bagParts[1] + " " + bagParts[2];

                var bagContent = new BagContent(bagColor, requiredBagQuantity);
                luggageRule.RequiredContent.Add(bagContent);
            }
            luggageRules.Add(luggageRule);
        }

        return(luggageRules);
    }
예제 #2
0
        async static Task Main(string[] args)
        {
            var containsRegex =
                new Regex(
                    "(?'tag'[a-z\\s]+)\\sbags\\scontain(?:\\s(?'bagcount'[0-9]+)\\s(?'bagtype'[a-z\\s]+)\\sbag[s]?,)*\\s(?'bagcount'[0-9])\\s(?'bagtype'[a-z\\s]+)\\sbag[s]?\\.",
                    RegexOptions.Compiled);
            var noBagsRegex = new Regex("(?'tag'[a-z\\s]+)\\sbags\\scontain\\sno\\sother\\sbags\\.",
                                        RegexOptions.Compiled);

            using var file   = new FileStream("input.txt", FileMode.Open);
            using var reader = new StreamReader(file);

            var bagDescriptors = new List <BagDescriptor>();

            while (true)
            {
                var line = await reader.ReadLineAsync();

                if (line == null)
                {
                    break;
                }

                var contents = default(BagContent[]);
                var name     = default(string?);
                var match    = containsRegex.Match(line);
                if (match.Success)
                {
                    name = match.Groups["tag"].Value;
                    var countCaptures = match.Groups["bagcount"].Captures;
                    var typeCaptures  = match.Groups["bagtype"].Captures;
                    if (countCaptures.Count != typeCaptures.Count)
                    {
                        throw new Exception("Bagcontent mismatch");
                    }

                    contents = countCaptures
                               .Zip(typeCaptures, (a, b) => (count: int.Parse(a.Value), type: b.Value))
                               .Select(c => new BagContent(c.count, c.type))
                               .ToArray();
                }
                else
                {
                    match = noBagsRegex.Match(line);
                    if (match.Success)
                    {
                        name     = match.Groups["tag"].Value;
                        contents = new BagContent[0];
                    }
                    else
                    {
                        throw new Exception("Unknown line");
                    }
                }

                bagDescriptors.Add(new BagDescriptor(name, contents));
            }

            var bagNodes = bagDescriptors
                           .Select(bd => new BagNode {
                Name = bd.Name
            })
                           .ToDictionary(b => b.Name, b => b);

            foreach (var descriptor in bagDescriptors)
            {
                var outsideBag = bagNodes[descriptor.Name];
                foreach (var content in descriptor.Content)
                {
                    var insideBag = bagNodes[content.Bagname];
                    var edge      = new BagEdge(outsideBag, insideBag, content.Count);
                    outsideBag.OutgoingEdges.Add(edge);
                    insideBag.IncomingEdges.Add(edge);
                }
            }

            var workQueue = new Queue <BagNode>();
            var initial   = bagNodes["shiny gold"];

            workQueue.Enqueue(initial);
            while (workQueue.Any())
            {
                var entry = workQueue.Dequeue();
                entry.Marked = true;
                foreach (var edge in entry.IncomingEdges)
                {
                    if (!edge.ContainingNode.Marked)
                    {
                        workQueue.Enqueue(edge.ContainingNode);
                    }
                }
            }

            var numReached = bagNodes.Count(kvp => kvp.Value.Marked) - 1;

            Console.WriteLine(numReached);

            var bagCounter   = 0;
            var contentQueue = new Queue <(BagNode item, int multiplier)>();

            contentQueue.Enqueue((initial, 1));
            while (contentQueue.Any())
            {
                var entry = contentQueue.Dequeue();
                foreach (var edge in entry.item.OutgoingEdges)
                {
                    bagCounter += edge.Count * entry.multiplier;
                    contentQueue.Enqueue((edge.ContentNode, entry.multiplier * edge.Count));
                }
            }
            Console.WriteLine(bagCounter);
        }
예제 #3
0
        static void Main(string[] args)
        {
            var lines = File.ReadAllLines("input.txt");

            var listOfBags  = new List <Bag>();
            var baseColours = new List <Bag>();

            // Grab all of the distinct bag names to give us a place to start
            foreach (var line in lines)
            {
                var components   = line.Split("contain");
                var bagColourRaw = components[0];
                var bagColour    = bagColourRaw.Substring(0, bagColourRaw.Length - 6); // -4 because "bags", 2 for spaces

                if (!baseColours.Any(b => b.Colour == bagColour))
                {
                    baseColours.Add(new Bag()
                    {
                        Colour = bagColour
                    });
                }
            }

            // baseColours now has a list of Bags that have all the top level colours

            // now need to iterate again to fill up each Bag with the correct contents, using existing Bag refs as
            // the content for the bags

            // Step through it all again but this time add bags to the list using references saved from above
            // Might be able to do this in one loop, but making the assumption that the contents of
            // the input file is NOT in order. If it is in order, can do this in one loop
            foreach (var line in lines)
            {
                var components   = line.Split("contain");
                var bagColourRaw = components[0];
                var bagColour    = bagColourRaw.Substring(0, bagColourRaw.Length - 6); // -4 because "bags", 2 for spaces

                var contentColours = components[1];

                var baseBag = baseColours.First(b => b.Colour == bagColour);
                if (contentColours.Trim() == "no other bags.")
                {
                    listOfBags.Add(baseBag);
                    continue;
                }

                var contentBagsRaw = contentColours.Split(',');

                foreach (var content in contentBagsRaw)
                {
                    var cnt      = content.Trim();
                    var pieces   = cnt.Split(' ');
                    var quantity = pieces[0];
                    var colour   = pieces[1] + " " + pieces[2];

                    var bag = baseColours.First(v => v.Colour == colour);

                    var bagContent = new BagContent()
                    {
                        Bag      = bag,
                        Quantity = Convert.ToInt32(quantity)
                    };

                    baseBag.Contents.Add(bagContent);
                }
                listOfBags.Add(baseBag);
            }

            // By here the list is fully populate with nodes that reference bags properly

            var numberOfBagsContainingAtLeastOne = 0;

            foreach (var bag in listOfBags)
            {
                // Solution for Part 2
                if (bag.Colour == "shiny gold")
                {
                    var amountInThisBag = CountBags(bag.Contents);
                    Console.WriteLine("Shiny gold:" + amountInThisBag);
                }
                // Solution for Part 1
                else
                {
                    var amountInThisBag = CountContent("shiny gold", bag.Contents);
                    if (amountInThisBag > 0)
                    {
                        numberOfBagsContainingAtLeastOne++;
                    }
                }
            }

            Console.WriteLine(numberOfBagsContainingAtLeastOne);
        }