aboutsummaryrefslogtreecommitdiff
path: root/challenge-054
diff options
context:
space:
mode:
authorMark Anderson <mark@frontrangerunner.com>2020-04-05 12:54:26 -0600
committerMark Anderson <mark@frontrangerunner.com>2020-04-05 12:54:26 -0600
commit9bc966d106e2a9b985d048fcd7c3715ea0891dfb (patch)
treeb302dbd349847db1dce4a66289b94252eb6bbd3b /challenge-054
parent79d617258e8dcf3b5758e8064e744ccffd90af9e (diff)
downloadperlweeklychallenge-club-9bc966d106e2a9b985d048fcd7c3715ea0891dfb.tar.gz
perlweeklychallenge-club-9bc966d106e2a9b985d048fcd7c3715ea0891dfb.tar.bz2
perlweeklychallenge-club-9bc966d106e2a9b985d048fcd7c3715ea0891dfb.zip
some optimizations
Diffstat (limited to 'challenge-054')
-rw-r--r--challenge-054/mark-anderson/raku/ch-1.p64
-rw-r--r--challenge-054/mark-anderson/raku/ch-2.p695
2 files changed, 50 insertions, 49 deletions
diff --git a/challenge-054/mark-anderson/raku/ch-1.p6 b/challenge-054/mark-anderson/raku/ch-1.p6
index 6b753dc2e5..f9ca36bab6 100644
--- a/challenge-054/mark-anderson/raku/ch-1.p6
+++ b/challenge-054/mark-anderson/raku/ch-1.p6
@@ -1,5 +1,5 @@
#!/usr/bin/env raku
-sub MAIN(UInt $length, UInt $which where $length > 0 < $which) {
- say (1..$length).permutations[$which-1];
+sub MAIN(UInt $n where * > 0, UInt $k where * > 0) {
+ say (1..$n).permutations[$k-1];
}
diff --git a/challenge-054/mark-anderson/raku/ch-2.p6 b/challenge-054/mark-anderson/raku/ch-2.p6
index 1dc29513af..6072bd6881 100644
--- a/challenge-054/mark-anderson/raku/ch-2.p6
+++ b/challenge-054/mark-anderson/raku/ch-2.p6
@@ -1,7 +1,7 @@
#!/usr/bin/env raku
# Usage: ch-2.p6
-# Output: The length of the 20 longest Collatz sequences from 1 to 1e6.
+# Output:
# 922524 => 445
# 922525 => 445
@@ -24,66 +24,67 @@
# 626331 => 509
# 837799 => 525
+# I couldn't figure out the built-in memoize so I just did my
+# own caching with the hash.
+
+# YMMV but on my computer...
+
+# The hash brings the runtime from 800 seconds to 160 seconds.
+
+# The exists adverb brings it down to 120 seconds.
+
+# Keeping a current sorted array of the 20 largest items brings it
+# down to 95 seconds. (vs. sorting 1_000_000 items later)
multi sub MAIN {
- my $length;
+ my $t = now;
+
my %seen;
%seen{1} = 1;
- my @collatz;
+ my @collatz = (1 => 1) xx 20;
for (1 .. 1e6) -> $start {
- $length = 0;
- %seen{$start} = collatz($start);
- @collatz.push($start => %seen{$start});
- }
+ my $n = $start;
+ my $length = 0;
- .fmt("%-6s => %s").say
- for @collatz.sort({$^a.value <=> $^b.value}).tail(20);
+ loop {
+ if %seen{$n}:exists {
+ %seen{$start} = %seen{$n} + $length;
- sub collatz($n is copy) {
- if (%seen{$n}) {
- return $length + %seen{$n};
- }
+ if @collatz[0].value <= %seen{$start} {
+ @collatz.shift;
+ @collatz.push($start => %seen{$start});
+ @collatz = @collatz.sort({$^a.value <=> $^b.value});
+ }
+
+ last;
+ }
- if $n %% 2 {
- $n = $n / 2;
+ $n = $n %% 2 ?? $n / 2 !! 3 * $n + 1;
+ $length++;
}
+ }
- else {
- $n = 3 * $n + 1;
- }
-
- $length++;
- collatz($n);
- }
+ .say for @collatz.sort({$^a.value <=> $^b.value}).tail(20);
+
+ say now - $t;
}
# Usage: ch-2.p6 23
-# Output: The length of the Collatz sequence followed by the sequence.
-# 23 -> 70 -> 35 -> 106 -> 53 -> 160 -> 80 -> 40 -> 20 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1
-# length = 16
-
-multi sub MAIN(UInt $num where $num > 0) {
- my @arr = collatz($num);
- say @arr.join(" -> ");
- say "length = {@arr.elems}";
-
- sub collatz($n is copy --> Array) {
- my @collatz;
+# Output:
+# 23 70 35 106 53 160
+# 80 40 20 10 5 16
+# 8 4 2 1
- loop {
- @collatz.push($n);
-
- if ($n == 1) {
- return @collatz;
- }
-
- if $n %% 2 {
- $n = $n / 2;
- }
+# length = 16
+multi sub MAIN(Numeric $n is copy where $n > 0) {
+ my @collatz = ($n);
- else {
- $n = 3 * $n + 1;
- }
- }
+ loop {
+ last if $n == 1;
+ $n = $n %% 2 ?? $n / 2 !! 3 * $n + 1;
+ @collatz.push($n);
}
+
+ .fmt("%-8d").say for @collatz.rotor(6, :partial);
+ say "\nlength = {@collatz.elems}";
}