Code kata: ленивое решето Эратосфена

  • Posted on
  • by

Это не вполне решето, так как является не тестом на простоту, а генератором простых чисел. Но принцип прореживания по каждому новому найденному числу остаётся.

#! /usr/bin/perl
use strict;
use warnings;
use 5.010;

use Test::Most;

sub next_int {
	state $i = 2;
	return $i++;
}

sub lazy_grep(&$) {
	my ($filter, $seq) = @_;

	return sub {
		my $next;
		until ($filter->($next = $seq->())) {};
		return $next;
	};
}

sub do_sieve {
	my $f = shift;

	my $nv = $f->();

	return ($nv, lazy_grep { $_[0] % $nv } $f);
}

sub sieve {
	state $next_f = \&next_int;
	my $n;

	($n, $next_f) = do_sieve($next_f);

	return $n;
}

cmp_deeply([sieve, sieve, sieve, sieve], [2, 3, 5, 7]);
cmp_deeply([sieve, sieve, sieve, sieve], [11, 13, 17, 19]);
cmp_deeply([sieve, sieve, sieve, sieve], [23, 29, 31, 37]);

done_testing;