aboutsummaryrefslogtreecommitdiff
path: root/challenge-165
diff options
context:
space:
mode:
authordrbaggy <js5@sanger.ac.uk>2022-05-23 10:18:47 +0100
committerdrbaggy <js5@sanger.ac.uk>2022-05-23 10:18:47 +0100
commitc03c8411079c6277c7b1558f9c953d72ef439f4f (patch)
tree48ff682540917d8777260a6787450cda2474218f /challenge-165
parent18e184b6eefa2d76f36b9ae51753f49396af65c5 (diff)
parent3e7c636b7168fa0cae1191abab965af749e167de (diff)
downloadperlweeklychallenge-club-c03c8411079c6277c7b1558f9c953d72ef439f4f.tar.gz
perlweeklychallenge-club-c03c8411079c6277c7b1558f9c953d72ef439f4f.tar.bz2
perlweeklychallenge-club-c03c8411079c6277c7b1558f9c953d72ef439f4f.zip
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'challenge-165')
-rwxr-xr-xchallenge-165/e-choroba/perl/ch-1.pl105
-rwxr-xr-xchallenge-165/e-choroba/perl/ch-2.pl60
-rw-r--r--challenge-165/wambash/raku/ch-1.raku75
-rw-r--r--challenge-165/wambash/raku/ch-2.raku31
4 files changed, 271 insertions, 0 deletions
diff --git a/challenge-165/e-choroba/perl/ch-1.pl b/challenge-165/e-choroba/perl/ch-1.pl
new file mode 100755
index 0000000000..9a22702560
--- /dev/null
+++ b/challenge-165/e-choroba/perl/ch-1.pl
@@ -0,0 +1,105 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+
+use Template;
+
+my $HELP = << '__HELP__';
+Usage: $0 input_file [width height]
+
+Use - for input_file to read standard input.
+Width and height default to 400x300.
+__HELP__
+
+my $TEMPLATE = << '__SVG__';
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg height="[% height %]" width="[% width %]" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+[% IF lines -%]
+ <g id="lines" stroke="#369" stroke-width="4">
+ [%- FOREACH line IN lines %]
+ <line x1="[% line.0 %]" x2="[% line.2 %]" y1="[% line.1 %]" y2="[% line.3 %]" />
+ [%- END %]
+ </g>
+[% END- %]
+[%- IF points -%]
+ <g fill="#f73" id="points">
+ [%- FOREACH point IN points %]
+ <circle cx="[% point.0 %]" cy="[% point.1 %]" r="3" />
+ [%- END %]
+ </g>
+[%- END %]
+</svg>
+__SVG__
+
+my $file = shift;
+if (! defined $file || $file =~ /^(?:-h|--help)$/) {
+ print $HELP;
+ exit ! defined $file
+}
+
+my $width = shift || 400;
+my $height = shift || 300;
+
+my ($min_x, $max_x, $min_y, $max_y);
+my (@points, @lines);
+my $FLOAT = qr/-?(?:[0-9]*(?:\.[0-9]+)?+)/;
+
+my $in;
+if ('-' eq $file) {
+ $in = *STDIN;
+} else {
+ open $in, '<', $file or die "$file: $!";
+}
+
+while (<$in>) {
+ if (/^($FLOAT),($FLOAT),($FLOAT),($FLOAT)$/) {
+ my ($x0, $y0, $x1, $y1) = ($1, $2, $3, $4);
+ push @lines, [$x0, $y0, $x1, $y1];
+ for my $x ($x0, $x1) {
+ $min_x = $x if ! defined $min_x || $x < $min_x;
+ $max_x = $x if ! defined $max_x || $x > $max_x;
+ }
+ for my $y ($y0, $y1) {
+ $min_y = $y if ! defined $min_y || $y < $min_y;
+ $max_y = $y if ! defined $max_y || $y > $max_y;
+ }
+
+ } elsif (/^($FLOAT),($FLOAT)$/) {
+ my ($x, $y) = ($1, $2);
+ push @points, [$x, $y];
+ $min_x = $x if ! defined $min_x || $x < $min_x;
+ $max_x = $x if ! defined $max_x || $x > $max_x;
+ $min_y = $y if ! defined $min_y || $y < $min_y;
+ $max_y = $y if ! defined $max_y || $y > $max_y;
+
+ } else {
+ warn "WARN: Ignoring: $_";
+ }
+}
+
+my $scale_x = ($max_x - $min_x) / $width;
+my $scale_y = ($max_y - $min_y) / $height;
+$_ ||= 1 for $scale_x, $scale_y;
+
+for my $point (@points) {
+ $point->[0] = ($point->[0] - $min_x) / $scale_x;
+ $point->[1] = ($point->[1] - $min_y) / $scale_y;
+}
+for my $line (@lines) {
+ $line->[$_] = ($line->[$_] - $min_x) / $scale_x for 0, 2;
+ $line->[$_] = ($line->[$_] - $min_y) / $scale_y for 1, 3;
+}
+
+my $template = 'Template'->new;
+$template->process(\$TEMPLATE,
+ {height => $height,
+ width => $width,
+ points => \@points,
+ lines => \@lines}
+) or die $template->error;
+
+__DATA__
+53,10
+53,10,23,30
+23,30
diff --git a/challenge-165/e-choroba/perl/ch-2.pl b/challenge-165/e-choroba/perl/ch-2.pl
new file mode 100755
index 0000000000..700420a82c
--- /dev/null
+++ b/challenge-165/e-choroba/perl/ch-2.pl
@@ -0,0 +1,60 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use feature qw{ say };
+
+use ARGV::OrDATA;
+use List::Util qw{ sum };
+
+=head1 Usage
+
+ch-2.pl input_file | ch-1.pl - > out.svg
+
+=cut
+
+my @points;
+while (<>) {
+ push @points, map [split /,/], split;
+}
+
+my ($min_x, $max_x, $min_y, $max_y)
+ = (($points[0][0]) x 2, ($points[0][1]) x 2);
+for my $point (@points[1 .. $#points]) {
+ $min_x = $point->[0] if $point->[0] < $min_x;
+ $min_y = $point->[1] if $point->[1] < $min_y;
+ $max_x = $point->[0] if $point->[0] > $max_x;
+ $max_y = $point->[1] if $point->[1] > $max_y;
+}
+
+my $sum_x = sum(map $_->[0], @points);
+my $sum_y = sum(map $_->[1], @points);
+my $sum_x_square = sum(map $_->[0] * $_->[0], @points);
+my $sum_xy = sum(map $_->[0] * $_->[1], @points);
+
+my $divisor = @points * $sum_x_square - $sum_x * $sum_x;
+my $slope = (@points * $sum_xy - $sum_x * $sum_y)
+ / ($divisor || 1);
+
+my $intercept = ($sum_y - $slope * $sum_x) / @points;
+
+my @line;
+push @line, ($_, $intercept + $_ * $slope) for $min_x, $max_x;
+
+# Vertical.
+if ($line[0] == $line[2] && $line[1] == $line[3]) {
+ $line[1] = $points[0][1];
+ $line[3] = $points[1][1];
+}
+
+{ local $, = ',';
+ say @$_ for @points;
+ say @line;
+}
+
+__DATA__
+333,129 39,189 140,156 292,134 393,52 160,166 362,122 13,193
+341,104 320,113 109,177 203,152 343,100 225,110 23,186 282,102
+284,98 205,133 297,114 292,126 339,112 327,79 253,136 61,169
+128,176 346,72 316,103 124,162 65,181 159,137 212,116 337,86
+215,136 153,137 390,104 100,180 76,188 77,181 69,195 92,186
+275,96 250,147 34,174 213,134 186,129 189,154 361,82 363,89
diff --git a/challenge-165/wambash/raku/ch-1.raku b/challenge-165/wambash/raku/ch-1.raku
new file mode 100644
index 0000000000..5d4409f1ce
--- /dev/null
+++ b/challenge-165/wambash/raku/ch-1.raku
@@ -0,0 +1,75 @@
+#!/usr/bin/env raku
+
+role SVG {
+ method svg () {
+ '<'
+ ~ self.^name.gist.lc
+ ~ ' '
+ ~ self.Capture.hash.sort.map( { .key ~ '=' ~ '"' ~ .value ~ '"' } )
+ ~ ' '
+ ~ '/>'
+ }
+}
+
+class Circle does SVG {
+ has $.cx;
+ has $.cy;
+ has $.r = 2;
+ has $.fill = 'orange';
+}
+
+class Line does SVG {
+ has $.x1;
+ has $.y1;
+ has $.x2;
+ has $.y2;
+ has $.stroke= 'blue';
+ has $.stroke-width = 1;
+}
+
+sub svg ( +@svg, :$height = 400, :$width = 600 ) {
+ sprintf( q:to/END/
+<svg
+version="1.1"
+xmlns="http://www.w3.org/2000/svg"
+xmlns:xlink="http://www.w3.org/1999/xlink"
+height="%d" width="%d"
+>
+END
+, $height, $width)
+ ~ @svg».svg.fmt( "\t%s", "\n" )
+ ~ "\n"
+ ~ '</svg>'
+}
+
+multi to-point-line (+@ ($cx, $cy) ) {
+ Circle.new: :$cx, :$cy
+}
+
+multi to-point-line (+@ ($x1, $y1, $x2, $y2)) {
+ Line.new: :$x1, :$y1, :$x2, :$y2
+}
+
+multi MAIN (Int :$height = 400,Int :$width = 600 ) {
+ words()
+ andthen .map: *.split: ','
+ andthen .map: &to-point-line
+ andthen svg $_, :$height, :$width
+ andthen .say
+}
+
+multi MAIN (Bool :test($)!) {
+ use Test;
+ with to-point-line 23,10 {
+ isa-ok $_, Circle;
+ is (.cx,.cy),(23,10);
+ is .svg, '<circle cx="23" cy="10" fill="orange" r="2" />';
+ }
+ with to-point-line 53,12, 23,10 {
+ isa-ok $_, Line;
+ is (.x1,.y1),(53,12);
+ is (.x2,.y2),(23,10);
+ is .svg, '<line stroke="blue" stroke-width="1" x1="53" x2="23" y1="12" y2="10" />';
+ }
+ done-testing;
+}
diff --git a/challenge-165/wambash/raku/ch-2.raku b/challenge-165/wambash/raku/ch-2.raku
new file mode 100644
index 0000000000..c27bb024ac
--- /dev/null
+++ b/challenge-165/wambash/raku/ch-2.raku
@@ -0,0 +1,31 @@
+#!/usr/bin/env raku
+
+
+
+
+sub line-of-best-fit (+@point) {
+ @point
+ andthen .map: { .[0]²,.[0], .[0],1, .[0] * .[1],.[1]}\
+ andthen [Z,] $_
+ andthen .map: *.sum
+ andthen (.[4]*.[3]-.[5]*.[2]),(.[0]*.[5]-.[1]*.[4]) X/ (.[0]*.[3]-.[1]*.[2])
+}
+
+multi MAIN (Bool :test($)!) {
+ use Test;
+ is line-of-best-fit((0,0),(1,1)),(1,0);
+ is line-of-best-fit((0,0),(1,2)),(2,0);
+ is line-of-best-fit((0,10),(1,20),(1,0)),(0,10);
+ done-testing;
+}
+
+#| echo "333,129 39,189 140,156 292,134 393,52 160,166 362,122 363,89" | raku ch-2.raku -from=0 -to=400 | raku ch-1.raku -height=200 -width=400 > point-line.svg
+multi MAIN (Numeric :$from=0,Numeric :$to=600) {
+ my $points= slurp();
+ say $points;
+ $points.words()
+ andthen .map: *.split: ','
+ andthen line-of-best-fit($_)
+ andthen $from,.[0]*$from+.[1], $to,.[0]*$to+.[1]
+ andthen .join(',').say
+}