diff options
| author | Mohammad S Anwar <Mohammad.Anwar@yahoo.com> | 2022-11-20 21:22:29 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-11-20 21:22:29 +0000 |
| commit | 20a01f1b0e883b0cc1e428fe1d631a9b9845783e (patch) | |
| tree | 585959ccb15d87621f712919f839ffd1150e2677 | |
| parent | bde0adaf7b8dfe99c4e494c932d8702eb8cf9a56 (diff) | |
| parent | 3b33fea6b629ea70479ed7188a86987cfa6d7b1e (diff) | |
| download | perlweeklychallenge-club-20a01f1b0e883b0cc1e428fe1d631a9b9845783e.tar.gz perlweeklychallenge-club-20a01f1b0e883b0cc1e428fe1d631a9b9845783e.tar.bz2 perlweeklychallenge-club-20a01f1b0e883b0cc1e428fe1d631a9b9845783e.zip | |
Merge pull request #7107 from wlmb/challenges
Add fastest nested iterator solution
| -rwxr-xr-x | challenge-191/wlmb/perl/ch-2d.pl | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/challenge-191/wlmb/perl/ch-2d.pl b/challenge-191/wlmb/perl/ch-2d.pl new file mode 100755 index 0000000000..640ed3cc59 --- /dev/null +++ b/challenge-191/wlmb/perl/ch-2d.pl @@ -0,0 +1,55 @@ +#!/usr/bin/env perl +# Perl weekly challenge 191 +# Task 2: Cute List. Nested iterators. +# +# See https://wlmb.github.io/2022/11/14/PWC191/#task-2-cute-list +use v5.36; +use List::Util qw(all reduce); + +sub listit(@set){ # iterator that returns the elements of a set + sub { return shift @set } +} + +sub cute($n){ # return an iterator to generate all cute sequences of length $n + my @sets; + for my $position(0..$n-1){ + for(1..$n){ # Build sets of divisors and multiples of $position+1 + push @{$sets[$position]}, $_ if ($position+1)%$_==0 || $_%($position+1)==0; + } + } + my $aux; + $aux = # closure for an ancilliary iterator constructor + sub ($pos) { # Returns an iterator for position $pos + #The iterator returns a cute subsecuence and a hash of seen values + # Return a trivial iterator if beyond end + return # trivial iterator beyond position + sub { state $n=0; return $n++? ():([],{})} if $pos >=@sets; + my @set=@{$sets[$pos]}; + my $it=$aux->($pos+1); # Iterator for next position + my $candidates=listit(@set); # iterator for candidates + my ($cute, $seen)=$it->(); # initial cute subsequence + sub { + while(1){ + while(my $candidate=$candidates->()){ + return([$candidate, @$cute], {$candidate, 1, %$seen}) + unless $seen->{$candidate}; + } + ($cute, $seen)=$it->() or return (); # next subsequence or return + $candidates=listit(@set); # reinitalize iterator for candidates + } + } + }; + $aux->(0); # return iterator for full sequence +} + +die << "EOF" unless @ARGV; +Usage: $0 N1 [N2...] +to count the cute orderings of 1..Ni +EOF +warn "Numbers beyond 20 will require patience" unless all {1<=$_<=20} @ARGV; +for(@ARGV){ + my $count=0; + my $it=cute($_); + ++$count while $it->(); # count cute sequences + say "$_-> $count"; # report +} |
