# t2/edgar

``````# -*- mode: cperl6; -*-

# 2011 Perl 6 Coding Contest
# Edgar Gonzàlez i Pellicer

use v6;

# A term
class Term {
has \$.value;
has \$.expression;
}

# Sum two terms
sub sum-terms(Term \$t1, Term \$t2) {
# Include lowest term first in the expression
my \$expr = \$t1.value < \$t2.value ??
sprintf('%s + %s', \$t1.expression, \$t2.expression) !!
sprintf('%s + %s', \$t2.expression, \$t1.expression);

# Return the sum
return Term.new(value      => \$t1.value + \$t2.value,
expression => \$expr);
}

# Merge two streams
sub merge(\$s1, \$s2) {
return gather {
# Clone the streams
my \$ws1 = \$s1.clone;
my \$ws2 = \$s2.clone;

# While both remain
while \$ws1 && \$ws2 {
if \$ws1[0].value < \$ws2[0].value {
take \$ws1.shift();
}
else {
take \$ws2.shift();
}
}

# Finish streams
take \$ws1.shift() while \$ws1;
take \$ws2.shift() while \$ws2;
}
}

# Merge the sums of two streams
sub merge-sums(\$s1, \$s2) {
return gather {
# Clone the streams
my \$ws1 = \$s1.clone;
my \$ws2 = \$s2.clone;

# While both remain
while \$ws1 && \$ws2 {
my \$h1 = \$ws1.shift();
my \$h2 = \$ws2.shift();

take sum-terms(\$h1, \$h2);

# Rest of merge-sums
take \$_
for merge(merge(\$ws2.map({ sum-terms(\$h1, \$_) }),
\$ws1.map({ sum-terms(\$_, \$h2) })),
merge-sums(\$ws1, \$ws2));
}
}
}

# Main
multi sub MAIN(Str \$n-str) {
# Cubes
my \$cubes = (1 .. *).map({ Term.new(value      => \$_ ** 3,
expression => sprintf("%d ** 3", \$_)) });

# Merge them
my \$merged = merge-sums(\$cubes, \$cubes);

# How many
my \$n = \$n-str.Int;

# Iterate
my \$prev = \$merged.shift();
while \$n > 0 && \$merged {
# Store the first
my @terms = \$prev;

# Next
my \$next = \$merged.shift();
while \$next.value == \$prev.value {
# Different expression?
@terms.push(\$next) if \$next.expression ne \$prev.expression;

# Next
\$prev = \$next;
\$next = shift(\$merged);
}

# How many?
if @terms > 1 {
say((\$prev.value, @terms>>.expression).join(' = '));
--\$n;
}

# Last
\$prev = \$next;
}
}

# Call main
MAIN(|@*ARGS);
``````

## Correctness

This code finds all sums of cubes.

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 more or less interchangeably, without any fixed rule, and assuming a `tabstop` of 8.

## Clarity of intent

The code is easy to follow, and the comments sometimes clarify but mostly just repeat what the code already says.

## Algorithmic efficiency

The code is one of the slower solutions to task 2, mostly due to enqueuing so many objects that later turn out to be uninteresting.

## Idiomatic use of Perl 6

Elegant use of infinite streams and `gather`/`take`.

## Brevity

The code has a "thin" feel: it's made up of quite a few parts, but each part is simple.