Skip to main content
4 of 5
added final solution for LinqPad testing
Xiaoy312
  • 3.1k
  • 16
  • 18

Naming

Use camelCase for local variable names. And, use a meaningful name if possible.

//var List1 = new List<int>{1,2,3,4,5,6,7,8,9};
var validNumbers = new List<int>{1,2,3,4,5,6,7,8,9};

Use pluralized noun for variable of collection type.

//var combo = ... /*combo contains all possible combinations, not just one*/
var combos

Code

  • You don't need to enumerate the numbers 1 to 9. A Enumerable.Range will do the job.
  • The chain of !exceptions.Contains(x) is rather inefficient and redundant. You can avoid them by removing the exceptions from the start with IEnumerable.Except.
  • You can reuse the same list in your LINQ.
  • You can reuse the same name for your lambdas given they are not within the same parentheses. (Not really a big problem)

Result :

var validNumbers = Enumerable.Range(1, 9).Except(exceptions);
var combos = (from a in validNumbers
              from b in validNumbers
              from b in validNumbers       // Cartesian product    
              where a > b && b > c &&      // exclude duplicates
                    a + b + c == target    // add up to the target 
              select new List<int>{ a, b , c})
             .OrderByDescending(x => x[0]) 
             .ThenByDescending(x => x[1])
             .ThenByDescending(x => x[2]);

In the last 2 blocks of the code, Console.Write was repeatedly called within the for loop. You can join them together with String.Join before printing it to the console.

Results :

foreach(var item in combos)
    Console.WriteLine(string.Join("", item));

Console.Write("excluding " + string.Join(" ", exceptions));

Final Code

I've only extractedtarget and exceptions to the parameters, as numElementCount is bound by the implementation.

void Main()
{
    string buffer;
    int target;
    
    //get target
    Console.WriteLine(">> Target is ..?");
    
    while(!int.TryParse(buffer = Console.ReadLine(), out target))
        Console.WriteLine("\tInvalid input : {0}", buffer);
    Console.WriteLine(target);
    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, 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;
    //var target=12;
    //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 combo = (from l1 in validNumbers
                from l2 in validNumbers
                from l3 in validNumbers        // Cartesian product    
                where l1 > l2 && l2 > l3 &&   // exclude duplicates
                    l1 + l2 + l3 == target   // add up to the target 
                select new List<int>{ l1, l2, l3 })
            .OrderByDescending(x => x[0]) 
            .ThenByDescending(x => x[1])
            .ThenByDescending(x => x[2]);
    
    Console.WriteLine(string.Format("{0}/{1}", target, ElementCount));
    
    foreach(var item in combo)
        Console.WriteLine(string.Join("", item));
    
    Console.Write("excluding : " + string.Join(" ", exceptions.OrderBy(x => x)));
}
Xiaoy312
  • 3.1k
  • 16
  • 18