我一直在工作,放弃然后重新处理这个问题几天。我已经看了很多不同的方法,但是我要么无法正确实现它,要么不适合我需要做的事情。
基本上:我有两个数组,前缀和后缀
prefix = { 0, 0, 3, 8, 8, 15}
suffix = { 0, 3, 2, 7, 7, 9, 12, 15 }
我需要:
最终目标是查看哪些组合可以等于X.
例如
X = 42
3 + 8 + 8 + 2 + 9 + 12 = 42
0 + 8 + 8 + 7 + 7 + 12 = 42
| Prefix | | Suffix |
15 + 12 + 15 = 42
0 + 15 + 0 + 12 + 15 = 42
我已经尝试过研究Permutations,IEnumerables,Concat等等,但找不到能成功做到这一点的东西。
这些是我需要使用的“完整”数组。
public int[] Prefix = {0, 6, 6, 8, 8, 8, 8, 8, 8, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 16, 15, 15, 18, 18, 18, 18, 18, 18, 23 };
public int[] Suffix = {0, 3, 3, 9, 11, 11, 11, 17, 18, 18, 20, 25, 25, 27, 30, 30};
任何帮助都表示赞赏,如果我不清楚任何事情我会尽可能地澄清,谢谢!
编辑:我还建议我运行它来等同于所有可能的结果并将其存储在哈希表中,以便在使用正确的值时使用?不确定哪种方法效果最好。
答案 0 :(得分:2)
采用“OR Javascript”选项......
expected_result - total
位于前缀的关联数组中时,才会使用后缀排列填充它。// Inputs
var prefixes = [0, 6, 6, 8, 8, 8, 8, 8, 8, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 16, 15, 15, 18, 18, 18, 18, 18, 18, 23],
suffixes = [0, 3, 3, 9, 11, 11, 11, 17, 18, 18, 20, 25, 25, 27, 30, 30],
expected_result = 42;
// Associative Arrays
var prefixTotals = {},
suffixTotals = {},
// Functions
addTotal = function( map, arr, other_map ){
var t = 0, i = 0;
for ( ; i < arr.length; ++i )
t += arr[i].value;
if ( ( other_map === undefined )
|| ( ( expected_result - t ) in other_map ) )
{
if ( !( t in map ) )
map[t] = [];
map[t].push( arr );
}
},
calcPermutations = function( affixes, map, other_map ) {
var i = 0, j, k, l = affixes.length;
for ( ; i < l; ++i )
{
addTotal( map, [ { index: i, value: affixes[i] } ], other_map );
for ( j = i+1; j < l; ++j )
{
addTotal( map, [ { index: i, value: affixes[i] }, { index: j, value: affixes[j] } ], other_map );
for ( k = j+1; k < l; ++k )
{
addTotal( map, [ { index: i, value: affixes[i] }, { index: j, value: affixes[j] }, { index: k, value: affixes[k] } ], other_map );
}
}
}
},
resultToString = function( affixes ){
var s = [];
for ( var i = 0; i < affixes.length; ++i )
s.push( affixes[i].index + '=>' + affixes[i].value );
return s.join(',');
};
calcPermutations( prefixes, prefixTotals, undefined );
calcPermutations( suffixes, suffixTotals, prefixTotals );
var i,j,k,p,s,count = 0,html=[];
for ( i in suffixTotals )
{
s = suffixTotals[i];
p = prefixTotals[expected_result - i];
for ( j = 0; j < p.length; ++j )
for ( k = 0; k < s.length; ++k )
html.push( 'Prefixes [' + resultToString( p[j] ) + '], Suffixes [' + resultToString( s[k] ) + ']' );
count += p.length * s.length;
}
html.unshift( 'There were ' + count + ' valid permutations:' );
document.getElementById( 'out' ).innerHTML = html.join( '<br />' );
答案 1 :(得分:1)
正如所建议的,你当然可以嵌套循环直到Pascal抱怨他的三角形,但如果你愿意,你也可以采取完全概率的方法:)
毕竟,当蛮力解决方案正在执行时,a rogue alpha particle can flip an entire bit in the memory cells无论如何也无法提出正确答案。 (这是一个笑话。请不要向我投降,让宇宙射线击中SO服务器来处理它。)
42 ==
prefix.OrderBy(x => random.Next(0,prefix.Length)).Take(random.Next(1,4)).Sum()
+
suffix.OrderBy(x => random.Next(0,suffix.Length)).Take(random.Next(1,4)).Sum();
这是一个演示,
using System;
using System.Linq;
namespace WhatWasTheQuestion {
class Program {
static readonly int[] prefix = { 0, 0, 3, 8, 8, 15 };
static readonly int[] suffix = { 0, 3, 2, 7, 7, 9, 12, 15 };
static readonly Random random = new Random();
static bool generateAndCheckCandidate(int X) {
var prefixCandidates = prefix.OrderBy(x => random.Next(0, prefix.Length)).Take(random.Next(1, 4)).ToList();
var suffixCandidates = suffix.OrderBy(x => random.Next(0, suffix.Length)).Take(random.Next(1, 4)).ToList();
if (prefixCandidates.Sum() + suffixCandidates.Sum() == X) {
Console.WriteLine(X + " = " + String.Join("+", prefixCandidates) + "+" + String.Join("+", suffixCandidates));
return true;
}
return false;
}
static void Main(string[] args) {
int maxAttempts = 10000;
while (maxAttempts > 0 && !generateAndCheckCandidate(42))
{
--maxAttempts;
}
}
}
}
// Output:
// 42 = 8+15+0+0+7+12+0
答案 2 :(得分:1)
这是一个使用LINQ的直观(虽然很慢)的解决方案:
int[] prefixes = { 0, 0, 3, 8, 8, 15 };
int[] suffixes = { 0, 3, 2, 7, 7, 9, 12, 15 };
int target = 42;
var results =
from prefixLength in Enumerable.Range(1, 3)
from suffixLength in Enumerable.Range(1, 3)
where prefixLength + suffixLength >= 3
from prefixPermutation in prefixes.GetPermutations(prefixLength)
from suffixPermutation in suffixes.GetPermutations(suffixLength)
let affixPermutation = prefixPermutation.Concat(suffixPermutation)
where affixPermutation.Sum() == target
select string.Join(" + ", affixPermutation);
var final = results.Distinct().ToArray();
我使用了一些基本的可枚举扩展:
public static partial class EnumerableExtensions
{
public static IEnumerable<IEnumerable<T>> GetPermutations<T>(this IEnumerable<T> source, int length)
{
if (length == 0)
{
yield return Enumerable.Empty<T>();
yield break;
}
int index = 0;
foreach (T item in source)
{
IEnumerable<T> remainder = source.ExceptAt(index);
IEnumerable<IEnumerable<T>> tails = GetPermutations(remainder, length - 1);
foreach (IEnumerable<T> tail in tails)
yield return tail.Prepend(item);
index++;
}
}
public static IEnumerable<T> ExceptAt<T>(this IEnumerable<T> source, int index)
{
return source.Take(index).Concat(source.Skip(index + 1));
}
public static IEnumerable<T> Prepend<T>(this IEnumerable<T> source, T first)
{
yield return first;
foreach (T item in source)
yield return item;
}
}
答案 3 :(得分:1)
对于那么多代码感到抱歉。它不是印度人,完全100%工作:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication1
{
static class Program
{
static void Main(string[] args)
{
Console.Write("Sum: ");
var sum = int.Parse(Console.ReadLine());
var prefix = new[] { 1, 2, 3, 4, 5, 6 };
var suffix = new[] { 0, 3, 2, 7, 7, 9, 12, 15 };
foreach (var item in Solution(prefix, suffix, 1, 3, sum))
{
Console.WriteLine("{0} = [ {1} ] + [ {2} ]", sum, string.Join(" + ", item.Item1.Select(T => prefix[T])), string.Join(" + ", item.Item2.Select(T => suffix[T])));
}
Console.WriteLine("Done here. Any key to close.");
Console.ReadKey();
}
public static IEnumerable<Tuple<int[], int[]>> Solution(int[] one, int[] two, int minElementCount, int maxElementCount, int sum)
{
if (one.Length < minElementCount || two.Length < minElementCount)
{
throw new Exception("Nah.");
}
var cacheOne = new Dictionary<int, List<int[]>>();
var cacheTwo = new Dictionary<int, List<int[]>>();
var result = new List<Tuple<int[], int[]>>();
for (int countInOne = minElementCount; countInOne <= Math.Min(one.Length, maxElementCount); countInOne++)
{
for (int countInTwo = minElementCount; countInTwo <= Math.Min(two.Length, maxElementCount); countInTwo++)
{
List<int[]> permutationsOne;
List<int[]> permutationsTwo;
if (!cacheOne.TryGetValue(countInOne, out permutationsOne))
{
permutationsOne = cacheOne[countInOne] = PermutationsIndices(one, countInOne).ToList();
}
if (!cacheTwo.TryGetValue(countInTwo, out permutationsTwo))
{
permutationsTwo = cacheTwo[countInTwo] = PermutationsIndices(two, countInTwo).ToList();
}
foreach (var permutationOne in permutationsOne)
{
var sumOne = permutationOne.Select(T => one[T]).Sum();
if (sumOne <= sum)
{
foreach (var permutationTwo in permutationsTwo)
{
if ((sumOne + permutationTwo.Select(T => two[T]).Sum() == sum))
{
yield return Tuple.Create(permutationOne, permutationTwo);
}
}
}
}
}
}
}
public static IEnumerable<int[]> PermutationsIndices<T>(this T[] e, int count)
{
if (count > e.Length)
{
throw new Exception("Nah.");
}
return TraverseArray(e, new Stack<int>(), 0, count - 1);
}
public static IEnumerable<int[]> TraverseArray<T>(T[] array, Stack<int> stack, int index, int iterations)
{
for (int i = index; i < array.Length - iterations; i++)
{
stack.Push(i);
if (iterations == 0)
{
yield return stack.Reverse().ToArray();
}
else
{
foreach (int[] item in TraverseArray(array, stack, i + 1, iterations - 1))
{
yield return item;
}
}
stack.Pop();
}
}
}
}
所以,你的任务输出......
prefix = { 0, 0, 3, 8, 8, 15 }
suffix = { 0, 3, 2, 7, 7, 9, 12, 15 }
将是这样:
Sum: 42
42 = [ 15 ] + [ 12 + 15 ]
42 = [ 8 ] + [ 7 + 12 + 15 ]
42 = [ 8 ] + [ 7 + 12 + 15 ]
42 = [ 8 ] + [ 7 + 12 + 15 ]
42 = [ 8 ] + [ 7 + 12 + 15 ]
42 = [ 15 ] + [ 0 + 12 + 15 ]
42 = [ 15 ] + [ 3 + 9 + 15 ]
42 = [ 0 + 15 ] + [ 12 + 15 ]
42 = [ 0 + 15 ] + [ 12 + 15 ]
42 = [ 3 + 15 ] + [ 9 + 15 ]
42 = [ 8 + 15 ] + [ 7 + 12 ]
42 = [ 8 + 15 ] + [ 7 + 12 ]
42 = [ 8 + 15 ] + [ 7 + 12 ]
42 = [ 8 + 15 ] + [ 7 + 12 ]
42 = [ 0 + 8 ] + [ 7 + 12 + 15 ]
42 = [ 0 + 8 ] + [ 7 + 12 + 15 ]
42 = [ 0 + 8 ] + [ 7 + 12 + 15 ]
42 = [ 0 + 8 ] + [ 7 + 12 + 15 ]
42 = [ 0 + 15 ] + [ 0 + 12 + 15 ]
42 = [ 0 + 15 ] + [ 3 + 9 + 15 ]
42 = [ 0 + 8 ] + [ 7 + 12 + 15 ]
42 = [ 0 + 8 ] + [ 7 + 12 + 15 ]
42 = [ 0 + 8 ] + [ 7 + 12 + 15 ]
42 = [ 0 + 8 ] + [ 7 + 12 + 15 ]
42 = [ 0 + 15 ] + [ 0 + 12 + 15 ]
42 = [ 0 + 15 ] + [ 3 + 9 + 15 ]
42 = [ 3 + 8 ] + [ 7 + 9 + 15 ]
42 = [ 3 + 8 ] + [ 7 + 9 + 15 ]
42 = [ 3 + 8 ] + [ 7 + 9 + 15 ]
42 = [ 3 + 8 ] + [ 7 + 9 + 15 ]
42 = [ 3 + 15 ] + [ 0 + 9 + 15 ]
42 = [ 3 + 15 ] + [ 3 + 9 + 12 ]
42 = [ 3 + 15 ] + [ 2 + 7 + 15 ]
42 = [ 3 + 15 ] + [ 2 + 7 + 15 ]
42 = [ 8 + 8 ] + [ 2 + 9 + 15 ]
42 = [ 8 + 8 ] + [ 7 + 7 + 12 ]
42 = [ 8 + 15 ] + [ 0 + 7 + 12 ]
42 = [ 8 + 15 ] + [ 0 + 7 + 12 ]
42 = [ 8 + 15 ] + [ 3 + 7 + 9 ]
42 = [ 8 + 15 ] + [ 3 + 7 + 9 ]
42 = [ 8 + 15 ] + [ 0 + 7 + 12 ]
42 = [ 8 + 15 ] + [ 0 + 7 + 12 ]
42 = [ 8 + 15 ] + [ 3 + 7 + 9 ]
42 = [ 8 + 15 ] + [ 3 + 7 + 9 ]
42 = [ 0 + 0 + 15 ] + [ 12 + 15 ]
42 = [ 0 + 3 + 15 ] + [ 9 + 15 ]
42 = [ 0 + 8 + 15 ] + [ 7 + 12 ]
42 = [ 0 + 8 + 15 ] + [ 7 + 12 ]
42 = [ 0 + 8 + 15 ] + [ 7 + 12 ]
42 = [ 0 + 8 + 15 ] + [ 7 + 12 ]
42 = [ 0 + 3 + 15 ] + [ 9 + 15 ]
42 = [ 0 + 8 + 15 ] + [ 7 + 12 ]
42 = [ 0 + 8 + 15 ] + [ 7 + 12 ]
42 = [ 0 + 8 + 15 ] + [ 7 + 12 ]
42 = [ 0 + 8 + 15 ] + [ 7 + 12 ]
42 = [ 3 + 8 + 15 ] + [ 7 + 9 ]
42 = [ 3 + 8 + 15 ] + [ 7 + 9 ]
42 = [ 3 + 8 + 15 ] + [ 7 + 9 ]
42 = [ 3 + 8 + 15 ] + [ 7 + 9 ]
42 = [ 8 + 8 + 15 ] + [ 2 + 9 ]
42 = [ 0 + 0 + 8 ] + [ 7 + 12 + 15 ]
42 = [ 0 + 0 + 8 ] + [ 7 + 12 + 15 ]
42 = [ 0 + 0 + 8 ] + [ 7 + 12 + 15 ]
42 = [ 0 + 0 + 8 ] + [ 7 + 12 + 15 ]
42 = [ 0 + 0 + 15 ] + [ 0 + 12 + 15 ]
42 = [ 0 + 0 + 15 ] + [ 3 + 9 + 15 ]
42 = [ 0 + 3 + 8 ] + [ 7 + 9 + 15 ]
42 = [ 0 + 3 + 8 ] + [ 7 + 9 + 15 ]
42 = [ 0 + 3 + 8 ] + [ 7 + 9 + 15 ]
42 = [ 0 + 3 + 8 ] + [ 7 + 9 + 15 ]
42 = [ 0 + 3 + 15 ] + [ 0 + 9 + 15 ]
42 = [ 0 + 3 + 15 ] + [ 3 + 9 + 12 ]
42 = [ 0 + 3 + 15 ] + [ 2 + 7 + 15 ]
42 = [ 0 + 3 + 15 ] + [ 2 + 7 + 15 ]
42 = [ 0 + 8 + 8 ] + [ 2 + 9 + 15 ]
42 = [ 0 + 8 + 8 ] + [ 7 + 7 + 12 ]
42 = [ 0 + 8 + 15 ] + [ 0 + 7 + 12 ]
42 = [ 0 + 8 + 15 ] + [ 0 + 7 + 12 ]
42 = [ 0 + 8 + 15 ] + [ 3 + 7 + 9 ]
42 = [ 0 + 8 + 15 ] + [ 3 + 7 + 9 ]
42 = [ 0 + 8 + 15 ] + [ 0 + 7 + 12 ]
42 = [ 0 + 8 + 15 ] + [ 0 + 7 + 12 ]
42 = [ 0 + 8 + 15 ] + [ 3 + 7 + 9 ]
42 = [ 0 + 8 + 15 ] + [ 3 + 7 + 9 ]
42 = [ 0 + 3 + 8 ] + [ 7 + 9 + 15 ]
42 = [ 0 + 3 + 8 ] + [ 7 + 9 + 15 ]
42 = [ 0 + 3 + 8 ] + [ 7 + 9 + 15 ]
42 = [ 0 + 3 + 8 ] + [ 7 + 9 + 15 ]
42 = [ 0 + 3 + 15 ] + [ 0 + 9 + 15 ]
42 = [ 0 + 3 + 15 ] + [ 3 + 9 + 12 ]
42 = [ 0 + 3 + 15 ] + [ 2 + 7 + 15 ]
42 = [ 0 + 3 + 15 ] + [ 2 + 7 + 15 ]
42 = [ 0 + 8 + 8 ] + [ 2 + 9 + 15 ]
42 = [ 0 + 8 + 8 ] + [ 7 + 7 + 12 ]
42 = [ 0 + 8 + 15 ] + [ 0 + 7 + 12 ]
42 = [ 0 + 8 + 15 ] + [ 0 + 7 + 12 ]
42 = [ 0 + 8 + 15 ] + [ 3 + 7 + 9 ]
42 = [ 0 + 8 + 15 ] + [ 3 + 7 + 9 ]
42 = [ 0 + 8 + 15 ] + [ 0 + 7 + 12 ]
42 = [ 0 + 8 + 15 ] + [ 0 + 7 + 12 ]
42 = [ 0 + 8 + 15 ] + [ 3 + 7 + 9 ]
42 = [ 0 + 8 + 15 ] + [ 3 + 7 + 9 ]
42 = [ 3 + 8 + 8 ] + [ 2 + 9 + 12 ]
42 = [ 3 + 8 + 8 ] + [ 7 + 7 + 9 ]
42 = [ 3 + 8 + 15 ] + [ 0 + 7 + 9 ]
42 = [ 3 + 8 + 15 ] + [ 0 + 7 + 9 ]
42 = [ 3 + 8 + 15 ] + [ 2 + 7 + 7 ]
42 = [ 3 + 8 + 15 ] + [ 0 + 7 + 9 ]
42 = [ 3 + 8 + 15 ] + [ 0 + 7 + 9 ]
42 = [ 3 + 8 + 15 ] + [ 2 + 7 + 7 ]
42 = [ 8 + 8 + 15 ] + [ 0 + 2 + 9 ]
Done here. Any key to close.
答案 4 :(得分:0)
这不是一个漂亮的解决方案,但它是一个有效的解决方案。 请注意我如何确保前缀和后缀在开始时都有两个零,以便还包括只使用该数组中的一个或两个值的情况。
int[] prefix = { 0, 0, 3, 8, 8, 15};
int[] suffix = { 0, 0, 3, 2, 7, 7, 9, 12, 15 };
for(int p1 = 0; p1 < prefix.Length; p1++) {
for(int p2 = 0; p2 < prefix.Length; p2++) {
for(int p3 = 0; p3 < prefix.Length; p3++) {
for(int s1 = 0; s1 < suffix.Length; s1++) {
for(int s2 = 0; s2 < suffix.Length; s2++) {
for(int s3 = 0; s3 < suffix.Length; s3++) {
if(prefix[p1] + prefix[p2] + prefix[p3] + suffix[s1] + suffix[s2] + suffix[s3] == 42)
{
System.Console.WriteLine(string.Format("{0} + {1} + {2} + {3} + {4} + {5} = 42", prefix[p1], prefix[p2], prefix[p3], suffix[s1], suffix[s2], suffix[s3] ));
}
}
}
}
}
}
答案 5 :(得分:0)
这是另一种强制解决方案的替代方案。我不得不在没有LINQ的情况下在.NET 3上编写它,所以我编写了自己的辅助方法来汇总和连接值 - 因此代码量很大。
EnumerateIndices
和Sum42
正在完成所有工作。使用LINQ可以缩短它的速度,但我现在无法访问它,所以在我意外引入任何错误之前,我会留下它来清理它。
public static IEnumerable<int[]> EnumerateIndices(int[] values, int length)
{
int[] result = new int[length];
int size = (int)(Math.Pow(values.Length, length));
for(int i = 0; i < size; ++i)
{
int tmp = i;
for(int j = length - 1; j >= 0; --j)
{
result[j] = values[tmp % values.Length];
tmp /= values.Length;
}
yield return result;
}
}
public static int Sum(int[] values)
{
// Just a helper method - if you can use LINQ replace by values.Sum()
int result = 0, size = values.Length;
for(int i = 0; i < size; ++i)
{
result += values[i];
}
return result;
}
public static string Join(string separator, int[] values)
{
// Just a helper method, if you can use LINQ replace by sth like string.Join(separator, values.ToArray<string>())
string[] stringValues = new string[values.Length];
int size = values.Length;
for(int i = 0; i < size; ++i)
{
stringValues[i] = values[i].ToString();
}
return string.Join(separator, stringValues);
}
public static void Sum42()
{
int[] prefix = { 0, 0, 3, 8, 8, 15};
int[] suffix = { 0, 3, 2, 7, 7, 9, 12, 15 };
IEnumerable<int[]> prefixes = EnumerateIndices(prefix, 3);
IEnumerable<int[]> suffixes = EnumerateIndices(suffix, 3);
foreach(int[] p in prefixes) {
foreach(int[] s in suffixes) {
if(Sum(p) + Sum(s) == 42)
{
System.Console.WriteLine("{0} + {1} = 42", Join(" + ", p), Join(" + ", s));
}
}
}
}