## DEV Community is a community of 848,284 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Kang-min Liu

Posted on • Updated on

# Raku: Van Eck Sequence Generator

One of the tasks from Perl Weekly Challenge #14.1 is to write a program to produce Van Eck sequence. I knew I've heard of it, and yes, it's from a Numberphile video: Numberphile -- Don't Know (the Van Eck Sequence) and OEIS/A181391.

To describe the Van Eck sequence: The first term is 0, and the following terms are defined to be the number of occurrences of the previous term, subtracted by the term index.

``````a[1] = 0
a[n+1] = 0, if a[n] is absent within a[0..n]
a[n+1] = n - m, Otherwise, where a[m] = a[n] and m < n and m is the largest of such.
``````

By definition, to compute `a[n+1]`, we look backward the entire sequence for `a[n]`.

~laurent_r offered a loop-based solution:

``````use v6;

my @a = 0,;
for ^20 -> \$n {
my \$result = 0;
for reverse ^\$n -> \$m {
\$result = \$n - \$m and last if @a[\$m] == @a[\$n];
# Note: \$m is always smaller than \$n, so \$n - \$m > 0
}
push @a, \$result;
}
say @a;
``````

Given the infinite nature of this sequence, I would like to make an object that represent this infinite sequence and, of course, lazily evaluated. Here's the result:

``````my \$vaneck = Seq.new(
class :: does Iterator {
has %!seen is default(-1);
has Int \$!term = -1;
has Int \$!pos  = 0;
method pull-one {
my \$next = %!seen{\$!term} == -1 ?? 0 !! \$!pos - %!seen{\$!term};
%!seen{\$!term} = \$!pos++;
return \$!term = \$next;
}
}.new()
);
``````

Seq and Iterator are both builtin Types in Raku. `%!seen` is a private variable for recording the position of previous occurrence of numbers.

Here's how you print the beginning 200 terms:

``````\$vaneck[^200].map({ .say });
``````

... or just keep it printing forever:

``````\$vaneck.map({ .say });
``````