aboutsummaryrefslogtreecommitdiff
path: root/challenge-246
diff options
context:
space:
mode:
Diffstat (limited to 'challenge-246')
-rwxr-xr-xchallenge-246/e-choroba/perl/ch-1.pl23
-rwxr-xr-xchallenge-246/e-choroba/perl/ch-2.pl120
-rw-r--r--challenge-246/mark-anderson/raku/ch-1.raku3
-rw-r--r--challenge-246/mark-anderson/raku/ch-2.raku27
-rwxr-xr-xchallenge-246/peter-meszaros/perl/ch-1.pl34
-rwxr-xr-xchallenge-246/peter-meszaros/perl/ch-2.pl76
6 files changed, 283 insertions, 0 deletions
diff --git a/challenge-246/e-choroba/perl/ch-1.pl b/challenge-246/e-choroba/perl/ch-1.pl
new file mode 100755
index 0000000000..2f284d6869
--- /dev/null
+++ b/challenge-246/e-choroba/perl/ch-1.pl
@@ -0,0 +1,23 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use experimental qw( signatures );
+
+use List::Util qw{ shuffle uniq };
+
+sub six_out_of_49() {
+ (shuffle(1 .. 49))[0 .. 5]
+}
+
+use constant TIMES => 100;
+use Test::More tests => TIMES * (2 + 2 * 6);
+
+for (1 .. TIMES) {
+ my @so49 = six_out_of_49();
+ for my $s (@so49) {
+ cmp_ok $s, '<=', 50, 'upper bound';
+ cmp_ok $s, '>=', 1, 'lower bound';
+ }
+ is scalar @so49, 6;
+ is uniq(@so49), @so49, 'unique';
+}
diff --git a/challenge-246/e-choroba/perl/ch-2.pl b/challenge-246/e-choroba/perl/ch-2.pl
new file mode 100755
index 0000000000..a78902bd6c
--- /dev/null
+++ b/challenge-246/e-choroba/perl/ch-2.pl
@@ -0,0 +1,120 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use feature qw{ say };
+use experimental qw( signatures );
+
+sub linear_recurrence_of_2nd_order(@a) {
+ my ($p, $q);
+ if (0 == $a[0]) {
+ return [0, 0] if @a == grep 0 == $_, @a;
+ return if 0 == $a[1];
+
+ $q = $a[2] / $a[1];
+ return unless $q == int $q;
+
+ $p = ($a[1] * $a[3] - $a[2] ** 2) / $a[1] ** 2;
+
+ } elsif ($a[1] ** 2 == $a[0] * $a[2]) {
+ return unless $a[1] * $a[2] == $a[0] * $a[3];
+
+ if (0 == $a[1]) {
+ return unless 3 == grep 0 == $_, @a[2 .. 4];
+ return [0, 0]
+ }
+
+ if ($a[2] ** 2 == $a[0] * $a[1] * $a[3]) {
+ return unless $a[4] == $a[1] * $a[3];
+ return [$a[1] + $a[2], -1]
+ }
+
+ $q = ($a[0] * $a[1] * $a[4] - $a[1] * $a[2] ** 2)
+ / ($a[0] * $a[1] * $a[3] - $a[2] ** 2);
+ return unless $q == int $q;
+
+
+ $p = ($a[1] * $a[2] - $q * $a[0] * $a[2]) / ($a[0] * $a[1]);
+ } else {
+ $q = ($a[1] * $a[2] - $a[0] * $a[3]) / ($a[1] ** 2 - $a[0] * $a[2]);
+ return unless $q == int $q;
+
+ $p = ($a[2] - $q * $a[1]) / $a[0];
+ }
+ return unless $p == int $p;
+
+ return unless $a[4] == $p * $a[2] + $q * $a[3];
+
+ return [$p, $q]
+}
+
+use Test::More tests => 3 + 1 + 10;
+
+ok linear_recurrence_of_2nd_order(1, 1, 2, 3, 5), 'Example 1';
+ok ! linear_recurrence_of_2nd_order(4, 2, 4, 5, 7), 'Example 2';
+ok linear_recurrence_of_2nd_order(4, 1, 2, -3, 8), 'Example 3';
+
+# p = 0, a[0] is irrelevant.
+ok linear_recurrence_of_2nd_order(qw( 15 1 16 256 4096 ));
+
+ok linear_recurrence_of_2nd_order(qw( 2 4 8 16 32 ));
+ok linear_recurrence_of_2nd_order(qw( -13 1 0 1 13 ));
+ok linear_recurrence_of_2nd_order(qw( -12 11 -10 8 8 ));
+ok linear_recurrence_of_2nd_order(qw( 1 -2 4 -8 16));
+ok linear_recurrence_of_2nd_order(qw( 1 -1 1 -1 1 ));
+ok linear_recurrence_of_2nd_order(qw( 3 5 8 16 0 ));
+ok ! linear_recurrence_of_2nd_order(qw( 3 0 0 6 6 ));
+ok ! linear_recurrence_of_2nd_order(qw( 0 -4 0 5 0 ));
+ok ! linear_recurrence_of_2nd_order(qw( 0 8 8 6 4 ));
+ok ! linear_recurrence_of_2nd_order(qw( 1 -1 1 -1 7 ));
+
+#
+# Extended testing.
+#
+# Hash all the possible sentences generated from p, q, a0, a1 in -20 .. 20.
+# Then generate random sentences and verify that they're recognised correctly.
+# This was great for debugging the edge cases.
+
+sub generate($p, $q, $a0, $a1) {
+ my @a = ($a0, $a1);
+ $a[$_] = $p * $a[$_ - 2] + $q * $a[$_ - 1] for 2, 3, 4;
+ return @a
+}
+
+my %generated;
+my %i;
+for my $p (-20 .. 20) {
+ for my $q (-20 .. 20) {
+ for my $a0 (-20 .. 20) {
+ for my $a1 (-20 .. 20) {
+ my @a = generate($p, $q, $a0, $a1);
+ next if grep 1000 < abs, @a;
+
+ $generated{"@a"} = "$p $q";
+ }
+ }
+ }
+}
+
+my $c = 0;
+my @a;
+local $SIG{__DIE__} = sub { warn "\t@a"; exit 1 };
+while (++$c < 1e7) {
+ @a = map -19 + int rand 38, 0 .. 4;
+ print "$c: @a \r";
+ if (exists $generated{"@a"}) {
+ my $pq = linear_recurrence_of_2nd_order(@a);
+ die "not ok @a (" . $generated{"@a"} . ')' unless $pq;
+ my @b = generate(@$pq, @a[0, 1]);
+ die "generated @a != @b (@$pq)" unless "@a" eq "@b";
+ } else {
+ my $pq = linear_recurrence_of_2nd_order(@a);
+ if ($pq) {
+ if (grep abs > 20, @$pq) {
+ my @b = generate(@$pq, @a[0, 1]);
+ die "!gen @a != @b (@$pq)" unless "@a" eq "@b";
+ } else {
+ die "not ok ! @a (@$pq)";
+ }
+ }
+ }
+}
diff --git a/challenge-246/mark-anderson/raku/ch-1.raku b/challenge-246/mark-anderson/raku/ch-1.raku
new file mode 100644
index 0000000000..757c3fe00d
--- /dev/null
+++ b/challenge-246/mark-anderson/raku/ch-1.raku
@@ -0,0 +1,3 @@
+#!/usr/bin/env raku
+
+.say for (1..49).pick(6).sort;
diff --git a/challenge-246/mark-anderson/raku/ch-2.raku b/challenge-246/mark-anderson/raku/ch-2.raku
new file mode 100644
index 0000000000..d162ab93d3
--- /dev/null
+++ b/challenge-246/mark-anderson/raku/ch-2.raku
@@ -0,0 +1,27 @@
+#!/usr/bin/env raku
+use Math::Matrix;
+use Test;
+
+# Disclaimer: This might be totally wrong but it seems right.
+
+ok task2(1,1,2,3,5);
+nok task2(4,2,4,5,7);
+ok task2(4,1,2,-3,8);
+
+sub task2(*@a)
+{
+ my @equations = @a.rotor(3 => -2);
+
+ my ($p1,$q1) = p-and-q(@equations[0], @equations[1]);
+ my ($p2,$q2) = p-and-q(@equations[1], @equations[2]);
+
+ return False unless ($p1,$q1,$p2,$q2)>>.narrow.all ~~ Int;
+ return ($p1,$q1) eqv ($p2,$q2)
+}
+
+sub p-and-q(@a, @b)
+{
+ my $A = Math::Matrix.new([[@a.head(2), @b.head(2)]]);
+ my $B = Math::Matrix.new([[@a.tail], [@b.tail]]);
+ |$A.inverted.dot-product($B)
+}
diff --git a/challenge-246/peter-meszaros/perl/ch-1.pl b/challenge-246/peter-meszaros/perl/ch-1.pl
new file mode 100755
index 0000000000..21d1ae0286
--- /dev/null
+++ b/challenge-246/peter-meszaros/perl/ch-1.pl
@@ -0,0 +1,34 @@
+#!/usr/bin/env perl
+#
+# 6 out of 49 is a German lottery.
+#
+# Write a script that outputs six unique random integers from the range 1 to 49.
+# Output
+#
+# 3
+# 10
+# 11
+# 22
+# 38
+# 49
+
+use strict;
+use warnings;
+
+sub six_outof_fortynine
+{
+ my %h;
+
+ while (keys %h < 6) {
+ $h{int(rand(48))+1}++;
+ }
+ return sort {$a <=> $b} keys %h;
+}
+
+for my $i (1..10) {
+ printf "%2d %s\n", $i, join('-', map { sprintf("%2d", $_) } six_outof_fortynine());
+}
+
+exit 0;
+
+
diff --git a/challenge-246/peter-meszaros/perl/ch-2.pl b/challenge-246/peter-meszaros/perl/ch-2.pl
new file mode 100755
index 0000000000..ac3a0218cc
--- /dev/null
+++ b/challenge-246/peter-meszaros/perl/ch-2.pl
@@ -0,0 +1,76 @@
+#!/usr/bin/env perl
+#
+# You are given an array @a of five integers.
+#
+# Write a script to decide whether the given integers form a linear recurrence
+# of second order with integer factors.
+#
+# A linear recurrence of second order has the form
+#
+# a[n] = p * a[n-2] + q * a[n-1] with n > 1
+#
+# where p and q must be integers.
+#
+# Example 1
+#
+# Input: @a = (1, 1, 2, 3, 5)
+# Output: true
+#
+# @a is the initial part of the Fibonacci sequence a[n] = a[n-2] + a[n-1]
+# with a[0] = 1 and a[1] = 1.
+#
+# Example 2
+#
+# Input: @a = (4, 2, 4, 5, 7)
+# Output: false
+#
+# a[1] and a[2] are even. Any linear combination of two even numbers with
+# integer factors is even, too. Because a[3] is odd, the given numbers cannot
+# form a linear recurrence of second order with integer factors.
+#
+# Example 3
+#
+# Input: @a = (4, 1, 2, -3, 8)
+# Output: true
+#
+# a[n] = a[n-2] - 2 * a[n-1]
+#
+
+use strict;
+use warnings;
+use Test::More;
+use Data::Dumper;
+
+my $cases = [
+ [1, 1, 2, 3, 5],
+ [4, 2, 4, 5, 7],
+ [4, 1, 2, -3, 8],
+];
+
+# a[2] = p * a[0] + q * a[1]
+# a[3] = p * a[1] + q * a[2]
+# a[4] = p * a[2] + q * a[3]
+# --------------------------
+# p = (a[2] - q * a[1]) / a[0]
+# q = (a[3] * a[0] - a[2] * a[1]) / (a[2] * a[0] - a[1] * a[1])
+# r = p * a[2] + q + a[3]
+# if p is int and q is int and r == a[4] then true else false
+sub linreq_of_second_order
+{
+ my $l = shift;
+
+ my $q = ($l->[3]*$l->[0] - $l->[2]*$l->[1]) /
+ ($l->[2]*$l->[0] - $l->[1]*$l->[1]);
+ my $p = ($l->[2] - $q*$l->[1]) / $l->[0];
+
+ my $r = $p*$l->[2] + $q*$l->[3];
+
+ return ($p == int($p) && $q == int($q) && $l->[4] == $r) ? 1 : 0;
+}
+
+is(linreq_of_second_order($cases->[0]), 1, '[1, 1, 2, 3, 5]');
+is(linreq_of_second_order($cases->[1]), 0, '[4, 2, 4, 5, 7]');
+is(linreq_of_second_order($cases->[2]), 1, '[4, 1, 2, -3, 8]');
+done_testing();
+
+exit 0;