예제 #1
0
        /// <summary>
        /// https://projecteuler.net/problem=51  --skip=12,15,20,26,60
        /// </summary>
        /// <param name="arguments"></param>
        /// <returns></returns>
        public static Result PrimeDigitReplacements(Problem arguments)
        {
            /// <summary>
            /// Return true if all digits in a numbers are the same, except those that repeat the
            /// same digit and it just increases/decreases from one to the other. For example
            /// CompareNumbers(124353,124757)=true, CompareNumbers(124353,124151)=true,
            /// CompareNumbers(121313,121757)=false. Also if numbers are the same return false.
            /// </summary>
            /// <param name="left"></param>
            /// <param name="right"></param>
            /// <returns></returns>
            bool NumbersBelongToSameDigitFamily(int left, int right, int repeating_sequences = 1)
            {
                var repeating = new Dictionary <char, List <int> >();
                var sleft     = left.ToString();
                var sright    = right.ToString();

                if (left == right)
                {
                    return(false);
                }
                if (sleft.Length != sright.Length)
                {
                    return(false);
                }

                for (var i = 0; i < sleft.Length; i++)
                {
                    var rdigit = sright[i];
                    var ldigit = sleft[i];

                    if ((repeating.Count < repeating_sequences) && !repeating.ContainsKey(ldigit) && (sleft.Count(c => c == ldigit) >= 2))
                    {
                        if (repeating.ContainsKey(ldigit) && repeating[ldigit].Contains(i))
                        {
                            continue;
                        }
                        else
                        {
                            repeating.Add(ldigit, new List <int>());

                            foreach (var(digit, j) in sleft.Enumerate())
                            {
                                if (digit == ldigit)
                                {
                                    repeating[ldigit].Add(j);
                                }
                            }
                            bool match = true;
                            foreach (var k in repeating[ldigit])
                            {
                                match = match && sright[k] == rdigit;

                                if (!match)
                                {
                                    break;
                                }
                            }
                            if (!match)
                            {
                                return(false);
                            }
                        }
                    }
                    else if (repeating.ContainsKey(ldigit) && repeating[ldigit].Contains(i))
                    {
                        continue;
                    }
                    else if (rdigit == ldigit)
                    {
                        continue;
                    }
                    else if (ldigit != rdigit)
                    {
                        return(false);
                    }
                }

                return(true);
            }

            // get all six digit primes
            var primes  = UtilityMath.GeneratePrimes(100000, 1000000).ToArray();
            var repeats = new List <int>();

            // get primes with repeated digits (not necessarily adjacent digits)
            for (int i = 0; i < primes.Length; i++)
            {
                var counts = UtilityMath.GetRepeatedDigitCounts(primes[i]);
                if (counts.Count(c => c > 1) >= 1) // choose only primes with at least one repeatig digit
                {
                    repeats.Add(primes[i]);
                }
            }

            // get first eight number prime-family
            HashSet <int> family = null;

            foreach (var prime in repeats)
            {
                family = new HashSet <int>
                {
                    prime
                };

                foreach (var n in repeats)
                {
                    if (NumbersBelongToSameDigitFamily(prime, n))
                    {
                        family.Add(n);
                    }

                    if (family.Count == 8)
                    {
                        break;
                    }
                }
                if (family.Count == 8)
                {
                    break;
                }
            }
            primes  = null;
            repeats = null;

            var answer  = family?.First().ToString();
            var message = string.Format("The smallest prime which, by replacing part of the number (not necessarily adjacent digits) with the same digit, is part of an eight prime value family is {0}.", answer);

            if (Answers[arguments.Id] != answer)
            {
                message += string.Format(" => INCORRECT ({0})", Answers[arguments.Id]);
            }
            var r = new Result(arguments.Id, message)
            {
                Answer = answer
            };

            return(r);
        }