General backtracking for a numbers' arrangement problem
Saw this problem on a Facebook post today:
To write a code for it, we can use DFS + backtracking. We can actually make it general enough so that we can solve it for:
1/ Any set of digits
2/ Broken into any group of numbers
3/ Looking for any target
The result for the puzzle above is this: 225 189 112
Code probably needs more boundary checks (overflows) as well as pruning of the search space, but for the most part it works. Code is down below, cheers, ACC.
using System; using System.Collections; using System.Collections.Generic; using System.Numerics; namespace ProductNumbersTarget { class Program { static void Main(string[] args) { int[] digits = { 9, 2, 5, 2, 1, 1, 8, 2, 1 }; Array.Sort(digits); BigInteger[] numbers = new BigInteger[3]; for (int i = 0; i < numbers.Length; i++) numbers[i] = 0; BigInteger target = 4762800; FindProductArrangement(digits, new Hashtable(), numbers, 0, target); } //0: found //1: greater //-1: smaller static int FindProductArrangement(int[] digits, Hashtable usedIndex, BigInteger[] numbers, int rotatingIndex, BigInteger target) { BigInteger product = MultiplyNumbers(numbers); if (usedIndex.Count == digits.Length) { if (product == target) { foreach (BigInteger n in numbers) Console.Write("{0} ", n); Console.WriteLine(); return 0; } else if (product > target) return 1; else return -1; } else if (product > target) return 1; bool productIsOver = false; bool[] indexOver = new bool[numbers.Length]; for (int i = 0; i < digits.Length && !productIsOver; i++) { if (!usedIndex.ContainsKey(i)) { usedIndex.Add(i, true); bool allProductOver = true; for (int j = 0; j < numbers.Length; j++) { int index = (j + rotatingIndex) % numbers.Length; if (indexOver[index]) continue; BigInteger temp = numbers[index]; numbers[index] = 10 * numbers[index] + digits[i]; int retVal = FindProductArrangement(digits, usedIndex, numbers, (index + 1) % numbers.Length, target); if (retVal == 0) return retVal; indexOver[index] = (retVal > 0); allProductOver &= indexOver[index]; numbers[index] = temp; } productIsOver = allProductOver; usedIndex.Remove(i); } } return -1; } static BigInteger MultiplyNumbers(BigInteger[] numbers) { BigInteger retVal = 1; foreach (BigInteger n in numbers) if (n > 0) retVal *= n; return retVal; } } }
Comments
Post a Comment