# t2/yary

``````#!/usr/bin/env perl6

use v6;

=NAME t2-code

=AUTHOR Yary Hluchan

=SYNOPSIS
t2-code R<count_to_find>

=begin DESCRIPTION
Shows first N sums of 2 cubes, where N is given on the command line.
This program is a solution to Task 2 of the 2011 Perl6 Code Contest.

It does this by building finite streams, S₁, S₂, S₃... where Sq
represents the sums q³+1³, q³+2³, q³+3³...q³+q³

By consuming the least sum from each stream, and creating a new stream
when consuming the first element of the greatest stream, it creates a
never-decreasing stream of sums.

=end DESCRIPTION

#= Represent a sum of cubes in a human-readable string vs. a numeric result
class sum_of_cubes {
has Int \$computed;

# Rely on the caller to tell us the values
# All we do is return the result in numeric context, and the
# calculation in string context.

method new(:\$computed, :\$q, :\$r) {
self.bless(*,
computed=> \$computed,
readable=> "\$q ** 3 + \$r ** 3"
)
}

# I'd like to use a "blessall" method, submethod BUILD is not handsome
submethod BUILD(:\$!computed, :\$!readable ) { }

method Numeric { \$computed }
}

#= Stream of sums of cubes q³+1³, q³+2³
class sum_of_cubes_stream {
# I would like to implement this as an iterator, but the array is so easy.
# Sorry for thinking in P5 :-/
has Int \$.q;
has @stream_of_sums;

# Took me some time on #perl6 to learn how to initialize both
# public and private attributes, without using named attributes
# in "new". I hope "blessall" becomes reality soon.
submethod BUILD(:\$!q, :@!stream_of_sums) { }

method new(Int \$q) {
self.bless(*,
:q( \$q ),
stream_of_sums => (1..\$q) »**» 3 »+» \$q**3
)
}

#= Have we consumed anything from this stream yet?
method is_fresh { @stream_of_sums == \$.q };

#= Peek at the current sum from this stream- or 0 if empty
method current { @stream_of_sums[0] // 0 };

#= Get the current element and prime for the next one
method consume {
# Here, "r" relies on arguments being evaluated left-to-right
sum_of_cubes.new(
computed=>shift(@stream_of_sums),
:q(\$.q),
:r(\$.q-@stream_of_sums)
)
}

}

# I would like to use this declaration, not yet impletmented.
# sub MAIN(Int \$count_to_find);

sub MAIN(Int \$count_to_find is rw) {
# Initialize streams collection with 1³+1³
my @streams=sum_of_cubes_stream.new(1);

while (\$count_to_find) {
my \$min_sum = @streams.map({.current}).min;
my @result = @streams.grep({.current == \$min_sum}).map: {.consume}
if @result > 1 {
say (+@result[0],@result).join: ' = ';
--\$count_to_find;
}

# Add a new stream if the last stream is not fresh
unless @streams[*-1].is_fresh {
push @streams,sum_of_cubes_stream.new(1 + @streams[*-1].q);
}

# Remove any empty streams from consideration,
# by keeping only streams with a value
@streams=@streams.grep: {.current}
}
}
``````

## Correctness

As far as we were able to test it, this produces the right output.

It also seems to handle the case of more than two ways to write a sum of cubes, even though excessive resource usage prevented us from testing it.

## Consistency

Tabs and spaces are used interchangeably, without any fixed rule, and assuming a `tabstop` of 8.

The actual number of steps indented, even with a `tabstop` of 8, vary between 2 and 7, with no apparent system behind it.

The conditional of the `while` loop has unnecessary parentheses, but not those of the `if` and `unless` blocks.

Sometimes there are spaces between hash keys ans the `=>` operator, sometimes there aren't. Sometimes there are spaces around the assignment operator, sometimes there aren't.

## Clarity of intent

The comments use Unicode characters for great good. In a world where Unicode still isn't the norm, this is to be commended.

## Algorithmic complexity

This is a solution that enqueues all sums of cubes, and thus is rather slow.

## Idiomatic use of Perl 6

There is much to like here. Classes are used, even though giving them names starting with lower-case is not too common. Pod is even used in places, though they actually don't seem intended for a user of the class API, but for the reader of the code.

Perl 6 connoisseurs will recognize a few missed opportunities to write named arguments more succinctly: `computed=> \$computed` could've been simply `:\$computed`, `:q( \$q )` could've been `:\$q`, and `:q(\$.q)` could've been `:\$.q`.

## Brevity

A rather verbose solution.