# -*- 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 { # Compare heads, and advance the lowest 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 { # Take heads my \$h1 = \$ws1.shift(); my \$h2 = \$ws2.shift(); # Sum of heads 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);