public override BeltPlan CalculatePlan() { if (BeltIn == SubtractedAmount) { List <Input> inputs = new List <Input> { new Input(Context, BeltIn) }; BeltPlan bp = new BeltPlan(Context, inputs.ToImmutableList()); return(bp); } else { ImmutableList <decimal> rates = ImmutableList <decimal> .Empty.Add(BeltIn); int chosenDivisor = 1; List <Sum> combinationsForAmount = GetCombinationsToMatchAmount(rates, SubtractedAmount); while (combinationsForAmount.Count == 0) { chosenDivisor++; rates = NumberManipulation.DivideList(ImmutableList <decimal> .Empty.Add(BeltIn), chosenDivisor); combinationsForAmount = GetCombinationsToMatchAmount(rates, SubtractedAmount); } Sum chosenSum = null; foreach (Sum sum in combinationsForAmount) { if (chosenSum == null) { chosenSum = sum; continue; } if (sum.Variety < chosenSum.Variety) { chosenSum = sum; } else if (sum.Variety == chosenSum.Variety) { if (sum.Parts.Count < chosenSum.Parts.Count) { chosenSum = sum; } } } List <Input> inputs = new List <Input> { new Input(Context, BeltIn) }; List <decimal> remainingRates = new List <decimal>(chosenSum.Parts); List <Input> relevantInputs = new List <Input>(); foreach (Input input in inputs) { if (remainingRates.Contains(input.OutputRate / chosenDivisor)) { input.Split(chosenDivisor); for (int i = 0; i < chosenDivisor; i++) { remainingRates.Remove(input.OutputRate / chosenDivisor); } relevantInputs.Add(input); } } List <Output> relevantNodes = new List <Output>(); foreach (Input input in relevantInputs) { relevantNodes.AddRange(input.GetFinalOutputs()); } remainingRates = new List <decimal>(chosenSum.Parts); List <Output> outputsToMerge = new List <Output>(); List <Output> otherOutputsToMerge = new List <Output>(); foreach (Output node in relevantNodes.Reverse <Output>()) { decimal outRate = node.OutputRate; if (remainingRates.Contains(outRate)) { outputsToMerge.Add(node); remainingRates.Remove(outRate); } else { otherOutputsToMerge.Add(node); } } Merger merger = new Merger(Context); merger.AddInputsSafe(outputsToMerge); merger = new Merger(Context); merger.AddInputsSafe(otherOutputsToMerge); BeltPlan bp = new BeltPlan(Context, inputs.ToImmutableList()); bp.Simplify(); return(bp); } }