I've only extractedtarget
and exceptions
This can be directly copied to the parameters, as num
ElementCount
is bound by the implementationLinqPad and ran.
void Main()
{
string buffer;
int target;target, elementCount;
//get target
Console.WriteLine(">> Target is ..?");
while(!int.TryParse(buffer = Console.ReadLine(), out target))
Console.WriteLine("\tInvalid input : {0}", buffer);
Console.WriteLine(target);
//get elementCount
Console.WriteLine(">> Number of elements is ..?");
while(!int.TryParse(buffer = Console.ReadLine(), out elementCount) ||
1 > elementCount || elementCount > 6)
Console.WriteLine("\tInvalid input : {0}", buffer);
Console.WriteLine(elementCount);
Console.WriteLine(/*Empty Line*/);
//get exceptions
var validNumbers = Enumerable.Range(1, 9);
IEnumerable<int?> exceptions;
Console.WriteLine(">> Exceptions are ..? (separated with comma like : 1,2,3)");
while(!TryParseExceptions(buffer = Console.ReadLine(), out exceptions))
Console.WriteLine("\tInvalid input : {0}", buffer);
Console.WriteLine(string.Join(" ", exceptions.OrderBy(x => x)));
Console.WriteLine(/*Empty Line*/);
CalculateCombinations(target, elementCount, exceptions.Select(e => e.Value).Distinct());
}
int? ToNullableInt(string value)
{
int number;
return int.TryParse(value.Trim(), out number) ? (int?)number : null;
}
bool TryParseExceptions(string value, out IEnumerable<int?> exceptions)
{
//const int MinValue = 1, MaxValue = 9;
exceptions = value == ""
? Enumerable.Empty<int?>()
: value.Split(',').Select(ToNullableInt);
return exceptions.All(e => e.HasValue && (1 <= e.Value && e.Value <= 9)); //less verbose but magical...
//return exceptions.All(e => e.HasValue && (MinValue <= e.Value && e.Value <= MaxValue));
}
// Define other methods and classes here
void CalculateCombinations(int target, IEnumerable<int> exceptions)
{
const int ElementCount = 3;
elementCount, //varIEnumerable<int> target=12;exceptions)
//var exceptions=new List<int>{9,7,6};
var validNumbers = Enumerable.Range(1, 9).Except(exceptions);
// Make a Cartesian join of the three lists
// Filter out the stuff that we want
// Sort the result from highest to lowest
var combocombos = validNumbers.CartesianProduct(fromelementCount) l1 in validNumbers // Cartesian product
from l2 in validNumbers
.Where(x => x.GreaterThanNext() && // fromexclude l3duplicates
in validNumbers // Cartesian product
where l1 > l2 && l2 > l3 &&x.Sum(y => y) == target) // excludeadd duplicatesup to the target
l1 + l2 + l3 == target .OrderByDescending(x => x.First()); // add upsort tofrom the target1st number to...
for(int i = 1; i < elementCount; i++)
select new List<int>{
l1, l2, l3 })
.OrderByDescending(x => x[0])
///i would be incremented when the ienumerable unfolds
.ThenByDescending(x => x[1])
var index = i;
combos = combos.ThenByDescending(x => x[2]x.ElementAt(index)); // ... the [n]th
}
Console.WriteLine(string.Format("{0}/{1}", target, ElementCountelementCount));
foreach(var item in combocombos)
Console.WriteLine(string.Join("", item));
Console.Write("excluding : " + string.Join(" ", exceptions.OrderBy(x => x)));
}
//credit : http://ericlippert.com/2010/06/28/computing-a-cartesian-product-with-linq/
//slightly altered to reuse the same sequence
public static class Extensions
{
public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<T> sequence, int repeat)
{
IEnumerable<IEnumerable<T>> result = new[] { Enumerable.Empty<T>() };
for(int i = 0; i < repeat; i++)
{
// don't close over the loop variable (fixed in C# 5 BTW)
var s = sequence;
// recursive case: use SelectMany to build
// the new product out of the old one
result = from seq in result
from item in s
select seq.Concat(new[] {item});
}
return result;
}
public static bool GreaterThanNext(this IEnumerable<int> sequence)
{
if (sequence.Count() < 2) return true;
var previous = int.MaxValue;
foreach(var item in sequence)
if(previous <= item)
return false;
else previous = item;
return true;
}
}
Example of result :
>> Target is ..?
25
>> Number of elements is ..?
4
>> Exceptions are ..? (separated with comma like : 1,2,3)
1
25/4
9862
9853
9763
9754
8764
excluding : 1