Author Topic: Combinations in C#  (Read 1260 times)

0 Members and 1 Guest are viewing this topic.

Bill Tillman

  • Guest
Combinations in C#
« on: July 02, 2015, 09:40:07 PM »
I found a neat little block of code which may help solve a problem for me but I'm not sure how to get it working for my needs. Basically, I want to take an int[] and fill it with three values which are 301, 305, & 347. What this has helped me to do is to build a list of all the various combinations using these three integers, with repetitions. So far I've gotten it to dump a copy of what it produces to a text file. I had to do this because this easily fills up the buffer with Console.WriteLine. I'll be the first to admit that I really don't know this code that well, except that I can make it work so far. But please don't think for a moment that I really know what I'm doing.

It's presenting me with a few puzzles which I'm not sure about. I have a watch on variables 'c' and 'vf'. The first time through the loop 'c' is equal to 301, okay cool that's what I expected. But when I look at the value for 'vf' I see 51 '3', which I assume means 53, the ascii value for the number 3, and so forth. So I gather that instead of seeing what I thought it would be which is the entire value of 301, I'm getting a breakdown of the first element in the int[] array 'c' which is a '3'.... When you let this run complete and examine the text file it creates you can see what I'm after. And each combination of the array will mean something to a force equation I'm working with. No matter the boring details, I don't seem to grasp how to get this to work with the entire elements of the array one at a time, that is the integers 301, 305 and 347. And based on the value of the elements in 'c' I want to tally up some force values in the variable 'vdForce'. Each line in the text file will show the elements in the combination for that line and the sum of the forces.

This appears to work very well for permutations but I guess like all recursive code this one could hog up large chunks of RAM if the array is large. Fortunately, I only want to figure the combinations on three integers with up to six items in each line. BTW, in the file that this produces the integers on the right side of the equal sign are not correct. I'm still working on that part.

Code - C#: [Select]
  1. using System;
  2. using System.IO;
  3. using System.Collections.Generic;
  4.  
  5. namespace Combinations01
  6. {
  7.     class Program
  8.     {
  9.         static void Main(string[] args)
  10.         {            
  11.             int k = 1;
  12.             double vdForce = 0, vdTempVar;
  13.  
  14.             using (StreamWriter objWriter = new StreamWriter(@"C:\Combinations.txt"))
  15.             {
  16.                 for (int count = 1; count <= 6; count++)
  17.                 {
  18.                     foreach (var c in CombinationsWithRepition(new int[] { 301, 305, 347 }, count))
  19.                     {
  20.                         foreach (var vf in c)
  21.                         {
  22.                             vdTempVar = 100;
  23.                             if (vf == 305) vdTempVar = 200;
  24.                             if (vf == 347) vdTempVar = 300;
  25.                             vdForce = vdForce + vdTempVar;
  26.                         }
  27.                         objWriter.WriteLine("{0,4} -> {1}  =  {2}", k, c, vdForce);
  28.                         k = k + 1;
  29.                         vdForce = 0;
  30.                     }
  31.                 }
  32.             }
  33.         }
  34.  
  35.         static IEnumerable<String> CombinationsWithRepition(IEnumerable<int> input, int length)
  36.         {
  37.             if (length <= 0)
  38.                 yield return "";
  39.             else
  40.             {
  41.                 foreach (var i in input)
  42.                     foreach (var c in CombinationsWithRepition(input, length - 1))
  43.                         yield return i.ToString() + " " + c;
  44.             }
  45.         }
  46.     }
  47. }


edit:kdub -> code = csharp
« Last Edit: July 03, 2015, 01:25:57 AM by Kerry »

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: Combinations in C#
« Reply #1 on: July 06, 2015, 08:03:50 AM »
Are you trying to write the integer value "301,305,347" or do you want to write the ascii character for "301,305,347"?

Quote
But when I look at the value for 'vf' I see 51 '3', which I assume means 53, the ascii value for the number 3, and so forth. So I gather that instead of seeing what I thought it would be which is the entire value of 301, I'm getting a breakdown of the first element in the int[] array 'c' which is a '3'....
Your returning an IEnumerable<string> from CombinationsWithRepition() then iterating over every char in that strings char[].

CombinationsWithRepition() doesn't make any sense to me.  It seems to be recursive only to get an empty string then work its way back up to get the result you want.  Perhaps you could post what you want the end result to be and we can work back from there.
« Last Edit: July 06, 2015, 08:08:30 AM by MexicanCustard »
Revit 2019, AMEP 2019 64bit Win 10

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: Combinations in C#
« Reply #2 on: July 06, 2015, 09:23:13 AM »
Ok, I was so confused looking at CombinationWithRepition that I loaded this up in a new project.  Stepped through and it all made sense.  After looking at the output I think I understand what you're after.  You need to be returning an IEnumerable<IEnumerable<T>> from CombinationWithRepition()

This is what I came up with if I'm assuming correctly.
Code - C#: [Select]
  1. using System.Collections.Generic;
  2. using System.IO;
  3. using System.Linq;
  4.  
  5. namespace Combinations01
  6. {
  7.     class Program
  8.     {
  9.         static void Main(string[] args)
  10.         {
  11.             var k = 1;
  12.             double vdForce = 0;
  13.  
  14.             using (var objWriter = new StreamWriter(@"C:\Temp\Combinations.txt"))
  15.             {
  16.                 for (var count = 1; count <= 6; count++)
  17.                 {
  18.                     var combos = CombinationsWithRepition(new[] {301, 305, 347}, count).Select(i => i.ToArray());
  19.                     foreach (var combo in combos)
  20.                     {
  21.                         foreach (var number in combo)
  22.                         {
  23.                             double vdTempVar = 100;
  24.                             if (number == 305) vdTempVar = 200;
  25.                             if (number == 347) vdTempVar = 300;
  26.                             vdForce = vdForce + vdTempVar;
  27.                         }
  28.                         objWriter.WriteLine("{0,4} -> {1}  =  {2}", k, string.Join(" ", combo), vdForce);
  29.                         k = k + 1;
  30.                         vdForce = 0;
  31.                     }
  32.                 }
  33.             }
  34.         }
  35.  
  36.         static IEnumerable<IEnumerable<int>> CombinationsWithRepition(int[] input, int length)
  37.         {
  38.             if (length == 1)
  39.                 return input.Select(i => new[]{i});
  40.  
  41.             return CombinationsWithRepition(input, length - 1)
  42.                 .SelectMany(t => input, (t1, t2) => t1.Concat(new[] {t2}));
  43.         }
  44.     }
  45. }
  46.  

The output looks like this.
Code: [Select]
1 -> 301  =  100
   2 -> 305  =  200
   3 -> 347  =  300
   4 -> 301 301  =  200
   5 -> 301 305  =  300
   6 -> 301 347  =  400
   7 -> 305 301  =  300
   8 -> 305 305  =  400
   9 -> 305 347  =  500
  10 -> 347 301  =  400
  11 -> 347 305  =  500
  12 -> 347 347  =  600
  13 -> 301 301 301  =  300
  14 -> 301 301 305  =  400
  15 -> 301 301 347  =  500
  16 -> 301 305 301  =  400
  17 -> 301 305 305  =  500
  18 -> 301 305 347  =  600
  19 -> 301 347 301  =  500
  20 -> 301 347 305  =  600
  21 -> 301 347 347  =  700
  22 -> 305 301 301  =  400
  23 -> 305 301 305  =  500
  24 -> 305 301 347  =  600
  25 -> 305 305 301  =  500
  26 -> 305 305 305  =  600
  27 -> 305 305 347  =  700
  28 -> 305 347 301  =  600
  29 -> 305 347 305  =  700
  30 -> 305 347 347  =  800
  31 -> 347 301 301  =  500
  32 -> 347 301 305  =  600
  33 -> 347 301 347  =  700
  34 -> 347 305 301  =  600
  35 -> 347 305 305  =  700
  36 -> 347 305 347  =  800
  37 -> 347 347 301  =  700
  38 -> 347 347 305  =  800
  39 -> 347 347 347  =  900
Revit 2019, AMEP 2019 64bit Win 10