Skip to content

Commit 648b159

Browse files
author
L. Grondin
committed
Merge branch 'master' of github.com:perl6/perl6-examples
2 parents 2b09646 + 3036039 commit 648b159

File tree

1 file changed

+153
-0
lines changed

1 file changed

+153
-0
lines changed

euler/prob149-shlomif.pl

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
use v6;
2+
3+
=begin pod
4+
5+
=head1 DESCRIPTION
6+
7+
Looking at the table below, it is easy to verify that the maximum possible sum
8+
of adjacent numbers in any direction (horizontal, vertical, diagonal or
9+
anti-diagonal) is 16 (= 8 + 7 + 1). −253 2 9−651 3273 −18−4 8
10+
11+
Now, let us repeat the search, b ut on a
12+
much larger scale:
13+
14+
First, generate four million pseudo-random numbers using a specific form of
15+
what is known as a "Lagged Fibonacci Generator":
16+
17+
For 1 ≤ k ≤ 55, sk = [100003 − 200003k + 300007k3] (modulo 1000000) − 500000.
18+
For 56 ≤ k ≤ 4000000, sk = [sk−24 + sk−55 + 1000000] (modulo 1000000) − 500000.
19+
20+
Thus, s10 = −393027 and s100 = 86613.
21+
22+
The terms of s are then arranged in a 2000×2000 table, using the first 2000
23+
numbers to fill the first row (sequentially), the next 2000 numbers to fill the
24+
second row, and so on.
25+
26+
Finally, find the greatest sum of (any number of) adjacent entries in any
27+
direction (horizontal, vertical, diagonal or anti-diagonal).
28+
29+
=end pod
30+
31+
# use integer;
32+
33+
# use Math::BigInt "lib" => "GMP";
34+
35+
class FiboRand {
36+
has $.k is rw = 1;
37+
has @.last_nums is rw;
38+
39+
method fetch() {
40+
my $k = $.k;
41+
my $s_k;
42+
43+
if ($k <= 55)
44+
{
45+
$s_k = (((100003 - 200003*$k + 300007*($k**3)) % 1000000) - 500000);
46+
}
47+
else
48+
{
49+
$s_k = (((@.last_nums[*-24] + @.last_nums[*-55] + 1000000) % 1000000) - 500000);
50+
shift(@.last_nums);
51+
}
52+
push @.last_nums, $s_k;
53+
$.k++;
54+
55+
return $s_k;
56+
}
57+
}
58+
59+
# Unit test to the randomizer.
60+
{
61+
my $rand = FiboRand.new;
62+
63+
for 1 .. 9 -> $k
64+
{
65+
$rand.fetch();
66+
}
67+
68+
if ($rand.fetch() != -393027)
69+
{
70+
die "Wrong s10!";
71+
}
72+
73+
for 11 .. 99 -> $k
74+
{
75+
$rand.fetch();
76+
}
77+
78+
if ($rand.fetch() != 86613)
79+
{
80+
die "Wrong s100!";
81+
}
82+
}
83+
84+
class Max
85+
{
86+
has $.s is rw = 0;
87+
has $.e is rw = 0;
88+
method add($n)
89+
{
90+
$.s = max($.s, ($.e = max($.e + $n, 0)));
91+
92+
return;
93+
}
94+
95+
# g = get()
96+
method g()
97+
{
98+
return $.s;
99+
}
100+
}
101+
102+
my $rand = FiboRand.new;
103+
104+
my $SIZE = 2_000;
105+
106+
my $max_max = 0;
107+
my @vert_max = map { Max.new }, (1 .. $SIZE);
108+
my @diag_max = map { Max.new }, (1 .. $SIZE);
109+
my @anti_diag_max = map { Max.new }, (1 .. $SIZE);
110+
111+
my $diag_offset = 0;
112+
my $anti_diag_offset = 0;
113+
114+
sub handle_row()
115+
{
116+
my $horiz = Max.new;
117+
# First row.
118+
for 0 .. $SIZE-1 -> $x
119+
{
120+
my $s = $rand.fetch();
121+
122+
@vert_max[$x].add($s);
123+
$horiz.add($s);
124+
@diag_max[($x+$diag_offset) % $SIZE].add($s);
125+
@anti_diag_max[($x+$anti_diag_offset) % $SIZE].add($s);
126+
}
127+
128+
$max_max = max(
129+
$max_max, $horiz.g(), @diag_max[0].g(), @anti_diag_max[*-1].g()
130+
);
131+
132+
@diag_max[0] = Max.new;
133+
$diag_offset++;
134+
135+
@anti_diag_max[*-1] = Max.new;
136+
$anti_diag_offset--;
137+
138+
return;
139+
}
140+
141+
for 1 .. $SIZE -> $y
142+
{
143+
print "Y=$y\n";
144+
handle_row();
145+
}
146+
147+
148+
print "Result = ", max(
149+
$max_max, (map { $_.g() }, @vert_max, @diag_max, @anti_diag_max
150+
)
151+
), "\n";
152+
153+
# vim: ft=perl6

0 commit comments

Comments
 (0)