in reply to Odometer pattern iterator (in C). (Updated.)

Hi BrowserUk,

I know you won't like me saying this, but I think that this comment:

It appears to me that the actual output (in the revised OP ...), is “give me all 3-tuples in the domain 0..5 such that none of the values in the tuple are duplicated.” You can construct the bit-sequences from this if you need them.
from your very dear friend sundialsvc4 is actually interesting and relevant and the idea of using a recursive function also makes some sense (although, to tell the truth, I fail to see the relevance of sundialsvc4's subsequent comments on the eight-queens problem).

So, forgetting the bits in your original question and directly searching for all unique N-tuples in a set of M unique elements, I came up with this try:

use strict; use warnings; my $M = 5; my @a = 1..$M; my $N = 3; get_all_tuples ($N, [], @a); sub get_all_tuples { my ($level, $valref, @a) = @_; if ($level <= 1) { print "@$valref $_\n" for @a; } else { while (@a) { my $i = shift @a; push @$valref, $i; get_all_tuples ($level-1, $valref, @a); pop @$valref; } } }
which produces the following output:
$ perl N_among_M.pl 1 2 3 1 2 4 1 2 5 1 3 4 1 3 5 1 4 5 2 3 4 2 3 5 2 4 5 3 4 5
Changing M to 10 and N to 4:
$ perl N_among_M.pl 1 2 3 4 1 2 3 5 1 2 3 6 1 2 3 7 1 2 3 8 1 2 3 9 1 2 3 10 1 2 4 5 ... 5 7 9 10 5 8 9 10 6 7 8 9 6 7 8 10 6 7 9 10 6 8 9 10 7 8 9 10
Removing the printing of the solutions and just storing them in an array, and printing only the array count at the end, and using M = 20 and N = 10, the program completes in just slightly over half a second:
$ time perl N_among_M.pl 167960 real 0m0.524s user 0m0.499s sys 0m0.015s
Computing almost 1.7m solutions in just over half a second is not too bad, it seems to me, but I have no idea on the dimensions of the actual problem you are trying to solve. This solution can easily be ported to C, I think, if performance needs to be higher.

Sorry to come back relatively late on the subject, but this weekend of mine was primarily aimed at filling my tax returns. One of the most boring task each year, I am happy that I could enjoy doing some Perl programming afterwards, this is really more pleasing and more fun.

Replies are listed 'Best First'.
Re^2: Odometer pattern iterator (in C). (Updated.)
by BrowserUk (Patriarch) on May 31, 2015 at 22:03 UTC
    I know you won't like me saying this,

    I have no problem with you saying it; though I somewhat fear what the consequence might be given previous examples.

    this comment: “give me all 3-tuples in the domain 0..5 such that none of the values in the tuple are duplicated.” ... is actually interesting

    So, the question is, where did he steal it from?

    and the idea of using a recursive function also makes some sense (although, to tell the truth, I fail to see the relevance of ... the eight-queens problem

    Exactly. None.

    directly searching for all unique N-tuples in a set of M unique elements, I came up with this

    You came up with a solution.

    His posts are like those "Your Stars" astrology pieces in newspapers; so vague that you can read just about anything into them.

    But your solution bears no resemblance to the "pseudo-code" he posted; and that bears no resemblance to any language I know; nor anything vaguely workable.

    Computing almost 1.7m solutions in just over half a second is not too bad, it seems to me, but I have no idea on the dimensions of the actual problem you are trying to solve. This solution can easily be ported to C, I think, if performance needs to be higher.

    Three thoughts:

    • My current solution (posted and refined by Anonymonk above) is iterative; which generally outstrip recursive solutions.

      (That's why compilers attempt to convert recursion to iteration.)

    • How would you convert that recursive solution into an iterator, as requested in the title and described in the OP?

      It's relatively easy to do in Perl; you just write it to take a callback (code block), but much harder to do in C.

    • How does it do on 32/16?

      Does it find all 601 million solutions? Does it come close to doing so in 5s?


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I'm with torvalds on this
    In the absence of evidence, opinion is indistinguishable from prejudice. Agile (and TDD) debunked
      How does it do on 32/16?

      Does it find all 601 million solutions? Does it come close to doing so in 5s?

      Yes, it finds 601 million solutions, but very very far from 5 sec.
      $ time perl N_among_M.pl 601080390 real 35m14.046s user 35m11.691s sys 0m0.108s
Re^2: Odometer pattern iterator (in C). (Updated.)
by Anonymous Monk on May 31, 2015 at 23:08 UTC

    I think that count is wrong. I compute 184756 for 20/10.

      Yes, right, I made a mistake when removing the printing out of the solutions and just counting the solutions. The result is now:
      $ time perl N_among_M.pl 184756 real 0m0.560s user 0m0.545s sys 0m0.015s
Re^2: Odometer pattern iterator (in C). (Updated.)
by Anonymous Monk on Jun 01, 2015 at 06:20 UTC

    For 20/10 with my C version - http://perlmonks.org/?node_id=1128364

    $ time ./inc_c count 184756 real 0m0.006s user 0m0.003s sys 0m0.000s