in reply to Faster alternative to Math::Combinatorics

Depending on how many elements you have :)

#!/usr/bin/perl -l # http://perlmonks.org/?node_id=1198509 use strict; use warnings; my @elements = (0, 2, 3); my ($first, $last) = @elements[0, -1]; my %next; @next{@elements} = @elements[1 .. @elements]; for my $count (1,2,3,4,7,8) { print "count=$count"; $_ = $first x $count; 1 while print(join ',', /./g), s/([^$last])($last*)$/ $next{$1} x length $& /e; }

Outputs:

count=1 0 2 3 count=2 0,0 0,2 0,3 2,2 2,3 3,3 count=3 0,0,0 0,0,2 0,0,3 0,2,2 0,2,3 0,3,3 2,2,2 2,2,3 2,3,3 3,3,3 count=4 0,0,0,0 0,0,0,2 0,0,0,3 0,0,2,2 0,0,2,3 0,0,3,3 0,2,2,2 0,2,2,3 0,2,3,3 0,3,3,3 2,2,2,2 2,2,2,3 2,2,3,3 2,3,3,3 3,3,3,3 count=7 0,0,0,0,0,0,0 0,0,0,0,0,0,2 0,0,0,0,0,0,3 0,0,0,0,0,2,2 0,0,0,0,0,2,3 0,0,0,0,0,3,3 0,0,0,0,2,2,2 0,0,0,0,2,2,3 0,0,0,0,2,3,3 0,0,0,0,3,3,3 0,0,0,2,2,2,2 0,0,0,2,2,2,3 0,0,0,2,2,3,3 0,0,0,2,3,3,3 0,0,0,3,3,3,3 0,0,2,2,2,2,2 0,0,2,2,2,2,3 0,0,2,2,2,3,3 0,0,2,2,3,3,3 0,0,2,3,3,3,3 0,0,3,3,3,3,3 0,2,2,2,2,2,2 0,2,2,2,2,2,3 0,2,2,2,2,3,3 0,2,2,2,3,3,3 0,2,2,3,3,3,3 0,2,3,3,3,3,3 0,3,3,3,3,3,3 2,2,2,2,2,2,2 2,2,2,2,2,2,3 2,2,2,2,2,3,3 2,2,2,2,3,3,3 2,2,2,3,3,3,3 2,2,3,3,3,3,3 2,3,3,3,3,3,3 3,3,3,3,3,3,3 count=8 0,0,0,0,0,0,0,0 0,0,0,0,0,0,0,2 0,0,0,0,0,0,0,3 0,0,0,0,0,0,2,2 0,0,0,0,0,0,2,3 0,0,0,0,0,0,3,3 0,0,0,0,0,2,2,2 0,0,0,0,0,2,2,3 0,0,0,0,0,2,3,3 0,0,0,0,0,3,3,3 0,0,0,0,2,2,2,2 0,0,0,0,2,2,2,3 0,0,0,0,2,2,3,3 0,0,0,0,2,3,3,3 0,0,0,0,3,3,3,3 0,0,0,2,2,2,2,2 0,0,0,2,2,2,2,3 0,0,0,2,2,2,3,3 0,0,0,2,2,3,3,3 0,0,0,2,3,3,3,3 0,0,0,3,3,3,3,3 0,0,2,2,2,2,2,2 0,0,2,2,2,2,2,3 0,0,2,2,2,2,3,3 0,0,2,2,2,3,3,3 0,0,2,2,3,3,3,3 0,0,2,3,3,3,3,3 0,0,3,3,3,3,3,3 0,2,2,2,2,2,2,2 0,2,2,2,2,2,2,3 0,2,2,2,2,2,3,3 0,2,2,2,2,3,3,3 0,2,2,2,3,3,3,3 0,2,2,3,3,3,3,3 0,2,3,3,3,3,3,3 0,3,3,3,3,3,3,3 2,2,2,2,2,2,2,2 2,2,2,2,2,2,2,3 2,2,2,2,2,2,3,3 2,2,2,2,2,3,3,3 2,2,2,2,3,3,3,3 2,2,2,3,3,3,3,3 2,2,3,3,3,3,3,3 2,3,3,3,3,3,3,3 3,3,3,3,3,3,3,3 real 0m0.023s user 0m0.018s sys 0m0.009s

Replies are listed 'Best First'.
Re^2: Faster alternative to Math::Combinatorics
by AppleFritter (Vicar) on Sep 01, 2017 at 16:46 UTC

    Depending on how many elements you have :)

    Good question! The number could be arbitrarily high in theory, in practice I doubt the number will leave the two-digit range¹. (In case anyone's wondering, BTW, this is related to multistate cellular automata; w is a neighborhood count, and the list I mentioned is a list of (some) states of the CA in question.)

    I'll have to take a long look at your code to really understand it, but wow, those timings look marvellous. Thank you! If this ends up working out I'll definitely owe you a beer.

    Footnotes:

    1. Edited to add: in fact, since the amount of data generated will increase exponentially with the number of CA states, I think realistically, it won't even leave the single-digit range.

      Here's a version of the same algorithm working on array elements instead of characters. (Messier, isn't it?)

      With 10 elements (states) it takes 1.5 seconds on my machine, but I think most of the time is taken by the printing.

      How many neighbors can you have? (for code testing purposes.)

      #!/usr/bin/perl -l # http://perlmonks.org/?node_id=1198509 use strict; use warnings; my @elements = (0, 2, 3); @elements = 0..9; my ($first, $last) = @elements[0, -1]; my %next; @next{@elements} = @elements[1 .. $#elements]; for my $count (1,2,3,4,7,8) { print "count=$count"; my @set = ($first) x $count; local $, = ','; while(1) { print @set; my $i = $#set; $i-- while $i >= 0 and $set[$i] eq $last; $i < 0 and last; @set[$i .. $#set] = ($next{$set[$i]}) x ( @set - $i); } }

        How many neighbors can you have? (for code testing purposes.)

        A maximum of eight — the size of the range-1 Moore neighborhood, as I'm not currently considering CAs with larger neighborhoods.