Happy numbers

sub happy (Int $n is copy --> Bool) {
  loop {
      state %seen;
      $n = [+] $n.comb.map: { $_ ** 2 }
      return True  if $n == 1;
      return False if %seen{$n}++;
  }
}

say join ' ', grep(&happy, 1 .. *)[^8];

Output:

1 7 10 13 19 23 28 31

Here's another approach that uses a different set of tricks including lazy lists, gather/take, repeat-until, and the cross metaoperator X.

my @happy = lazy gather for 1..* -> $number {
    my %stopper = 1 => 1;
    my $n = $number;
    repeat until %stopper{$n}++ {
        $n = [+] $n.comb X** 2;
    }
    take $number if $n == 1;
}

say ~@happy[^8];

Output is the same as above.

Here is a version using a subset and an anonymous recursion (we cheat a little bit by using the knowledge that 7 is the second happy number):

subset Happy of Int where sub ($n) {
    $n == 1 ?? True  !!
    $n < 7  ?? False !!
    &?ROUTINE([+] $n.comb »**» 2);
}

say (grep Happy, 1 .. *)[^8];

Again, output is the same as above. It is not clear whether this version returns in finite time for any integer, though.

There's more than one way to do it...