Exemple #1
0
        private long produce(Chemical chemical, long amount)
        {
            if (chemical.Name == "FUEL")
            {
                foreach (Chemical chemicalClean in chemicals)
                {
                    chemicalClean.AmountAvailable = 0;
                }
            }

            long oreAmount = 0;

            if (chemical.AmountAvailable >= amount)
            {
                chemical.AmountAvailable -= amount;
                return(oreAmount);
            }

            if (chemical.AmountAvailable > 0)
            {
                amount -= chemical.AmountAvailable;
                chemical.AmountAvailable = 0;
            }

            long amountOfReactions;

            if (amount <= chemical.ReactionToProduce.Output.Item2)
            {
                amountOfReactions = 1;
            }
            else
            {
                amountOfReactions = amount / chemical.ReactionToProduce.Output.Item2;

                if (amount % chemical.ReactionToProduce.Output.Item2 != 0)
                {
                    amountOfReactions += 1;
                }
            }

            foreach (var input in chemical.ReactionToProduce.Inputs)
            {
                long amountNeeded = input.Value * amountOfReactions;

                if (input.Key.Name == "ORE")
                {
                    oreAmount += amountNeeded;
                }
                else
                {
                    oreAmount += this.produce(input.Key, amountNeeded);
                }
            }

            chemical.AmountAvailable += amountOfReactions * chemical.ReactionToProduce.Output.Item2;
            chemical.AmountAvailable -= amount;

            return(oreAmount);
        }
Exemple #2
0
        public Chemical getChemical(string name)
        {
            Chemical chemical = chemicals.FirstOrDefault(x => x.Name == name);

            if (chemical == null)
            {
                chemical = new Chemical()
                {
                    Name = name
                };

                chemicals.Add(chemical);
            }

            return(chemical);
        }
Exemple #3
0
        public string ComputePartTwo(string[] input)
        {
            surplus   = new ChemicalsStore();
            reactions = input.Select(i => Reaction.Parse(i)).ToList();

            var fuel = new Chemical {
                Name = "FUEL", Quantity = 1
            };
            var  oreGoal         = 1000000000000;
            var  orePerFuel      = CalculateOreNeeded(fuel);
            var  fuelGuess       = oreGoal / orePerFuel;
            var  mostValidGuess  = fuelGuess;
            var  fuelGuessFactor = fuelGuess / 2;
            long result;

            while ((result = CalculateOreNeeded(fuel * fuelGuess)) < oreGoal)
            {
                mostValidGuess = fuelGuess;
                if (result == oreGoal)
                {
                    return($"{result}");
                }

                Console.WriteLine($"Failed with guess {fuelGuess} - {fuelGuessFactor} and result {result}/{oreGoal}");

                while (CalculateOreNeeded(fuel * (fuelGuessFactor + fuelGuess)) > oreGoal)
                {
                    fuelGuessFactor /= 2;
                }

                if (fuelGuessFactor == 0)
                {
                    fuelGuessFactor = 1;
                }

                fuelGuess += fuelGuessFactor;
            }
            return($"{mostValidGuess}");
        }
Exemple #4
0
        public long CalculateOreNeeded(Chemical product)
        {
            var reaction         = reactions.First(r => r.CanReverseReact(product));
            var availableProduct = surplus.Withdraw(product.Name, product.Quantity);
            var productNeeded    = product.Quantity - availableProduct;
            var wishFactor       = (long)Math.Ceiling((double)Math.Max(productNeeded, 0) / (double)reaction.OutputQuantity);
            var bonusProduct     = (long)(reaction.OutputQuantity * wishFactor - productNeeded);

            if (!product.IsOre())
            {
                surplus.Deposit(product.Name, bonusProduct);
            }

            var requiredOre = 0L;

            foreach (var reactant in reaction.Input)
            {
                requiredOre += reactant.IsOre() ? wishFactor * reactant.Quantity : CalculateOreNeeded(reactant * wishFactor);
            }

            return(requiredOre);
        }
Exemple #5
0
        public override async Task Run()
        {
            string[] lines = File.ReadAllLines("Data/Day14.txt");
            //lines = File.ReadAllLines("Data/Day14Part1Example1.txt");
            //lines = File.ReadAllLines("Data/Day14Part1Example2.txt");
            //lines = File.ReadAllLines("Data/Day14Part1Example3.txt");
            //lines = File.ReadAllLines("Data/Day14Part1Example4.txt");
            //lines = File.ReadAllLines("Data/Day14Part1Example5.txt");

            foreach (string line in lines)
            {
                string[] lineSplitted = line.Split("=>");

                Dictionary <Chemical, long> inputs = lineSplitted[0].Trim().Split(",").Select(x =>
                {
                    string[] inputSplitted = x.Trim().Split(" ", StringSplitOptions.RemoveEmptyEntries);

                    Chemical chemical = this.getChemical(inputSplitted[1].Trim());

                    return(new Tuple <Chemical, long>(chemical, long.Parse(inputSplitted[0])));
                }).ToDictionary(x => x.Item1, x => x.Item2);

                string[] outputSplitted = lineSplitted[1].Trim().Split(" ", StringSplitOptions.RemoveEmptyEntries);

                Tuple <Chemical, long> output = new Tuple <Chemical, long>(this.getChemical(outputSplitted[1].Trim()), long.Parse(outputSplitted[0]));

                Reaction reaction = new Reaction()
                {
                    Inputs = inputs,
                    Output = output
                };

                if (reaction.Inputs.Count == 1 && reaction.Inputs.First().Key.Name == "ORE")
                {
                    reaction.IsOre = true;
                }

                output.Item1.ReactionToProduce = reaction;

                this.reactions.Add(reaction);
            }

            //foreach (var reaction in reactions)
            //{
            //    Console.WriteLine(reaction.ToString());
            //}

            Tuple <Chemical, long> chemicalFuel = reactions.First(x => x.Output.Item1.Name == "FUEL").Output;

            long oreAmount = this.produce(chemicalFuel.Item1, chemicalFuel.Item2);

            Console.WriteLine("Part 1: " + oreAmount);

            long oreAmountTotal = 1000000000000;
            long bsMax          = 1;
            long bsMin          = 0;
            long bsMid;

            while (true)
            {
                long oreAmountCurrent = this.produce(chemicalFuel.Item1, bsMax);

                if (oreAmountCurrent < oreAmountTotal)
                {
                    bsMax *= 2;
                }
                else
                {
                    break;
                }
            }

            while (bsMin < bsMax)
            {
                bsMid = (bsMin + bsMax) / 2;

                if (this.produce(chemicalFuel.Item1, bsMid) <= oreAmountTotal)
                {
                    bsMin = bsMid + 1;
                }
                else
                {
                    bsMax = bsMid;
                }
            }

            Console.WriteLine("Part 2: " + (bsMin - 1));
        }
Exemple #6
0
        public static Reaction Parse(string data)
        {
            var membersData = data.Split("=>");

            return(new Reaction(membersData[0].Split(',').Select(m => Chemical.Parse(m)).ToArray(), Chemical.Parse(membersData[1])));
        }
Exemple #7
0
 public bool CanReverseReact(Chemical chemical)
 {
     return(output.Name.Equals(chemical.Name));
 }
Exemple #8
0
 public Reaction(Chemical[] input, Chemical output)
 {
     this.input  = input;
     this.output = output;
 }