Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. The Lounge
  3. Monday's programming question of the day

Monday's programming question of the day

Scheduled Pinned Locked Moved The Lounge
csharpc++comdata-structuresregex
22 Posts 16 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Marc Clifton

    Let's say you have n combinations of v items, and you want create a sequential string that represents every non-duplicate combination of those v items. So, 3 combinations (3 columns) of 4 items (0 through 3 inclusive) would look like: 0 1 2 0 1 3 0 2 3 1 2 3 and you also want to create the same pattern in reverse: 1 2 3 0 2 3 0 1 3 0 1 2 However, you don't want to create the entire list in memory (because, for example, 8 combinations of 58 items will result in billions of rows). Instead, you want to get each combination sequentially, forward or reverse, as requested, given the last state. Here's a C++ implementation I wrote a while ago that iterates in the forward direction, using an array to manage the current state:

    bool MyList::GetNext(int numCombinations)
    {
    if (numCombinations==-1)
    {
    return false;
    }

    int q=list\[numCombinations\];
    ++q;
    
    while (q >= numItems)
    {
    	if (numCombinations==0)
    	{
    		return false;
    	}
    	if (!GetNext(numCombinations-1))
    	{
    		return false;
    	}
    
    	q=list\[numCombinations-1\]+1;
    }
    
    list\[numCombinations\]=q;
    return true;
    

    }

    Use your favorite language to write this. :) (Yeah, I must admit, I'm personally interested in cool C# 3.5 examples) Marc

    Thyme In The Country Interacx My Blog

    S Offline
    S Offline
    Super Lloyd
    wrote on last edited by
    #8

    Here is a C# enhanced version

    static IEnumerable<int> GetPermutation(int index, int selcount, int objcount)
    {
    List<int> list = new List<int>(objcount);
    for (int i = 0; i < objcount; i++)
    list.Add(i);
    for (int i = 0; i < selcount; i++)
    {
    int N = list.Count;
    int k = index % N;
    index /= N;

    	int result = list\[k\];
    	list.RemoveAt(k);
    	yield return result;
    }
    

    }

    A train station is where the train stops. A bus station is where the bus stops. On my desk, I have a work station.... _________________________________________________________ My programs never have bugs, they just develop random features.

    modified on Tuesday, September 16, 2008 1:06 AM

    1 Reply Last reply
    0
    • M Marc Clifton

      Let's say you have n combinations of v items, and you want create a sequential string that represents every non-duplicate combination of those v items. So, 3 combinations (3 columns) of 4 items (0 through 3 inclusive) would look like: 0 1 2 0 1 3 0 2 3 1 2 3 and you also want to create the same pattern in reverse: 1 2 3 0 2 3 0 1 3 0 1 2 However, you don't want to create the entire list in memory (because, for example, 8 combinations of 58 items will result in billions of rows). Instead, you want to get each combination sequentially, forward or reverse, as requested, given the last state. Here's a C++ implementation I wrote a while ago that iterates in the forward direction, using an array to manage the current state:

      bool MyList::GetNext(int numCombinations)
      {
      if (numCombinations==-1)
      {
      return false;
      }

      int q=list\[numCombinations\];
      ++q;
      
      while (q >= numItems)
      {
      	if (numCombinations==0)
      	{
      		return false;
      	}
      	if (!GetNext(numCombinations-1))
      	{
      		return false;
      	}
      
      	q=list\[numCombinations-1\]+1;
      }
      
      list\[numCombinations\]=q;
      return true;
      

      }

      Use your favorite language to write this. :) (Yeah, I must admit, I'm personally interested in cool C# 3.5 examples) Marc

      Thyme In The Country Interacx My Blog

      H Offline
      H Offline
      Hawk777
      wrote on last edited by
      #9

      I already did this, albeit without the reversal (which could trivially be added in the caller): http://www.codeproject.com/KB/recipes/combinations.aspx

      1 Reply Last reply
      0
      • M Marc Clifton

        Let's say you have n combinations of v items, and you want create a sequential string that represents every non-duplicate combination of those v items. So, 3 combinations (3 columns) of 4 items (0 through 3 inclusive) would look like: 0 1 2 0 1 3 0 2 3 1 2 3 and you also want to create the same pattern in reverse: 1 2 3 0 2 3 0 1 3 0 1 2 However, you don't want to create the entire list in memory (because, for example, 8 combinations of 58 items will result in billions of rows). Instead, you want to get each combination sequentially, forward or reverse, as requested, given the last state. Here's a C++ implementation I wrote a while ago that iterates in the forward direction, using an array to manage the current state:

        bool MyList::GetNext(int numCombinations)
        {
        if (numCombinations==-1)
        {
        return false;
        }

        int q=list\[numCombinations\];
        ++q;
        
        while (q >= numItems)
        {
        	if (numCombinations==0)
        	{
        		return false;
        	}
        	if (!GetNext(numCombinations-1))
        	{
        		return false;
        	}
        
        	q=list\[numCombinations-1\]+1;
        }
        
        list\[numCombinations\]=q;
        return true;
        

        }

        Use your favorite language to write this. :) (Yeah, I must admit, I'm personally interested in cool C# 3.5 examples) Marc

        Thyme In The Country Interacx My Blog

        D Offline
        D Offline
        dwales
        wrote on last edited by
        #10

        //(c++) forward only (not just for 0-9)
        void doit( int nitems, int col, vector v=vector(), int colval=0 )
        {
        if ( col==0 ){
        for (int i(0); i < v.size(); ++i) cout << " " << v[i];
        cout << endl;
        return;
        }

        for( int i(colval); i < nitems; ++i ){
        vector v1 = v;
        v1.push_back(i);
        doit( nitems, col - 1, v1, i+1 );
        }
        }

        kick it off with

        doit( nitems, ncols)

        modified on Tuesday, September 16, 2008 1:31 AM

        1 Reply Last reply
        0
        • M Marc Clifton

          Let's say you have n combinations of v items, and you want create a sequential string that represents every non-duplicate combination of those v items. So, 3 combinations (3 columns) of 4 items (0 through 3 inclusive) would look like: 0 1 2 0 1 3 0 2 3 1 2 3 and you also want to create the same pattern in reverse: 1 2 3 0 2 3 0 1 3 0 1 2 However, you don't want to create the entire list in memory (because, for example, 8 combinations of 58 items will result in billions of rows). Instead, you want to get each combination sequentially, forward or reverse, as requested, given the last state. Here's a C++ implementation I wrote a while ago that iterates in the forward direction, using an array to manage the current state:

          bool MyList::GetNext(int numCombinations)
          {
          if (numCombinations==-1)
          {
          return false;
          }

          int q=list\[numCombinations\];
          ++q;
          
          while (q >= numItems)
          {
          	if (numCombinations==0)
          	{
          		return false;
          	}
          	if (!GetNext(numCombinations-1))
          	{
          		return false;
          	}
          
          	q=list\[numCombinations-1\]+1;
          }
          
          list\[numCombinations\]=q;
          return true;
          

          }

          Use your favorite language to write this. :) (Yeah, I must admit, I'm personally interested in cool C# 3.5 examples) Marc

          Thyme In The Country Interacx My Blog

          S Offline
          S Offline
          Stuart Dootson
          wrote on last edited by
          #11

          OK - an outline sketch of part of the problem in my language of choice, Haskell (a lazy, pure functional language)

          indices :: Num a => [a] -> a -> Maybe [a]
          indices [] _ = Nothing
          indices l max =
          if (last l)==max
          then indices (init l) (max-1) >>= \stub -> return $ stub ++ [(last stub)+1]
          else Just $ (init l) ++ [(last l)+1]

          loop :: (Num a, Enum a) => a -> a -> Maybe [a]
          loop count max =
          loop' [0..count-1] max
          where
          loop' l max = indices l max >>= \next -> loop' next max

          indices takes a list of indices (which would be used to de-reference the list of items using map (items !!) index_list) and the max count and returns the next list of indices in the required sequence. The list is wrapped in the Maybe type, so returns Just _the list_ when there are still items in the sequence or Nothing when the sequence is complete. The one point of interest is the then branch of the if, which makes use of the monadic nature of Maybe to propagate Nothing or manipulate the returned sub-list. loop takes the # combinations and # items and iterates through the sequence via loop' until indices returns Nothing. Again, the monadic nature of Maybe is used, to terminate the sequence. So, the 'state' is the index list, passed into indices and then (Maybe :-)) returned from indices. As Haskell is pure functional (therefore, no mutable state), that's how you have to manage state. OK, it doesn't do the whole problem, but it illustrates the flavour of a possible Haskell solution. Basic garbage collection profiling shows that memory in use remains constant, independent of the parameters passed to loop, so that satisfies the condition that you don't generate all items of the sequence in memory at once.

          1 Reply Last reply
          0
          • M Marc Clifton

            Let's say you have n combinations of v items, and you want create a sequential string that represents every non-duplicate combination of those v items. So, 3 combinations (3 columns) of 4 items (0 through 3 inclusive) would look like: 0 1 2 0 1 3 0 2 3 1 2 3 and you also want to create the same pattern in reverse: 1 2 3 0 2 3 0 1 3 0 1 2 However, you don't want to create the entire list in memory (because, for example, 8 combinations of 58 items will result in billions of rows). Instead, you want to get each combination sequentially, forward or reverse, as requested, given the last state. Here's a C++ implementation I wrote a while ago that iterates in the forward direction, using an array to manage the current state:

            bool MyList::GetNext(int numCombinations)
            {
            if (numCombinations==-1)
            {
            return false;
            }

            int q=list\[numCombinations\];
            ++q;
            
            while (q >= numItems)
            {
            	if (numCombinations==0)
            	{
            		return false;
            	}
            	if (!GetNext(numCombinations-1))
            	{
            		return false;
            	}
            
            	q=list\[numCombinations-1\]+1;
            }
            
            list\[numCombinations\]=q;
            return true;
            

            }

            Use your favorite language to write this. :) (Yeah, I must admit, I'm personally interested in cool C# 3.5 examples) Marc

            Thyme In The Country Interacx My Blog

            R Offline
            R Offline
            Roger Alsing 0
            wrote on last edited by
            #12

            C#3 list extension method:

            public static IEnumerable< IList< T >> GetPremutations< T >(this IList< T > items, int columns)
            {
            for (int i = 0; i < (int)Math.Pow(items.Count, columns); i++)
            {
            IList< T > result = new List< T >();

                for (int k = 0; k < columns; k++) 
                    result.Add(items\[(i / (int)Math.Pow(items.Count,k) ) % items.Count\]);
            
                yield return result;
            }
            

            }

            This will return a list of the elements for each premutation. (not a list with all premutations, a list for each entry in the premutation set... each entry is yielded by the enumerator) (However, this will crash and burn at large sets due to int overflows)

            My Blog

            J 1 Reply Last reply
            0
            • M Marc Clifton

              Let's say you have n combinations of v items, and you want create a sequential string that represents every non-duplicate combination of those v items. So, 3 combinations (3 columns) of 4 items (0 through 3 inclusive) would look like: 0 1 2 0 1 3 0 2 3 1 2 3 and you also want to create the same pattern in reverse: 1 2 3 0 2 3 0 1 3 0 1 2 However, you don't want to create the entire list in memory (because, for example, 8 combinations of 58 items will result in billions of rows). Instead, you want to get each combination sequentially, forward or reverse, as requested, given the last state. Here's a C++ implementation I wrote a while ago that iterates in the forward direction, using an array to manage the current state:

              bool MyList::GetNext(int numCombinations)
              {
              if (numCombinations==-1)
              {
              return false;
              }

              int q=list\[numCombinations\];
              ++q;
              
              while (q >= numItems)
              {
              	if (numCombinations==0)
              	{
              		return false;
              	}
              	if (!GetNext(numCombinations-1))
              	{
              		return false;
              	}
              
              	q=list\[numCombinations-1\]+1;
              }
              
              list\[numCombinations\]=q;
              return true;
              

              }

              Use your favorite language to write this. :) (Yeah, I must admit, I'm personally interested in cool C# 3.5 examples) Marc

              Thyme In The Country Interacx My Blog

              O Offline
              O Offline
              Oldes
              wrote on last edited by
              #13

              I'm not sure if you can count this, but in REBOL console:

              >> sort/reverse [[0 1 2][0 1 3] [0 2 3] [1 2 3]]
              == [[1 2 3] [0 2 3] [0 1 3] [0 1 2]]

              1 Reply Last reply
              0
              • M Marc Clifton

                Let's say you have n combinations of v items, and you want create a sequential string that represents every non-duplicate combination of those v items. So, 3 combinations (3 columns) of 4 items (0 through 3 inclusive) would look like: 0 1 2 0 1 3 0 2 3 1 2 3 and you also want to create the same pattern in reverse: 1 2 3 0 2 3 0 1 3 0 1 2 However, you don't want to create the entire list in memory (because, for example, 8 combinations of 58 items will result in billions of rows). Instead, you want to get each combination sequentially, forward or reverse, as requested, given the last state. Here's a C++ implementation I wrote a while ago that iterates in the forward direction, using an array to manage the current state:

                bool MyList::GetNext(int numCombinations)
                {
                if (numCombinations==-1)
                {
                return false;
                }

                int q=list\[numCombinations\];
                ++q;
                
                while (q >= numItems)
                {
                	if (numCombinations==0)
                	{
                		return false;
                	}
                	if (!GetNext(numCombinations-1))
                	{
                		return false;
                	}
                
                	q=list\[numCombinations-1\]+1;
                }
                
                list\[numCombinations\]=q;
                return true;
                

                }

                Use your favorite language to write this. :) (Yeah, I must admit, I'm personally interested in cool C# 3.5 examples) Marc

                Thyme In The Country Interacx My Blog

                G Offline
                G Offline
                Gary Wheeler
                wrote on last edited by
                #14

                C'mon guys. Surely this can be done in a single line of code using LINQ, right? I'm not going to try it. I don't have my license yet, and I wouldn't want anyone to get hurt.

                Software Zen: delete this;

                M 1 Reply Last reply
                0
                • G Gary Wheeler

                  C'mon guys. Surely this can be done in a single line of code using LINQ, right? I'm not going to try it. I don't have my license yet, and I wouldn't want anyone to get hurt.

                  Software Zen: delete this;

                  M Offline
                  M Offline
                  Marc Clifton
                  wrote on last edited by
                  #15

                  Gary Wheeler wrote:

                  C'mon guys. Surely this can be done in a single line of code using LINQ, right?

                  LOL! That's what I was thinking to. But actually not Linq, because it has to yield a return for each iteration. Marc

                  Thyme In The Country Interacx My Blog

                  1 Reply Last reply
                  0
                  • R Roger Alsing 0

                    C#3 list extension method:

                    public static IEnumerable< IList< T >> GetPremutations< T >(this IList< T > items, int columns)
                    {
                    for (int i = 0; i < (int)Math.Pow(items.Count, columns); i++)
                    {
                    IList< T > result = new List< T >();

                        for (int k = 0; k < columns; k++) 
                            result.Add(items\[(i / (int)Math.Pow(items.Count,k) ) % items.Count\]);
                    
                        yield return result;
                    }
                    

                    }

                    This will return a list of the elements for each premutation. (not a list with all premutations, a list for each entry in the premutation set... each entry is yielded by the enumerator) (However, this will crash and burn at large sets due to int overflows)

                    My Blog

                    J Offline
                    J Offline
                    Jordon4Kraftd
                    wrote on last edited by
                    #16

                    RUN!!! It is to early for "Pre-mutations" please stick with "Permutations" ha ha, I love reading something and having mutated creatures being created in a loop.

                    1 Reply Last reply
                    0
                    • M Marc Clifton

                      Let's say you have n combinations of v items, and you want create a sequential string that represents every non-duplicate combination of those v items. So, 3 combinations (3 columns) of 4 items (0 through 3 inclusive) would look like: 0 1 2 0 1 3 0 2 3 1 2 3 and you also want to create the same pattern in reverse: 1 2 3 0 2 3 0 1 3 0 1 2 However, you don't want to create the entire list in memory (because, for example, 8 combinations of 58 items will result in billions of rows). Instead, you want to get each combination sequentially, forward or reverse, as requested, given the last state. Here's a C++ implementation I wrote a while ago that iterates in the forward direction, using an array to manage the current state:

                      bool MyList::GetNext(int numCombinations)
                      {
                      if (numCombinations==-1)
                      {
                      return false;
                      }

                      int q=list\[numCombinations\];
                      ++q;
                      
                      while (q >= numItems)
                      {
                      	if (numCombinations==0)
                      	{
                      		return false;
                      	}
                      	if (!GetNext(numCombinations-1))
                      	{
                      		return false;
                      	}
                      
                      	q=list\[numCombinations-1\]+1;
                      }
                      
                      list\[numCombinations\]=q;
                      return true;
                      

                      }

                      Use your favorite language to write this. :) (Yeah, I must admit, I'm personally interested in cool C# 3.5 examples) Marc

                      Thyme In The Country Interacx My Blog

                      U Offline
                      U Offline
                      User 3935472
                      wrote on last edited by
                      #17

                      Looks like some college student is trying to get the community to get them an A.

                      M 1 Reply Last reply
                      0
                      • U User 3935472

                        Looks like some college student is trying to get the community to get them an A.

                        M Offline
                        M Offline
                        Marc Clifton
                        wrote on last edited by
                        #18

                        Member 3938395 wrote:

                        Looks like some college student is trying to get the community to get them an A.

                        I'm not a college student. I thought it would be an interesting exercise, as it's something I'm dealing with on a project. I particularly find it interesting that no one posted the reverse version. There's two ways of doing it, the easiest is to generate the forward item and subtract the values from the max item count and replace the string in reverse order so that the result is still incremental. Marc

                        Thyme In The Country Interacx My Blog

                        S 1 Reply Last reply
                        0
                        • M Marc Clifton

                          Member 3938395 wrote:

                          Looks like some college student is trying to get the community to get them an A.

                          I'm not a college student. I thought it would be an interesting exercise, as it's something I'm dealing with on a project. I particularly find it interesting that no one posted the reverse version. There's two ways of doing it, the easiest is to generate the forward item and subtract the values from the max item count and replace the string in reverse order so that the result is still incremental. Marc

                          Thyme In The Country Interacx My Blog

                          S Offline
                          S Offline
                          Shao Voon Wong
                          wrote on last edited by
                          #19

                          Is there any reason that you have the forward version and you still need the reverse version of the function? Or is it just purely academically pursue to find the reverse version just for sake of fun?

                          M 1 Reply Last reply
                          0
                          • S Shao Voon Wong

                            Is there any reason that you have the forward version and you still need the reverse version of the function? Or is it just purely academically pursue to find the reverse version just for sake of fun?

                            M Offline
                            M Offline
                            Marc Clifton
                            wrote on last edited by
                            #20

                            CBasicNet wrote:

                            Is there any reason that you have the forward version and you still need the reverse version of the function?

                            In a multicore system, one of the interesting things to do is to create a couple threads, one working through the list forward, the other reverse. Marc

                            Thyme In The Country Interacx My Blog

                            S 1 Reply Last reply
                            0
                            • M Marc Clifton

                              CBasicNet wrote:

                              Is there any reason that you have the forward version and you still need the reverse version of the function?

                              In a multicore system, one of the interesting things to do is to create a couple threads, one working through the list forward, the other reverse. Marc

                              Thyme In The Country Interacx My Blog

                              S Offline
                              S Offline
                              Shao Voon Wong
                              wrote on last edited by
                              #21

                              With a forward version and reverse version, you can only create 2 threads. By using Combinadic[^] , you can create as many threads as accordingly to the number of cores or SMP processors. This article below shows you how to find combinations using Combinadic and arbitrary number of threads. You might be interested to take a look. Combinations in C++, Part 2[^]

                              M 1 Reply Last reply
                              0
                              • S Shao Voon Wong

                                With a forward version and reverse version, you can only create 2 threads. By using Combinadic[^] , you can create as many threads as accordingly to the number of cores or SMP processors. This article below shows you how to find combinations using Combinadic and arbitrary number of threads. You might be interested to take a look. Combinations in C++, Part 2[^]

                                M Offline
                                M Offline
                                Marc Clifton
                                wrote on last edited by
                                #22

                                CBasicNet wrote:

                                With a forward version and reverse version, you can only create 2 threads.

                                Well no. First off, you can partition the forward and reverse pieces. Furthermore, you can have several cores working on the forward iterations and other cores working on the reverse iterations, you just do a lock when a thread is ready to get the next iteration.

                                CBasicNet wrote:

                                By using Combinadic[^]

                                Wow! Thanks for that great link! It also references an MSDN article, which provides an implementation. Geez. I've spent a lot of time debugging my algorithms. If only I'd seen this! Well, thanks again. Tomorrow I'm going to replace my algorithms with the code in either the C# version or your C++ version (my original code is in C++, BTW). Great article, also. I owe you one! Marc

                                Thyme In The Country Interacx My Blog

                                1 Reply Last reply
                                0
                                Reply
                                • Reply as topic
                                Log in to reply
                                • Oldest to Newest
                                • Newest to Oldest
                                • Most Votes


                                • Login

                                • Don't have an account? Register

                                • Login or register to search.
                                • First post
                                  Last post
                                0
                                • Categories
                                • Recent
                                • Tags
                                • Popular
                                • World
                                • Users
                                • Groups