示例#1
0
        public string Encrypt(KMBombInfo bombInfo, ComponentInfo componentInfo, NumberInfo numberInfo)
        {
            var number = numberInfo.Number;

            _logger = numberInfo.Logger;
            var colorRule = componentInfo.SimonsStagesColor;
            var lastDigit = bombInfo.GetSerialNumberNumbers().Last();

            opposites = new[]
            {
                new List <int> {
                    lastDigit, (lastDigit + 1) % 10, (lastDigit + 2) % 10, (lastDigit + 3) % 10, (lastDigit + 4) % 10
                },
                new List <int> {
                    (lastDigit + 9) % 10, (lastDigit + 8) % 10, (lastDigit + 7) % 10, (lastDigit + 6) % 10, (lastDigit + 5) % 10
                }
            };
            _logger.LogMessage("------Start of Simon's Stages------");
            _logger.LogMessage("Opposites:");
            _logger.LogMessage(opposites[0].Join());
            _logger.LogMessage(opposites[1].Join());
            _logger.LogMessage("The {0} rule applies.", colorRule.ToString());
            switch (colorRule)
            {
            case SimonsStagesColor.Red:
                return(number);

            case SimonsStagesColor.Blue:
                _logger.LogMessage("Reversing the string.");
                return(number.Reverse().Join(""));

            case SimonsStagesColor.Pink:
                _logger.LogMessage("Taking the opposites of the string.");
                return(number.Select(x => Opposite(int.Parse(x.ToString()))).Join(""));

            case SimonsStagesColor.Lime:
                _logger.LogMessage("Reversing the string and taking the opposites.");
                return(number.Select(x => Opposite(int.Parse(x.ToString()))).Reverse().Join(""));

            case SimonsStagesColor.Cyan:
                _logger.LogMessage("Taking the opposites of the first and last.");
                var cyanAnswer = number.ToArray().Select(x => x.ToString()).ToArray();
                cyanAnswer[0]  = Opposite(int.Parse(cyanAnswer[0])).ToString();
                cyanAnswer[11] = Opposite(int.Parse(cyanAnswer[11])).ToString();
                return(cyanAnswer.Join(""));

            case SimonsStagesColor.White:
                _logger.LogMessage("Taking the opposites of the third and second.");
                var whiteAnswer = number.ToArray().Select(x => x.ToString()).ToArray();
                whiteAnswer[1] = Opposite(int.Parse(whiteAnswer[1])).ToString();
                whiteAnswer[2] = Opposite(int.Parse(whiteAnswer[2])).ToString();
                return(whiteAnswer.Join(""));

            default:
                throw new InvalidOperationException(string.Format("invalid color rule SS {0}", colorRule));
            }
        }
示例#2
0
        public string Encrypt(KMBombInfo bombInfo, ComponentInfo componentInfo, NumberInfo numberInfo)
        {
            var answer     = new List <int>();
            var number     = numberInfo.Number;
            var firstDigit = bombInfo.GetSerialNumberNumbers().First();
            var lastDigit  = bombInfo.GetSerialNumberNumbers().Last();

            _logger = numberInfo.Logger;
            _logger.LogMessage("------Start of Forget Me Now------");

            for (int i = 0; i < 12; i++)
            {
                var digit      = 0;
                var prevDigit1 = 0;
                var prevDigit2 = 0;

                if (i == 0)
                {
                    prevDigit1 = componentInfo.StartingNumber;
                    prevDigit2 = lastDigit;
                }
                else if (i == 1)
                {
                    prevDigit1 = answer[i - 1];
                    prevDigit2 = componentInfo.StartingNumber;
                }
                else
                {
                    prevDigit1 = answer[i - 2];
                    prevDigit2 = answer[i - 1];
                }

                if (prevDigit1 == 0 || prevDigit2 == 0)
                {
                    _logger.LogMessage("One of the previous 2 calculated numbers were 0:");
                    digit = (int)Math.Ceiling((double)hOfX[i] * firstDigit / 5.0);
                }
                else if (prevDigit1 % 2 == 0 && prevDigit2 % 2 == 0)
                {
                    _logger.LogMessage("Both of the previous 2 calculated numbers were even:");
                    digit = Math.Abs(gOfX[i] * 4 - 12);
                }
                else
                {
                    _logger.LogMessage("Otherwise rule:");
                    digit = prevDigit1 + prevDigit2 + fOfX[i];
                }

                var digitToAdd = (int.Parse(number[i].ToString()) + digit) % 10;
                _logger.LogMessage("Number {0}: The final number is: {1}", i + 1, digitToAdd);
                answer.Add(digitToAdd);
            }

            return(answer.Join(""));
        }
        public string Encrypt(KMBombInfo bombInfo, ComponentInfo componentInfo, NumberInfo numberInfo)
        {
            _logger = numberInfo.Logger;
            var order         = componentInfo.Positions;
            var initialNumber = numberInfo.Number;
            var numbers       = new List <string>();
            var finalnumbers  = new int[12];

            _logger.LogMessage("------Start of Forget Us Not------");
            for (var i = 0; i < 12; ++i)
            {
                numbers.Add(initialNumber.Take(3).Join(""));
                initialNumber = Shift(initialNumber);
            }

            _logger.LogMessage("The 3 digit groups are: {0}.", numbers.Join(", "));

            switch (bombInfo.GetSerialNumberLetters().Count() - bombInfo.GetSerialNumberNumbers().Count())
            {
            case 0:
                function = (s) =>
                {
                    var digits = s.Select(x => int.Parse(x.ToString())).ToList();
                    return((Math.Abs(digits[1] - bombInfo.GetBatteryCount()) + Math.Abs(digits[0] - digits[2])) % 10);
                };
                break;

            case -2:
                function = (s) =>
                {
                    var digits = s.Select(x => int.Parse(x.ToString())).ToList();
                    return((Math.Abs(digits[2] - bombInfo.GetBatteryCount()) + Math.Abs(digits[0] - digits[1])) % 10);
                };
                break;

            default:
                function = (s) =>
                {
                    var digits = s.Select(x => int.Parse(x.ToString())).ToList();
                    return((Math.Abs(digits[0] - bombInfo.GetBatteryCount()) + Math.Abs(digits[1] - digits[2])) % 10);
                };
                break;
            }

            for (var i = 0; i < numbers.Count; ++i)
            {
                var str    = numbers[i];
                var answer = function(str);
                _logger.LogMessage("The final answer for string {0}({1}), which will be placed in position {2} is {3}.", i + 1, str, order[i], answer);
                finalnumbers[order[i] - 1] = answer;
            }

            return(finalnumbers.Join(""));
        }
        public string Encrypt(KMBombInfo bombInfo, ComponentInfo componentInfo, NumberInfo numberInfo)
        {
            var answer       = new List <int>();
            var number       = numberInfo.Number.Select(x => int.Parse(x.ToString())).ToList();
            var bottomNumber = numberInfo.BottomNumber.Select(x => int.Parse(x.ToString())).ToList();

            _logger = numberInfo.Logger;

            _logger.LogMessage("------Start of Forget Everything------");

            ForgetEverythingColor primaryCol;

            if (componentInfo.FEColors[0] == componentInfo.FEColors[1] ||
                componentInfo.FEColors[0] == componentInfo.FEColors[2])
            {
                primaryCol = componentInfo.FEColors[0];
            }
            else if (componentInfo.FEColors[1] == componentInfo.FEColors[2])
            {
                primaryCol = componentInfo.FEColors[1];
            }
            else
            {
                if (componentInfo.FEColors[0] != 0 && componentInfo.FEColors[1] != 0 && componentInfo.FEColors[2] != 0)
                {
                    primaryCol = 0;
                }
                else if (componentInfo.FEColors[0] != (ForgetEverythingColor)1 &&
                         componentInfo.FEColors[1] != (ForgetEverythingColor)1 &&
                         componentInfo.FEColors[2] != (ForgetEverythingColor)1)
                {
                    primaryCol = (ForgetEverythingColor)1;
                }
                else if (componentInfo.FEColors[0] != (ForgetEverythingColor)2 &&
                         componentInfo.FEColors[1] != (ForgetEverythingColor)2 &&
                         componentInfo.FEColors[2] != (ForgetEverythingColor)2)
                {
                    primaryCol = (ForgetEverythingColor)2;
                }
                else
                {
                    primaryCol = (ForgetEverythingColor)3;
                }
            }
            _logger.LogMessage("The rule used is {0}", primaryCol.ToString());

            switch (primaryCol)
            {
            case ForgetEverythingColor.Red:
                ApplyRule(answer, (i) => (bottomNumber[i] + number[i]) % 10);
                break;

            case ForgetEverythingColor.Yellow:
                ApplyRule(answer, (i) => (bottomNumber[i] - number[i] + 10) % 10);
                break;

            case ForgetEverythingColor.Green:
                ApplyRule(answer, (i) => (bottomNumber[i] + number[i] + 5) % 10);
                break;

            case ForgetEverythingColor.Blue:
                ApplyRule(answer, (i) => (number[i] - bottomNumber[i] + 10) % 10);
                break;

            default:
                throw new InvalidOperationException(string.Format("invalid color rule {0}", primaryCol));
            }

            return(answer.Join(""));
        }
示例#5
0
        public string Encrypt(KMBombInfo bombInfo, ComponentInfo componentInfo, NumberInfo numberInfo)
        {
            var number = numberInfo.Number;

            var firstItemRemove   = Math.Max(componentInfo.IgnoredNumbers.Item1, componentInfo.IgnoredNumbers.Item2) - 1;
            var secondItemRemove  = Math.Min(componentInfo.IgnoredNumbers.Item1, componentInfo.IgnoredNumbers.Item2) - 1;
            var removedFirstItem  = number[firstItemRemove];
            var removedSecondItem = number[secondItemRemove];

            _logger = numberInfo.Logger;
            _logger.LogMessage("------Start of Forget Infinity------");

            var allModNames = bombInfo.GetModuleNames().ToList();

            var numberList = number.ToList();

            numberList.RemoveAt(firstItemRemove);
            numberList.RemoveAt(secondItemRemove);
            number = numberList.Join("");
            _logger.LogMessage("After removing the items at: {0}, the new number is: {1}", new[] { firstItemRemove + 1, secondItemRemove + 1 }.Join(" and "), number);


            var solution = new[] { new int[5], new int[5] };

            if (number.Length != 10)
            {
                throw new InvalidOperationException(string.Format("Invalid length of number, length is {0}, expected 10", number.Length));
            }

            var calculationNumber = new[] { number.Take(5).Select(x => int.Parse(x.ToString())).ToArray(), number.TakeLast(5).Select(x => int.Parse(x.ToString())).ToArray() };

            _logger.LogMessage("The two numbers are: {0}", new[] { calculationNumber[0].Join(""), calculationNumber[1].Join("") }.Join(" and "));

            for (var x = 0; x < calculationNumber.Length; x++)
            {
                var hasSwapped        = false;
                var finalStageNumbers = new int[5];
                calculationNumber[x].CopyTo(finalStageNumbers, 0);

                var lastDigitInSerial  = bombInfo.GetSerialNumberNumbers().Any() ? bombInfo.GetSerialNumberNumbers().Last() : 0;
                var firstDigitInSerial =
                    bombInfo.GetSerialNumberNumbers().Any() ? bombInfo.GetSerialNumberNumbers().First() : 0;
                var smallestDigitInSerial =
                    bombInfo.GetSerialNumberNumbers().Any() ? bombInfo.GetSerialNumberNumbers().Min() : 0;
                var largestDigitInSerial =
                    bombInfo.GetSerialNumberNumbers().Any() ? bombInfo.GetSerialNumberNumbers().Max() : 0;
                // Begin Solution Calculations
                // Culumulative Slot Calculations
                if (bombInfo.IsPortPresent(Port.StereoRCA))
                {
                    finalStageNumbers = finalStageNumbers.Reverse().ToArray();
                    hasSwapped        = true;
                }

                var batterycount = bombInfo.GetBatteryCount();
                for (var idx = 0; idx < finalStageNumbers.Length; idx++)
                {
                    finalStageNumbers[idx] += batterycount;
                }

                var LettersInSerial = bombInfo.GetSerialNumberLetters().ToList();
                if (LettersInSerial.Contains('F') || LettersInSerial.Contains('I'))
                {
                    for (var idx = 0; idx < finalStageNumbers.Length; idx++)
                    {
                        finalStageNumbers[idx] -= LettersInSerial.Count;
                    }
                }
                // Individual Slots
                // Slot 1
                if (allModNames.Contains("Tetris"))
                {
                    finalStageNumbers[0] = calculationNumber[x][0] + 7;
                }
                else if (finalStageNumbers[0] >= 10 && finalStageNumbers[0] % 2 == 0)
                {
                    finalStageNumbers[0] /= 2;
                }
                else if (finalStageNumbers[0] < 5)
                {
                    finalStageNumbers[0] += lastDigitInSerial;
                }
                else
                {
                    finalStageNumbers[0] += 1;
                }
                // Slot 2
                if (bombInfo.CountDuplicatePorts() > 0)
                {
                    finalStageNumbers[1] += bombInfo.CountDuplicatePorts();
                }
                else if (bombInfo.GetPortCount() == 0)
                {
                    finalStageNumbers[1] += calculationNumber[x].ToArray()[0] + calculationNumber[x].ToArray()[2];
                }
                else
                {
                    finalStageNumbers[1] += bombInfo.GetPortCount();
                }
                // Slot 3
                if (!hasSwapped)
                {
                    if (finalStageNumbers[2] >= 7)
                    {
                        var currentValue    = calculationNumber[x][2];
                        var finalValueSlot3 = 0;
                        while (currentValue > 0)
                        {
                            finalValueSlot3 += currentValue % 2;
                            currentValue    /= 2;
                        }

                        finalStageNumbers[2] = finalValueSlot3;
                    }
                    else if (finalStageNumbers[2] < 3)
                    {
                        finalStageNumbers[2] = Math.Abs(finalStageNumbers[2]);
                    }
                    else
                    {
                        finalStageNumbers[2] = calculationNumber[x][2] + smallestDigitInSerial;
                    }
                }

                // Slot 4
                if (finalStageNumbers[3] < 0)
                {
                    finalStageNumbers[3] += largestDigitInSerial;
                }
                // Slot 5
                var slotTable5th = new [, ]
                {
                    { 0, 1, 2, 3, 4 },
                    { 5, 6, 7, 8, 9 },
                    { calculationNumber[x][4], 1 + calculationNumber[x][4], 9 - calculationNumber[x][4], calculationNumber[x][4] - 1, calculationNumber[x][4] + 5 },
                    { 9, 8, 5, 6, 7 },
                    { 4, 3, 0, 1, 2 }
                };
                var rowCellToGrab = finalStageNumbers[4] - (Mathf.FloorToInt(finalStageNumbers[4] / 5.0f) * 5);
                finalStageNumbers[4] = slotTable5th[rowCellToGrab, firstDigitInSerial / 2];
                // Within 0-9
                while (!finalStageNumbers.ToList().TrueForAll(a => a >= 0 && a <= 9))
                {
                    for (var idx = 0; idx < finalStageNumbers.Length; idx++)
                    {
                        if (finalStageNumbers[idx] < 0)
                        {
                            finalStageNumbers[idx] += 10;
                        }
                        else if (finalStageNumbers[idx] > 9)
                        {
                            finalStageNumbers[idx] -= 10;
                        }
                    }
                }

                solution[x] = finalStageNumbers;
                _logger.LogMessage("The final answer for the {0} string is: {1}", x == 0 ? "first" : "second", solution[x].Join(""));
            }

            var finalString = solution[0].Concat(solution[1]).Join("");

            finalString = finalString.Insert(secondItemRemove, removedSecondItem.ToString());
            finalString = finalString.Insert(firstItemRemove, removedFirstItem.ToString());
            _logger.LogMessage("After concatinating and inserting the removed numbers, the answer is: {0}", finalString);

            return(finalString);
        }
        public string Encrypt(KMBombInfo bombInfo, ComponentInfo componentInfo, NumberInfo numberInfo)
        {
            var answer = new List <int>();
            var number = numberInfo.Number;

            _logger = numberInfo.Logger;
            _logger.LogMessage("------Start of Forget Me Not------");
            for (var i = 0; i < number.Length; i++)
            {
                var nr = int.Parse(number[i].ToString());
                switch (i)
                {
                case 0:
                    if (bombInfo.IsIndicatorOff(Indicator.CAR))
                    {
                        _logger.LogMessage("Number {0}, rule 1 applies.", i + 1);
                        answer.Add(Sum(nr, 2));
                    }
                    else if (bombInfo.GetOffIndicators().Count() > bombInfo.GetOnIndicators().Count())
                    {
                        _logger.LogMessage("Number {0}, rule 2 applies.", i + 1);
                        answer.Add(Sum(nr, 7));
                    }
                    else if (!bombInfo.GetOffIndicators().Any())
                    {
                        _logger.LogMessage("Number {0}, rule 3 applies.", i + 1);
                        answer.Add(Sum(nr, bombInfo.GetOnIndicators().Count()));
                    }
                    else
                    {
                        _logger.LogMessage("Number {0}, the otherwise rule applies.", i + 1);
                        answer.Add(Sum(nr, bombInfo.GetSerialNumberNumbers().Last()));
                    }
                    break;

                case 1:
                    if (bombInfo.IsPortPresent(Port.Serial) && bombInfo.GetSerialNumberNumbers().Count() >= 3)
                    {
                        _logger.LogMessage("Number {0}, rule 1 applies.", i + 1);
                        answer.Add(Sum(nr, 3));
                    }
                    else if (int.Parse(answer[0].ToString()) % 2 == 0)
                    {
                        _logger.LogMessage("Number {0}, rule 2 applies.", i + 1);
                        answer.Add(Sum(nr, (int.Parse(answer[0].ToString()) + 1)));
                    }
                    else
                    {
                        _logger.LogMessage("Number {0}, the otherwise rule applies.", i + 1);
                        answer.Add(Sum(nr, (int.Parse(answer[0].ToString()) - 1)));
                    }
                    break;

                default:
                    var prevNr = new Pair <int, int>(int.Parse(answer[i - 1].ToString()), int.Parse(answer[i - 2].ToString()));
                    if (new[] { prevNr.Item1, prevNr.Item2 }.Contains(0))
                    {
                        _logger.LogMessage("Number {0}, rule 1 applies.", i + 1);
                        answer.Add(Sum(nr, bombInfo.GetSerialNumberNumbers().Max()));
                    }
                    else if ((prevNr.Item1 % 2 == 0) && (prevNr.Item2 % 2 == 0))
                    {
                        _logger.LogMessage("Number {0}, rule 2 applies.", i + 1);
                        answer.Add(Sum(nr, bombInfo.GetSerialNumberNumbers().Any(x => x % 2 != 0)
                                                                ? bombInfo.GetSerialNumberNumbers().Where(x => x % 2 != 0).Min()
                                                                : 9));
                    }
                    else
                    {
                        _logger.LogMessage("Number {0}, the otherwise rule applies.", i + 1);
                        answer.Add(Sum(nr, (prevNr.Item1 + prevNr.Item2) > 9 ? (prevNr.Item1 + prevNr.Item2) / 10: prevNr.Item1 + prevNr.Item2));
                    }
                    break;
                }
            }

            var answerToReturn = answer.Join("");

            _logger.LogMessage("The answer for Forget Me Not is: {0}", answerToReturn);
            return(answerToReturn);
        }
示例#7
0
        public string Encrypt(KMBombInfo bombInfo, ComponentInfo componentInfo, NumberInfo numberInfo)
        {
            var answer       = new List <int>();
            var rules        = componentInfo.Rules;
            var number       = numberInfo.Number.Select(x => int.Parse(x.ToString())).ToList();
            var bottomNumber = numberInfo.BottomNumber.Select(x => int.Parse(x.ToString())).ToList();

            _logger = numberInfo.Logger;
            _logger.LogMessage("------Start of Forget Me Later------");

            for (int j = 0; j < 12; j++)
            {
                switch (rules[j])
                {
                case 0:
                    AddFunction((i) => Sum(number[i], bottomNumber[i]));
                    break;

                case 1:
                    AddFunction((i) => Sum(number[i], bottomNumber[i] + 1));
                    break;

                case 2:
                    AddFunction((i) => Sum(number[i], bottomNumber[i] * 2));
                    break;

                case 3:
                    AddFunction((i) => Sum(number[i], bottomNumber[i] + (i == 0 ? number[i] : answer[i - 1])));
                    break;

                case 4:
                    AddFunction((i) => Sum(number[i], (i == 0 ? number[i] :answer[i - 1]) - bottomNumber[i]));
                    break;

                case 5:
                    AddFunction(
                        (i) => Sum(number[i],
                                   Math.Abs((i == 0 ? number[i] : answer[i - 1]) - (i == 0 || i == 1 ? number[i] : answer[i - 2]))));
                    break;

                case 6:
                    AddFunction(
                        (i) => Sum(number[i], (i == 0 || i == 1 ? number[i] : answer[i - 2]) - bottomNumber[i]));
                    break;

                case 7:
                    AddFunction((i) => Sum(number[i], bottomNumber[i] + (i == 0 ? number[i] : answer[i - 1]) + 1));
                    break;

                case 8:
                    AddFunction(
                        (i) => Sum(number[i], bottomNumber[i] + (i == 0 || i == 1 ? number[i] : answer[i - 2]) + 1));
                    break;

                case 9:
                    AddFunction(
                        (i) => Sum(number[i], (i == 0 ? number[i] : answer[i - 1]) + (i == 0 || i == 1 ? number[i] : answer[i - 2]) + 1));
                    break;

                case 10:
                    AddFunction((i) => Sum(number[i], (i == 0 ? number[i] : answer[i - 1])));
                    break;

                case 11:
                    AddFunction((i) => Sum(number[i], (i == 0 ? number[i] : answer[i - 1]) + 1));
                    break;

                case 12:
                    AddFunction((i) => Sum(number[i], (i == 0 ? number[i] : answer[i - 1]) * 2));
                    break;

                case 13:
                    AddFunction(
                        (i) => Sum(number[i], (i == 0 ? number[i] : answer[i - 1]) + (i == 0 || i == 1 ? number[i] : answer[i - 2])));
                    break;

                case 14:
                    AddFunction((i) => Sum(number[i], bottomNumber[i] - 1));
                    break;

                case 15:
                    AddFunction((i) => Sum(number[i], (i == 0 ? number[i] : answer[i - 1]) - 1));
                    break;

                case 16:
                    AddFunction((i) => Sum(number[i], (i == 0 || i == 1 ? number[i] : answer[i - 2]) - 1));
                    break;

                case 17:
                    AddFunction((i) => Sum(number[i], (i == 0 ? number[i] : answer[i - 1]) + bottomNumber[i] - 1));
                    break;

                case 18:
                    AddFunction(
                        (i) => Sum(number[i], (i == 0 || i == 1 ? number[i] : answer[i - 2]) + bottomNumber[i] - 1));
                    break;

                case 19:
                    AddFunction(
                        (i) => Sum(number[i], (i == 0 ? number[i] : answer[i - 1]) + (i == 0 || i == 1 ? number[i] : answer[i - 2]) - 1));
                    break;

                case 20:
                    AddFunction((i) => Sum(number[i], (i == 0 || i == 1 ? number[i] : answer[i - 2])));
                    break;

                case 21:
                    AddFunction((i) => Sum(number[i], (i == 0 || i == 1 ? number[i] : answer[i - 2]) + 1));
                    break;

                case 22:
                    AddFunction((i) => Sum(number[i], (i == 0 || i == 1 ? number[i] : answer[i - 2]) * 2));
                    break;

                case 23:
                    AddFunction(
                        (i) => Sum(number[i], (i == 0 || i == 1 ? number[i] : answer[i - 2]) + bottomNumber[i]));
                    break;

                case 24:
                    AddFunction(
                        (i) => Sum(number[i], ((i == 0 ? number[i] : answer[i - 1]) + (i == 0 || i == 1 ? number[i] : answer[i - 2])) * 2));
                    break;

                case 25:
                    AddFunction((i) => Sum(number[i], ((i == 0 ? number[i] : answer[i - 1]) + bottomNumber[i]) * 2));
                    break;

                case 26:
                    AddFunction(
                        (i) => Sum(number[i], ((i == 0 || i == 1 ? number[i] : answer[i - 2]) + bottomNumber[i]) * 2));
                    break;

                case 27:
                    AddFunction(
                        (i) => Sum(number[i],
                                   Math.Abs((i == 0 || i == 1 ? number[i] : answer[i - 2]) - (i == 0 ? number[i] : answer[i - 1])) * 2));
                    break;

                case 28:
                    AddFunction(
                        (i) => Sum(number[i], Math.Abs(bottomNumber[i] - (i == 0 ? number[i] : answer[i - 1])) * 2));
                    break;

                case 29:
                    AddFunction(
                        (i) => Sum(number[i], Math.Abs((i == 0 || i == 1 ? number[i] : answer[i - 2]) - bottomNumber[i]) * 2));
                    break;

                case 30:
                    AddFunction((i) => Sum(number[i], bottomNumber[i] * 3));
                    break;

                case 31:
                    AddFunction((i) => Sum(number[i], (i == 0 ? number[i] : answer[i - 1]) * 3));
                    break;

                case 32:
                    AddFunction((i) => Sum(number[i], (i == 0 || i == 1 ? number[i] : answer[i - 2]) * 3));
                    break;

                case 33:
                    AddFunction(
                        (i) => Sum(number[i], ((i == 0 || i == 1 ? number[i] : answer[i - 2]) + (i == 0 ? number[i] : answer[i - 1])) * 3));
                    break;

                case 34:
                    AddFunction(
                        (i) => Sum(number[i], (i == 0 || i == 1 ? number[i] : answer[i - 2]) + ((i == 0 ? number[i] : answer[i - 1]) * 3)));
                    break;

                case 35:
                    AddFunction((i) => Sum(number[i], (i == 0 ? number[i] : answer[i - 1]) + (bottomNumber[i] * 3)));
                    break;

                case 36:
                    AddFunction(
                        (i) => Sum(number[i], (i == 0 || i == 1 ? number[i] : answer[i - 2]) + (bottomNumber[i] * 3)));
                    break;

                case 37:
                    AddFunction((i) => Sum(number[i], bottomNumber[i] + ((i == 0 ? number[i] : answer[i - 1]) * 3)));
                    break;

                case 38:
                    AddFunction(
                        (i) => Sum(number[i], bottomNumber[i] + ((i == 0 || i == 1 ? number[i] : answer[i - 2]) * 3)));
                    break;

                case 39:
                    AddFunction(
                        (i) => Sum(number[i], (i == 0 ? number[i] : answer[i - 1]) + ((i == 0 || i == 1 ? number[i] : answer[i - 2]) * 3)));
                    break;

                case 40:
                    AddFunction((i) => Sum(number[i], bottomNumber[i] + 5));
                    break;

                case 41:
                    AddFunction((i) => Sum(number[i], (i == 0 ? number[i] : answer[i - 1]) + 5));
                    break;

                case 42:
                    AddFunction((i) => Sum(number[i], (i == 0 || i == 1 ? number[i] : answer[i - 2]) + 5));
                    break;

                case 43:
                    AddFunction((i) => Sum(number[i], bottomNumber[i] + (2 * (i == 0 ? number[i] : answer[i - 1]))));
                    break;

                case 44:
                    AddFunction(
                        (i) => Sum(number[i], bottomNumber[i] + (2 * (i == 0 || i == 1 ? number[i] : answer[i - 2]))));
                    break;

                case 45:
                    AddFunction((i) => Sum(number[i], (i == 0 ? number[i] : answer[i - 1]) + (2 * bottomNumber[i])));
                    break;

                case 46:
                    AddFunction(
                        (i) => Sum(number[i], (i == 0 || i == 1 ? number[i] : answer[i - 2]) + (2 * bottomNumber[i])));
                    break;

                case 47:
                    AddFunction(
                        (i) => Sum(number[i],
                                   Math.Abs((i == 0 || i == 1 ? number[i] : answer[i - 2]) - (2 * (i == 0 ? number[i] : answer[i - 1])))));
                    break;

                case 48:
                    AddFunction(
                        (i) => Sum(number[i], Math.Abs(bottomNumber[i] - (2 * (i == 0 ? number[i] : answer[i - 1])))));
                    break;

                case 49:
                    AddFunction(
                        (i) => Sum(number[i],
                                   Math.Abs((i == 0 ? number[i] : answer[i - 1]) - (2 * (i == 0 || i == 1 ? number[i] : answer[i - 2])))));
                    break;

                case 50:
                    AddFunction((i) => Sum(number[i], 9 - bottomNumber[i]));
                    break;

                case 51:
                    AddFunction((i) => Sum(number[i], 9 - (i == 0 ? number[i] : answer[i - 1])));
                    break;

                case 52:
                    AddFunction((i) => Sum(number[i], 9 - (i == 0 || i == 1 ? number[i] : answer[i - 2])));
                    break;

                case 53:
                    AddFunction((i) => Sum(number[i], 18 - (bottomNumber[i] + (i == 0 ? number[i] : answer[i - 1]))));
                    break;

                case 54:
                    AddFunction(
                        (i) => Sum(number[i], 18 - (bottomNumber[i] + (i == 0 || i == 1 ? number[i] : answer[i - 2]))));
                    break;

                case 55:
                    AddFunction(
                        (i) => Sum(number[i],
                                   18 - ((i == 0 ? number[i] : answer[i - 1]) + (i == 0 || i == 1 ? number[i] : answer[i - 2]))));
                    break;

                case 56:
                    AddFunction((i) => Sum(number[i], 18 - (2 * bottomNumber[i])));
                    break;

                case 57:
                    AddFunction(
                        (i) => Sum(number[i], 9 - Math.Abs((i == 0 ? number[i] : answer[i - 1]) - bottomNumber[i])));
                    break;

                case 58:
                    AddFunction(
                        (i) => Sum(number[i], 9 - Math.Abs((i == 0 || i == 1 ? number[i] : answer[i - 2]) - bottomNumber[i])));
                    break;

                case 59:
                    AddFunction(
                        (i) => Sum(number[i],
                                   9 - Math.Abs((i == 0 || i == 1 ? number[i] : answer[i - 2]) - (i == 0 ? number[i] : answer[i - 1]))));
                    break;

                default:
                    throw new InvalidOperationException(string.Format("Invalid rule #{0}", rules[j]));
                }
            }
            CalculateAnswer(answer);
            return(answer.Join(""));
        }
        public string Encrypt(KMBombInfo bombInfo, ComponentInfo componentInfo, NumberInfo numberInfo)
        {
            var answer = new List <int>();

            _logger = numberInfo.Logger;
            var number       = numberInfo.Number;
            var bottomNumber = numberInfo.BottomNumber;
            var logicGates   = componentInfo.LogicGates;

            _logger.LogMessage("------Start of A>N<D------");

            for (int i = 0; i < 12; i++)
            {
                _logger.LogMessage("Digit {0}:", i + 1);
                var bits1 = Convert.ToString(number[i], 2).TakeLast(4).Select(x => x == '1').ToArray();
                var bits2 = Convert.ToString(bottomNumber[i], 2).TakeLast(4).Select(x => x == '1').ToArray();
                _logger.LogMessage("The first digit is: {0}, and that in binary is: {1}", number[i],
                                   bits1.Select(x => x ? "1" : "0").Join(""));
                _logger.LogMessage("The second digit is: {0}, and that in binary is: {1}", bottomNumber[i],
                                   bits2.Select(x => x ? "1" : "0").Join(""));
                var finalBinary = new[] { false, false, false, false };
                if (logicGates[i] == ANDLogicGate.Not)
                {
                    _logger.LogMessage("The gate is NOT, so only the first bits are required.");
                    finalBinary = bits1.Select(x => !x).ToArray();
                    var finalNotNumber = Convert.ToInt32(finalBinary.Select(x => x ? 1 : 0).Join(""), 2);
                    _logger.LogMessage("Final binary: {0}", finalBinary.Select(x => x ? 1 : 0).Join(""));
                    _logger.LogMessage("The number obtained is: {0}", finalNotNumber);
                    if (finalNotNumber > 9)
                    {
                        if (i % 2 == 0)
                        {
                            finalNotNumber = (finalNotNumber / 10) + (finalNotNumber % 10);
                            _logger.LogMessage("Applying the digital root: {0}", finalNotNumber);
                        }
                        else
                        {
                            finalNotNumber %= 10;
                            _logger.LogMessage("Taking the last digit: {0}", finalNotNumber);
                        }
                    }

                    answer.Add(finalNotNumber);
                    continue;
                }

                switch (logicGates[i])
                {
                case ANDLogicGate.AND:
                    _logger.LogMessage("The gate is AND");
                    break;

                case ANDLogicGate.OR:
                    _logger.LogMessage("The gate is OR");
                    break;

                case ANDLogicGate.XOR:
                    _logger.LogMessage("The gate is XOR");
                    break;

                case ANDLogicGate.NAND:
                    _logger.LogMessage("The gate is NAND");
                    break;

                case ANDLogicGate.NOR:
                    _logger.LogMessage("The gate is NOR");
                    break;

                case ANDLogicGate.XNOR:
                    _logger.LogMessage("The gate is XNOR");
                    break;

                case ANDLogicGate.ImpLeft:
                    _logger.LogMessage("The gate is ImpLeft");
                    break;

                case ANDLogicGate.ImpRight:
                    _logger.LogMessage("The gate is ImpRight");
                    break;

                default:
                    throw new InvalidOperationException(string.Format("invalid operator {0}", logicGates[i]));
                }

                for (int k = 0; k < 4; k++)
                {
                    switch (logicGates[i])
                    {
                    case ANDLogicGate.AND:
                        finalBinary[3 - k] = bits1[3 - k] && bits2[3 - k];
                        break;

                    case ANDLogicGate.OR:
                        finalBinary[3 - k] = bits1[3 - k] || bits2[3 - k];
                        break;

                    case ANDLogicGate.XOR:
                        finalBinary[3 - k] = bits1[3 - k] ^ bits2[3 - k];
                        break;

                    case ANDLogicGate.NAND:
                        finalBinary[3 - k] = !(bits1[3 - k] && bits2[3 - k]);
                        break;

                    case ANDLogicGate.NOR:
                        finalBinary[3 - k] = !(bits1[3 - k] || bits2[3 - k]);
                        break;

                    case ANDLogicGate.XNOR:
                        finalBinary[3 - k] = !(bits1[3 - k] ^ bits2[3 - k]);
                        break;

                    case ANDLogicGate.ImpLeft:
                        finalBinary[3 - k] = !(bits1[3 - k] && !bits2[3 - k]);
                        break;

                    case ANDLogicGate.ImpRight:
                        finalBinary[3 - k] = !(!bits1[3 - k] && bits2[3 - k]);
                        break;

                    default:
                        throw new InvalidOperationException(string.Format("invalid operator {0}", logicGates[i]));
                    }
                }
                _logger.LogMessage("Final binary: {0}", finalBinary.Select(x => x ? 1 : 0).Join(""));
                var finalNumber = Convert.ToInt32(finalBinary.Select(x => x ? 1 : 0).Join(""), 2);
                _logger.LogMessage("The number obtained is: {0}", finalNumber);
                if (finalNumber > 9)
                {
                    if (i % 2 == 0)
                    {
                        finalNumber = (finalNumber / 10) + (finalNumber % 10);
                        _logger.LogMessage("Applying the digital root: {0}", finalNumber);
                    }
                    else
                    {
                        finalNumber %= 10;
                        _logger.LogMessage("Taking the last digit: {0}", finalNumber);
                    }
                }

                answer.Add(finalNumber);
            }

            return(answer.Join(""));
        }