diff options
| author | drbaggy <js5@sanger.ac.uk> | 2021-12-14 16:45:42 +0000 |
|---|---|---|
| committer | drbaggy <js5@sanger.ac.uk> | 2021-12-14 16:45:42 +0000 |
| commit | ec5f0be67d3191dac4cd1cbac0cd46142caf9d50 (patch) | |
| tree | a0ea02a07c4b65936deb4e1361499893af0d5f2a | |
| parent | 83bbf539df77c2f4bb734d248fa13ae89e47dcf9 (diff) | |
| parent | 6cf0f1d6a11fc23b2fbf66c4ceee99cd75c21f16 (diff) | |
| download | perlweeklychallenge-club-ec5f0be67d3191dac4cd1cbac0cd46142caf9d50.tar.gz perlweeklychallenge-club-ec5f0be67d3191dac4cd1cbac0cd46142caf9d50.tar.bz2 perlweeklychallenge-club-ec5f0be67d3191dac4cd1cbac0cd46142caf9d50.zip | |
Merge remote-tracking branch 'upstream/master'
46 files changed, 2345 insertions, 1515 deletions
diff --git a/challenge-027/paulo-custodio/Makefile b/challenge-027/paulo-custodio/Makefile new file mode 100644 index 0000000000..c3c762d746 --- /dev/null +++ b/challenge-027/paulo-custodio/Makefile @@ -0,0 +1,2 @@ +all: + perl ../../challenge-001/paulo-custodio/test.pl diff --git a/challenge-027/paulo-custodio/README b/challenge-027/paulo-custodio/README new file mode 100644 index 0000000000..87dc0b2fbd --- /dev/null +++ b/challenge-027/paulo-custodio/README @@ -0,0 +1 @@ +Solution by Paulo Custodio diff --git a/challenge-027/paulo-custodio/perl/ch-1.pl b/challenge-027/paulo-custodio/perl/ch-1.pl new file mode 100644 index 0000000000..e4b4feca3e --- /dev/null +++ b/challenge-027/paulo-custodio/perl/ch-1.pl @@ -0,0 +1,23 @@ +#!/usr/bin/perl + +# Challenge 027 +# +# Task #1 +# Write a script to find the intersection of two straight lines. The +# co-ordinates of the two lines should be provided as command line parameter. +# For example: +# +# The two ends of Line 1 are represented as co-ordinates (a,b) and (c,d). +# +# The two ends of Line 2 are represented as co-ordinates (p,q) and (r,s). +# +# The script should print the co-ordinates of point of intersection of the +# above two lines. + +use Modern::Perl; + +my($x1,$y1,$x2,$y2,$x3,$y3,$x4,$y4) = @ARGV; +my $D = ($x1-$x2)*($y3-$y4)-($y1-$y2)*($x3-$x4); +my $x = (($x1*$y2-$y1*$x2)*($x3-$x4)-($x1-$x2)*($x3*$y4-$y3*$x4))/$D; +my $y = (($x1*$y2-$y1*$x2)*($y3-$y4)-($y1-$y2)*($x3*$y4-$y3*$x4))/$D; +say sprintf("%.1f %.1f", $x, $y); diff --git a/challenge-027/paulo-custodio/perl/ch-2.pl b/challenge-027/paulo-custodio/perl/ch-2.pl new file mode 100644 index 0000000000..8091076b58 --- /dev/null +++ b/challenge-027/paulo-custodio/perl/ch-2.pl @@ -0,0 +1,38 @@ +#!/usr/bin/perl + +# Challenge 027 +# +# Task #2 +# Write a script that allows you to capture/display historical data. It could +# be an object or a scalar. For example +# +# my $x = 10; $x = 20; $x -= 5; +# +# After the above operations, it should list $x historical value in order. + +use Modern::Perl; + +{ + package LoggingScalar; + sub TIESCALAR { + my($class, $value) = @_; + return bless [$value], $class; + } + sub FETCH { + my($self) = @_; + return $self->[-1]; + } + sub STORE { + my($self, $value) = @_; + push @$self, $value; + } + sub show_hist { + my($self) = @_; + say join(" ", @$self); + } +} + +tie my $x, 'LoggingScalar', 10; +$x = 20; +$x -= 5; +tied($x)->show_hist(); diff --git a/challenge-027/paulo-custodio/python/ch-1.py b/challenge-027/paulo-custodio/python/ch-1.py new file mode 100644 index 0000000000..8f3e6c9731 --- /dev/null +++ b/challenge-027/paulo-custodio/python/ch-1.py @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +# Challenge 027 +# +# Task #1 +# Write a script to find the intersection of two straight lines. The +# co-ordinates of the two lines should be provided as command line parameter. +# For example: +# +# The two ends of Line 1 are represented as co-ordinates (a,b) and (c,d). +# +# The two ends of Line 2 are represented as co-ordinates (p,q) and (r,s). +# +# The script should print the co-ordinates of point of intersection of the +# above two lines. + +import sys + +x1,y1,x2,y2,x3,y3,x4,y4 = [int(x) for x in sys.argv[1:9]] +D = (x1-x2)*(y3-y4)-(y1-y2)*(x3-x4) +x = ((x1*y2-y1*x2)*(x3-x4)-(x1-x2)*(x3*y4-y3*x4))/D +y = ((x1*y2-y1*x2)*(y3-y4)-(y1-y2)*(x3*y4-y3*x4))/D +print("{:.1f} {:.1f}".format(x, y)) diff --git a/challenge-027/paulo-custodio/python/ch-2.py b/challenge-027/paulo-custodio/python/ch-2.py new file mode 100644 index 0000000000..99fd57554b --- /dev/null +++ b/challenge-027/paulo-custodio/python/ch-2.py @@ -0,0 +1,26 @@ +#!/usr/bin/python3 + +# Challenge 027 +# +# Task #2 +# Write a script that allows you to capture/display historical data. It could +# be an object or a scalar. For example +# +# my $x = 10; $x = 20; $x -= 5; +# +# After the above operations, it should list $x historical value in order. + +class LoggingScalar: + def __init__(self, value): + self.values = [value] + def set(self, value): + self.values.append(value) + def get(self): + return self.values[-1] + def show_hist(self): + print(" ".join([str(x) for x in self.values])) + +x = LoggingScalar(10) +x.set(20) +x.set(x.get()-5) +x.show_hist() diff --git a/challenge-027/paulo-custodio/t/test-1.yaml b/challenge-027/paulo-custodio/t/test-1.yaml new file mode 100644 index 0000000000..31ebb25d9b --- /dev/null +++ b/challenge-027/paulo-custodio/t/test-1.yaml @@ -0,0 +1,5 @@ +- setup: + cleanup: + args: 15 10 49 25 29 5 32 32 + input: + output: 30.3 16.8 diff --git a/challenge-027/paulo-custodio/t/test-2.yaml b/challenge-027/paulo-custodio/t/test-2.yaml new file mode 100644 index 0000000000..78447f751a --- /dev/null +++ b/challenge-027/paulo-custodio/t/test-2.yaml @@ -0,0 +1,5 @@ +- setup: + cleanup: + args: + input: + output: 10 20 15 diff --git a/challenge-143/alexander-pankoff/perl/ch-1.pl b/challenge-143/alexander-pankoff/perl/ch-1.pl new file mode 100755 index 0000000000..fcb9c8edbc --- /dev/null +++ b/challenge-143/alexander-pankoff/perl/ch-1.pl @@ -0,0 +1,7 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +my $expr = $ARGV[0]; +die "invalid expr\n" unless $expr && $expr =~ m/^[\s\d\.\+\-\*\(\)]*$/; +print eval($expr) . "\n"; diff --git a/challenge-143/alexander-pankoff/perl/ch-2.pl b/challenge-143/alexander-pankoff/perl/ch-2.pl new file mode 100755 index 0000000000..a952866cde --- /dev/null +++ b/challenge-143/alexander-pankoff/perl/ch-2.pl @@ -0,0 +1,61 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use feature qw'say signatures'; +no warnings qw'experimental::signatures'; + +use List::Util qw'first'; + +use constant DEBUG => $ENV{DEBUG} // 0; + +run() unless caller(); + +sub run() { + my $stealthy = stealthy( $ARGV[0] ); + say $stealthy ? 1 : 0; + explain($stealthy) if DEBUG; +} + +sub stealthy($n) { + my @divisors = find_divisors_pairs($n); + my @pairs = pairs(@divisors); + + my $stealthy = first { + my ( $a, $b, $c, $d ) = flatten($_); + $a * $b == $c * $d && $a + $b == $c + $d + 1; + } + @pairs; + + return $stealthy; +} + +sub explain($stealthy) { + say "Not stealthy" && return if !$stealthy; + my ( $a, $b, $c, $d ) = flatten($stealthy); + say +"Since $a (a) * $b (b) = $c (c) * $d (d) and $a (a) + $b (b) = $c (c) + $d (d) + 1"; +} + +sub pairs(@xs) { + my @out; + for my $i ( 0 .. $#xs - 1 ) { + push @out, map { [ $xs[$i], $xs[$_] ] } ( $i + 1 .. $#xs ); + } + return @out; +} + +sub flatten($xs) { + map { @$_ } @$xs; +} + +sub find_divisors_pairs($x) { + my @out; + my $max = sqrt($x); + for my $i ( 1 .. $max ) { + if ( $x % $i == 0 ) { + push @out, [ $i, $x / $i ]; + } + } + + return @out; +} diff --git a/challenge-143/conor-hoekstra/apl/ch-1.apl b/challenge-143/conor-hoekstra/apl/ch-1.apl new file mode 100644 index 0000000000..ec5e3506f0 --- /dev/null +++ b/challenge-143/conor-hoekstra/apl/ch-1.apl @@ -0,0 +1,5 @@ +solution ← ⍎'×'@('*'∘=) + +⍝ Tests +solution '10 + 20 - 5' ⍝ 25 +solution '(10 + 20 - 5) * 2' ⍝ 50 diff --git a/challenge-143/conor-hoekstra/apl/ch-2.apl b/challenge-143/conor-hoekstra/apl/ch-2.apl new file mode 100644 index 0000000000..2c5bcceda9 --- /dev/null +++ b/challenge-143/conor-hoekstra/apl/ch-2.apl @@ -0,0 +1,4 @@ +solution ← {1∊2-/(⍵∘÷+⊢)∪⍵∨⍳⌊⍵*.5} + +⍝ Tests +solution ¨ 36 12 6 ⍝ 1 1 0 diff --git a/challenge-143/dave-jacoby/blog.txt b/challenge-143/dave-jacoby/blog.txt new file mode 100644 index 0000000000..c3e15f2677 --- /dev/null +++ b/challenge-143/dave-jacoby/blog.txt @@ -0,0 +1 @@ +https://jacoby.github.io/2021/12/14/ninja-numbers-hiding-in-trees-the-weekly-challenge-143.html diff --git a/challenge-143/dave-jacoby/perl/ch-1.pl b/challenge-143/dave-jacoby/perl/ch-1.pl new file mode 100644 index 0000000000..0caded391c --- /dev/null +++ b/challenge-143/dave-jacoby/perl/ch-1.pl @@ -0,0 +1,62 @@ +#!/usr/bin/env perl + +use strict; +use warnings; +use feature qw{ say state postderef signatures }; +no warnings qw{ experimental }; + +my @examples; +push @examples, '( 5 * 10 ) - ( 12 * 3 )'; +push @examples, '10 + 20 - 5'; +push @examples, '(10 + 20 - 5) * 2'; +push @examples, '( ( 10 * 20 ) - 5) * 2'; + +for my $i (@examples) { + my $o = calculator($i); + my $o2 = bc($i); + say <<"END"; + Input: \$i = $i + Output: $o + BC: $o2 +END +} + +sub calculator( $s) { + + # parens + while ( $s =~ /\([\s\d\+\-\*]+\)/mix ) { + $s =~ s/\(([\s\d\+\-\*]+\))/calculator( unbracket( $1 ))/e; + } + + # multiplication + + while ( $s =~ / \d+ \s* \* \s* \d+ /mx ) { + $s =~ s/( (\d+) \s* \* \s* (\d+) )/ $2 * $3 /emx; + } + + # addition + + while ( $s =~ / \d+ \s* \+ \s* \d+ /mx ) { + $s =~ s/( (\d+) \s* \+ \s* (\d+) )/ $2 + $3 /emx; + } + + # subtraction + while ( $s =~ / \d+ \s* \- \s* \d+ /mx ) { + $s =~ s/( (\d+) \s* \- \s* (\d+) )/ $2 - $3 /emx; + } + return $s; +} + +sub unbracket( $s ) { + $s =~ s/^\(//; + $s =~ s/\)$//; + return $s; +} + +# This is the easy way, using pre-existing code +sub bc( $s) { + my $cmd = qq{ echo '$s' | bc }; + my $x = qx{$cmd}; + chomp $x; + return $x; +} diff --git a/challenge-143/dave-jacoby/perl/ch-2.pl b/challenge-143/dave-jacoby/perl/ch-2.pl new file mode 100644 index 0000000000..c712e2014b --- /dev/null +++ b/challenge-143/dave-jacoby/perl/ch-2.pl @@ -0,0 +1,41 @@ +#!/usr/bin/env perl + +use strict; +use warnings; +use feature qw{ say postderef signatures state }; +no warnings qw{ experimental }; + +my @examples = qw( 6 12 24 36 ); + +for my $i (@examples) { + my $o = stealthy_numbers($i); + say <<"END"; + Input: \$n = $i + Output: $o +END +} + +sub stealthy_numbers ( $n ) { + my @factors = get_factor_pairs($n); + for my $i ( 0 .. -1 + scalar @factors ) { + my ( $ix, $iy ) = $factors[$i]->@*; + for my $j ( $i + 1 .. -1 + scalar @factors ) { + my ( $jx, $jy ) = $factors[$j]->@*; + my $addi = $ix + $iy; + my $addj = $jx + $jy; + return 1 if abs( $addi - $addj ) == 1; + } + } + return 0; +} + +sub get_factor_pairs( $n ) { + my %hash; + for my $x ( map { int $_ } 1 .. $n ) { + next unless $n % $x == 0; + my $y = $n / $x; + my $xy = join ',', sort { $a <=> $b } $x, $y; + $hash{$xy} = 1; + } + return map { [ split /,/, $_ ] } sort keys %hash; +} diff --git a/challenge-143/e-choroba/perl/ch-1.pl b/challenge-143/e-choroba/perl/ch-1.pl new file mode 100755 index 0000000000..b1e25bec50 --- /dev/null +++ b/challenge-143/e-choroba/perl/ch-1.pl @@ -0,0 +1,62 @@ +#!/usr/bin/perl +use warnings; +use strict; + +sub calculator { + my ($expression) = @_; + while ($expression =~ m{[ ()]}) { + $expression =~ s/(-?\d+) (\*) (-?\d+)/$1 * $3/e; + $expression =~ s/(-?\d+) ([-+]) (-?\d+)/"$1 $2 $3"/ee; + $expression =~ s/\((-?\d+)\)/$1/g; + } + return $expression +} + +use Marpa::R2; +my $dsl = << '__DSL__'; + + lexeme default = latm => 1 + :default ::= action => ::first + + Expression ::= Number + | ('(') Expression (')') assoc => group + || Expression (ws asterisk ws) Expression action => multiply + || Expression (ws plus ws) Expression action => add + | Expression (ws minus ws) Expression action => subtract + Number ::= Negative | positive + Negative ::= minus positive action => neg + + ws ~ [\s]+ + asterisk ~ '*' + plus ~ '+' + positive ~ [\d]+ + minus ~ '-' + +__DSL__ + +sub add { $_[1] + $_[2] } +sub subtract { $_[1] - $_[2] } +sub multiply { $_[1] * $_[2] } +sub neg { -$_[2] } +sub second { $_[2] } + +my $grammar = 'Marpa::R2::Scanless::G'->new({source => \$dsl}); + +sub calculate { + my ($input) = @_; + return ${ $grammar->parse(\$input, 'main') } +} + +use Test2::V0; +plan 8; + +my %tests = ( + 'Example 1' => ['10 + 20 - 5', 25], + 'Example 2' => ['(10 + 20 - 5) * 2', 50], + Negative => ['(1 + 2) - (1 * 12)', -9], + Precedence => ['((-1 - -2 - -3 * -4 + -5))', -16]); + +for my $t (sort keys %tests) { + is calculator($tests{$t}[0]), $tests{$t}[1], "regex $t"; + is calculate($tests{$t}[0]), $tests{$t}[1], "marpa $t"; +} diff --git a/challenge-143/e-choroba/perl/ch-2.pl b/challenge-143/e-choroba/perl/ch-2.pl new file mode 100755 index 0000000000..3feae62c6a --- /dev/null +++ b/challenge-143/e-choroba/perl/ch-2.pl @@ -0,0 +1,24 @@ +#!/usr/bin/perl +use warnings; +use strict; +use feature qw{ say }; + +sub stealthy_number { + my ($n) = @_; + my @divisors = (map $n / $_, grep 0 == $n % $_, 1 .. sqrt $n); + for my $A (@divisors) { + for my $C (@divisors) { + my $B = $n / $A; + my $D = $n / $C; + return 1 if $A + $B == $C + $D + 1; + } + } + return 0 +} + +use Test2::V0; +plan 3; + +is stealthy_number(36), 1, 'Example 1'; +is stealthy_number(12), 1, 'Example 2'; +is stealthy_number(6), 0, 'Example 3'; diff --git a/challenge-143/luca-ferrari/blog-1.txt b/challenge-143/luca-ferrari/blog-1.txt new file mode 100644 index 0000000000..fbfeba6f6c --- /dev/null +++ b/challenge-143/luca-ferrari/blog-1.txt @@ -0,0 +1 @@ +https://fluca1978.github.io/2021/12/13/PerlWeeklyChallenge143.html#task1 diff --git a/challenge-143/luca-ferrari/blog-2.txt b/challenge-143/luca-ferrari/blog-2.txt new file mode 100644 index 0000000000..d7ed898652 --- /dev/null +++ b/challenge-143/luca-ferrari/blog-2.txt @@ -0,0 +1 @@ +https://fluca1978.github.io/2021/12/13/PerlWeeklyChallenge143.html#task2 diff --git a/challenge-143/luca-ferrari/blog-3.txt b/challenge-143/luca-ferrari/blog-3.txt new file mode 100644 index 0000000000..bd24cc0a68 --- /dev/null +++ b/challenge-143/luca-ferrari/blog-3.txt @@ -0,0 +1 @@ +https://fluca1978.github.io/2021/12/13/PerlWeeklyChallenge143.html#task2pg diff --git a/challenge-143/luca-ferrari/postgresql/ch-2.sql b/challenge-143/luca-ferrari/postgresql/ch-2.sql new file mode 100644 index 0000000000..4f67625b37 --- /dev/null +++ b/challenge-143/luca-ferrari/postgresql/ch-2.sql @@ -0,0 +1,32 @@ +CREATE OR REPLACE FUNCTION f_stealth( needle int ) + RETURNS int +AS $CODE$ + WITH numbers AS ( SELECT generate_series( 2, needle ) as n ) + , pairs AS ( + SELECT needle as n + , n as divisor + , needle / n as divisor_2 + , case needle % n + when 0 then n + needle / n + else null + end as summix + from numbers + ) + , stealth as ( + select * + , abs( summix - lag( summix, 1, summix ) over ( ORDER BY summix DESC ) ) as lag + , abs( summix - lead( summix, 1, summix ) over ( ORDER BY summix DESC ) ) as lead + FROM pairs + where summix is not null + ) + + SELECT CASE count(*) + WHEN 0 THEN 0 + ELSE 1 + END + FROM stealth + WHERE ( lag = 1 or lead = 1 ); + + + $CODE$ + LANGUAGE sql; diff --git a/challenge-143/luca-ferrari/raku/ch-1.p6 b/challenge-143/luca-ferrari/raku/ch-1.p6 new file mode 100644 index 0000000000..3ffbf3107b --- /dev/null +++ b/challenge-143/luca-ferrari/raku/ch-1.p6 @@ -0,0 +1,124 @@ +#!raku + + +my Str $OPERATOR_ADD = '+'; +my Str $OPERATOR_MINUS = '-'; +my Str $OPERATOR_MULTIPLY = '*'; +my Str $OPERATOR_DIVIDE = '/'; + + + + +grammar Calculator { + rule TOP { + ^ <expression> $ + } + + rule expression { + | <operation>+ %% $<operator>=([$OPERATOR_ADD|$OPERATOR_MINUS]) + | <parenthesized-expression> + } + rule operation { + <operand>+ %% $<operator>=([$OPERATOR_MULTIPLY|$OPERATOR_DIVIDE]) + } + + rule operand { + | <number> + | <parenthesized-expression> + } + + rule parenthesized-expression { + '(' <expression> ')' + } + + token number { \d+ } +} + + +class CalculatorActions { + method TOP($/) { + $/.make: $<expression>.made + } + + + method parenthesized-expression($/) { + $/.make: $<expression>.made + } + + method number($/) { + $/.make: +$/ + } + + + method operand($/) { + $/.make: $<number> ?? $<number>.Int !! $<parenthesized-expression>.made; + } + + + # Computes a single operation in the form + # a + b + method do-compute( $left-operand, $operator, $right-operand ) { + given $operator { + when $OPERATOR_ADD { $left-operand + $right-operand } + when $OPERATOR_MINUS { $left-operand - $right-operand } + when $OPERATOR_MULTIPLY { $left-operand * $right-operand } + when $OPERATOR_DIVIDE { $left-operand / $right-operand } + } + } + + + # Computes all the operation given the first operand, the set of operators + # and the other operands. + # For example: + # 1 + 2 * 3 + # becomes + # do-compute-all( 1, [+,*], [2,3]) + method do-compute-all( $left-operand is rw, @operators, @operands ) { + while ( @operators.elems > 0 ) { + $left-operand = self.do-compute( $left-operand, + @operators.pop, + @operands.pop ); + } + } + + method operation($/) { + # left part + my $result = $<operand>[ 0 ].made; + + # if there is a right part ... + if $<operator> { + my @operators = $<operator>.map( *.Str ); + my @operands = $<operand>[ 1..* ].map( *.made ); + + self.do-compute-all( $result, @operators, @operands ); + } + + $/.make: $result; + } + + + + method expression($/) { + if $<parenthesized-expression> { + $/.make: $<parenthesized-expression>.made + } + else { + my $result = $<operation>[ 0 ].made; + + if $<operator> { + my @operators = $<operator>.map( *.Str ); + my @operands = $<operation>[ 1..* ].map( *.made ); + + self.do-compute-all( $result, @operators, @operands ); + + } + + $/.make: $result; + } + } +} + +sub MAIN( Str $expr ) { + my $calculator = Calculator.parse( $expr, :actions( CalculatorActions ) ); + "{ $expr } = { $calculator.made }".say; +} diff --git a/challenge-143/luca-ferrari/raku/ch-2.p6 b/challenge-143/luca-ferrari/raku/ch-2.p6 new file mode 100644 index 0000000000..b0be43e59c --- /dev/null +++ b/challenge-143/luca-ferrari/raku/ch-2.p6 @@ -0,0 +1,23 @@ +#!raku + +sub MAIN( Int $n where { $n > 0 }, Bool :$verbose = False ) { + my @numbers = 1 ^..^ $n; + + # extract all the pairs to get the $n by multiplication + my @pairs = @numbers.grep( $n %% * ).map( { $_, $n / $_, $_ + $n / $_ } ); + + # now extract all the pairs couples that have a difference of one + my $found = False; + for 0 ..^ @pairs.elems -> $left { + for $left ^..^ @pairs.elems -> $right { + if @pairs[ $left ][ 2 ] - @pairs[ $right ][ 2 ] == any( 1, -1 ) { + $found = True; + "$n is stealth by { @pairs[ $left ][ 0..1 ].join( ',' ) } and { @pairs[ $right ][ 0..1 ].join( ',' ) }".say if $verbose; + } + } + } + + "1".say and exit if $found; + "0".say; + +} diff --git a/challenge-143/paulo-custodio/perl/ch-1.pl b/challenge-143/paulo-custodio/perl/ch-1.pl index 90b6fe6506..73a806191b 100644 --- a/challenge-143/paulo-custodio/perl/ch-1.pl +++ b/challenge-143/paulo-custodio/perl/ch-1.pl @@ -3,10 +3,10 @@ |
