aboutsummaryrefslogtreecommitdiff
path: root/challenge-155/jo-37/perl/ch-1.pl
blob: ad2c14239224e862e3187096dc7591da77432f17 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#!/usr/bin/perl -s

use v5.16;
use Test2::V0;
use bigint;
use Math::Prime::Util qw(next_prime is_prime);
use Coro::Generator;

our ($tests, $examples);

run_tests() if $tests || $examples;	# does not return

die <<EOS unless @ARGV;
usage: $0 [-examples] [-tests] [N]

-examples
    run the examples from the challenge
 
-tests
    run some tests

N
    Print the first N distinct fortunate numbers in ascending order.

EOS


### Input and Output

main: {
    my $fn = gen_fortunate_numbers();
    my %fn;
    # Collect the first N distinct fortunate numbers.
    until (keys %fn == $ARGV[0]) {
        $fn{$fn->()} = undef;
    }
    # Present in ascending order.
    say for sort {$a <=> $b} keys %fn;
}


### Implementation

# Build a generator for fortunate numbers.  The resulting sequence is
# neither sorted nor does it consist of distinct values only.
sub gen_fortunate_numbers {
    my $pn = 1;
    my $p = 1;

    generator {
        while () {
            $pn *= ($p = next_prime($p));
            for (my $m = 2;; $m++) {
                yield($m), last if is_prime($pn + $m);
            }
        }
    }
}


### Examples and tests

sub run_tests {
    SKIP: {
        skip "examples" unless $examples;

        my $fn = gen_fortunate_numbers();
        is [map $fn->(), 1 .. 9], [3, 5, 7, 13, 23, 17, 19, 23, 37],
            'the raw sequence: neither sorted nor distinct'
    }

    SKIP: {
        skip "tests" unless $tests;

        my $fn = gen_fortunate_numbers();
        $fn->() for 1 .. 57;
        is $fn->(), 331, '#58 according to OEIS';
	}

    done_testing;
    exit;
}