From 3372aa59aa755e499917b0cb31b4d385c30f1ae1 Mon Sep 17 00:00:00 2001 From: Adam Russell Date: Sun, 23 Oct 2022 11:05:25 -0400 Subject: initial commit --- challenge-187/adam-russell/blog.txt | 1 + challenge-187/adam-russell/blog1.txt | 1 + challenge-187/adam-russell/perl/ch-1.pl | 48 ++++++++++++++++++++++++++++++++ challenge-187/adam-russell/perl/ch-2.pl | 38 +++++++++++++++++++++++++ challenge-187/adam-russell/prolog/ch-2.p | 10 +++++++ 5 files changed, 98 insertions(+) create mode 100644 challenge-187/adam-russell/blog.txt create mode 100644 challenge-187/adam-russell/blog1.txt create mode 100644 challenge-187/adam-russell/perl/ch-1.pl create mode 100644 challenge-187/adam-russell/perl/ch-2.pl create mode 100644 challenge-187/adam-russell/prolog/ch-2.p diff --git a/challenge-187/adam-russell/blog.txt b/challenge-187/adam-russell/blog.txt new file mode 100644 index 0000000000..5cc1e4bcea --- /dev/null +++ b/challenge-187/adam-russell/blog.txt @@ -0,0 +1 @@ +http://www.rabbitfarm.com/cgi-bin/blosxom/perl/2022/10/23 \ No newline at end of file diff --git a/challenge-187/adam-russell/blog1.txt b/challenge-187/adam-russell/blog1.txt new file mode 100644 index 0000000000..5abed41bec --- /dev/null +++ b/challenge-187/adam-russell/blog1.txt @@ -0,0 +1 @@ +http://www.rabbitfarm.com/cgi-bin/blosxom/prolog/2022/10/23 \ No newline at end of file diff --git a/challenge-187/adam-russell/perl/ch-1.pl b/challenge-187/adam-russell/perl/ch-1.pl new file mode 100644 index 0000000000..bf21b2369c --- /dev/null +++ b/challenge-187/adam-russell/perl/ch-1.pl @@ -0,0 +1,48 @@ +use v5.36; +use strict; +use warnings; +## +# Two friends, Foo and Bar gone on holidays seperately to the same city. You are given their schedule i.e. start date and end date. +# To keep the task simple, the date is in the form DD-MM and all dates belong to the same calendar year i.e. between 01-01 and 31-12. +# Also the year is non-leap year and both dates are inclusive. +# Write a script to find out for the given schedule, how many days they spent together in the city, if at all. +## +use Time::Piece; +use Time::Seconds; + +sub days_together{ + my($together) = @_; + my $days_together = 0; + my($start, $end); + my $foo_start = Time::Piece->strptime($together->{Foo}->{SD}, q/%d-%m/); + my $bar_start = Time::Piece->strptime($together->{Bar}->{SD}, q/%d-%m/); + my $foo_end = Time::Piece->strptime($together->{Foo}->{ED}, q/%d-%m/); + my $bar_end = Time::Piece->strptime($together->{Bar}->{ED}, q/%d-%m/); + $start = $foo_start; + $start = $bar_start if $bar_start > $foo_start; + $end = $foo_end; + $end = $bar_end if $bar_end < $foo_end; + { + $days_together++ if $start <= $end; + $start += ONE_DAY; + redo if $start <= $end; + } + return $days_together; +} + + +MAIN:{ + my $days; + $days = days_together({Foo => {SD => q/12-01/, ED => q/20-01/}, + Bar => {SD => q/15-01/, ED => q/18-01/}}); + say $days; + $days = days_together({Foo => {SD => q/02-03/, ED => q/12-03/}, + Bar => {SD => q/13-03/, ED => q/14-03/}}); + say $days; + $days = days_together({Foo => {SD => q/02-03/, ED => q/12-03/}, + Bar => {SD => q/11-03/, ED => q/15-03/}}); + say $days; + $days = days_together({Foo => {SD => q/30-03/, ED => q/05-04/}, + Bar => {SD => q/28-03/, ED => q/02-04/}}); + say $days; +} diff --git a/challenge-187/adam-russell/perl/ch-2.pl b/challenge-187/adam-russell/perl/ch-2.pl new file mode 100644 index 0000000000..79bedcce41 --- /dev/null +++ b/challenge-187/adam-russell/perl/ch-2.pl @@ -0,0 +1,38 @@ +use v5.36; +use strict; +use warnings; +## +# You are given a list of positive numbers, @n, having at least 3 numbers. +# Write a script to find the triplets (a, b, c) from the given list that satisfies +# the following rules. +# a + b > c +# b + c > a +# a + c > b +# a + b + c is maximum. +## +use Hash::MultiKey; +use Math::Combinatorics; + +sub magical_triples{ + my(@numbers) = @_; + my %triple_sum; + tie %triple_sum, q/Hash::MultiKey/; + my $combinations = Math::Combinatorics->new(count => 3, data => [@numbers]); + my($s, $t, $u); + while(my @combination = $combinations->next_combination()){ + my($s, $t, $u) = @combination; + my $sum; + $sum = $s + $t + $u if $s + $t > $u && $t + $u > $s && $s + $u > $t; + $triple_sum{[$s, $t, $u]} = $sum if $sum; + } + my @triples_sorted = sort {$triple_sum{$b} <=> $triple_sum{$a}} keys %triple_sum; + return ($triples_sorted[0]->[0], $triples_sorted[0]->[1], $triples_sorted[0]->[2]) if @triples_sorted; + return (); +} + +MAIN:{ + say "(" . join(", ", magical_triples(1, 2, 3, 2)) . ")"; + say "(" . join(", ", magical_triples(1, 3, 2)) . ")"; + say "(" . join(", ", magical_triples(1, 1, 2, 3)) . ")"; + say "(" . join(", ", magical_triples(2, 4, 3)) . ")"; +} \ No newline at end of file diff --git a/challenge-187/adam-russell/prolog/ch-2.p b/challenge-187/adam-russell/prolog/ch-2.p new file mode 100644 index 0000000000..a7c0c86c0b --- /dev/null +++ b/challenge-187/adam-russell/prolog/ch-2.p @@ -0,0 +1,10 @@ +magical_triple_sum(Numbers, Triple, TripleSum):- + sublist([A, B, C], Numbers), + A + B > C, + B + C > A, + A + C > B, + Triple = [A, B, C], + sum_list(Triple, TripleSum). + +magical_triple(Numbers, Triple):- + fd_maximize(magical_triple_sum(Numbers, Triple, TripleSum), TripleSum). \ No newline at end of file -- cgit From c7307733a39bb6a776dbb43dce38dccf8d83d476 Mon Sep 17 00:00:00 2001 From: Jan Krňávek Date: Sun, 23 Oct 2022 21:39:42 +0200 Subject: solution week 187-1 --- challenge-187/wambash/raku/ch-1.raku | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 challenge-187/wambash/raku/ch-1.raku diff --git a/challenge-187/wambash/raku/ch-1.raku b/challenge-187/wambash/raku/ch-1.raku new file mode 100644 index 0000000000..a1edafafba --- /dev/null +++ b/challenge-187/wambash/raku/ch-1.raku @@ -0,0 +1,22 @@ +#!/usr/bin/env raku +multi days-together ( +@dr ) { + [∩] @dr + andthen .elems +} + + +multi MAIN (Bool :test($)!) { + use Test; + is-deeply days-together((.clone(:12day) .. .clone(:20day)), (.clone(:15day) .. .clone(:18day))), 4 with Date.new: '1999-01-01'; + is-deeply days-together((.clone( :2day) .. .clone(:12day)), (.clone(:13day) .. .clone(:14day))), 0 with Date.new: '1999-03-01'; + is-deeply days-together((.clone( :2day) .. .clone(:12day)), (.clone(:11day) .. .clone(:15day))), 2 with Date.new: '1999-03-01'; + is-deeply days-together( + (.clone(:30day) .. .clone(:5day:4month)), + (.clone(:28day) .. .clone(:2day:4month)) + ), 4 with Date.new: '1999-03-01'; + done-testing; +} + +multi MAIN (Date() $Foo-sd,Date() $Foo-ed, Date() $Bar-sd, Date() $Bar-ed) { + say days-together $Foo-sd..$Foo-ed, $Bar-sd..$Bar-ed +} -- cgit From 83d7deba390598a9759c9981eb768cfc1c2fdb31 Mon Sep 17 00:00:00 2001 From: arnesom Date: Sun, 23 Oct 2022 22:03:18 +0200 Subject: Arne Sommer --- challenge-187/arne-sommer/blog.txt | 1 + challenge-187/arne-sommer/raku/ch-1.raku | 39 +++++++++++++++++++++++++ challenge-187/arne-sommer/raku/ch-2.raku | 32 ++++++++++++++++++++ challenge-187/arne-sommer/raku/days-together | 39 +++++++++++++++++++++++++ challenge-187/arne-sommer/raku/magical-triplets | 32 ++++++++++++++++++++ 5 files changed, 143 insertions(+) create mode 100644 challenge-187/arne-sommer/blog.txt create mode 100755 challenge-187/arne-sommer/raku/ch-1.raku create mode 100755 challenge-187/arne-sommer/raku/ch-2.raku create mode 100755 challenge-187/arne-sommer/raku/days-together create mode 100755 challenge-187/arne-sommer/raku/magical-triplets diff --git a/challenge-187/arne-sommer/blog.txt b/challenge-187/arne-sommer/blog.txt new file mode 100644 index 0000000000..1b0746e883 --- /dev/null +++ b/challenge-187/arne-sommer/blog.txt @@ -0,0 +1 @@ +https://raku-musings.com/magical-together.html diff --git a/challenge-187/arne-sommer/raku/ch-1.raku b/challenge-187/arne-sommer/raku/ch-1.raku new file mode 100755 index 0000000000..e8558a7323 --- /dev/null +++ b/challenge-187/arne-sommer/raku/ch-1.raku @@ -0,0 +1,39 @@ +#! /usr/bin/env raku + +unit sub MAIN (:v(:$verbose)); + +my $year = 2022; + +say days-together({ 'Foo' => { 'SD' => '12-01', 'ED' => '20-01' }, + 'Bar' => { 'SD' => '15-01', 'ED' => '18-01' }}); + + +say days-together({ 'Foo' => { 'SD' => '02-03', 'ED' => '12-03' }, + 'Bar' => { 'SD' => '13-03', 'ED' => '14-03' }}); + + +say days-together({ 'Foo' => { 'SD' => '02-03', 'ED' => '12-03' }, + 'Bar' => { 'SD' => '11-03', 'ED' => '15-03' }}); + +say days-together({ 'Foo' => { 'SD' => '30-03', 'ED' => '05-04' }, + 'Bar' => { 'SD' => '28-03', 'ED' => '02-04' }}); + + +sub days-together ($struct) +{ + my $sf = Date.new($year ~ "-" ~ $struct..split("-").reverse.join("-")).day-of-year; + my $ef = Date.new($year ~ "-" ~ $struct..split("-").reverse.join("-")).day-of-year; + my $sb = Date.new($year ~ "-" ~ $struct..split("-").reverse.join("-")).day-of-year; + my $eb = Date.new($year ~ "-" ~ $struct..split("-").reverse.join("-")).day-of-year; + + say ": $sf, $ef, $sb, $eb" if $verbose; + + return 0 if $sf > $eb; + return 0 if $sb > $ef; + + my $start = max($sf, $sb); + my $end = min($ef, $eb); + + return $end - $start + 1; +} + diff --git a/challenge-187/arne-sommer/raku/ch-2.raku b/challenge-187/arne-sommer/raku/ch-2.raku new file mode 100755 index 0000000000..fb6b7ea31d --- /dev/null +++ b/challenge-187/arne-sommer/raku/ch-2.raku @@ -0,0 +1,32 @@ +#! /usr/bin/env raku + +unit sub MAIN (*@n where @n.elems >= 3, :v(:$verbose)); + +my $max = @n.combinations(3)>>.sum.max; + +say ":Max: $max" if $verbose; + +# my @candidates = @n.combinations(3)>>.permutations[*;*].unique(:with(&[eqv])); +my @candidates = @n>>.Int.combinations(3)>>.permutations[*;*].unique(:with(&[eqv])); + +say ":Permutations: { @candidates.raku }" if $verbose; + +my @ok = @candidates.grep( { $_[0] + $_[1] > $_[2] && + $_[1] + $_[2] > $_[0] && + $_[0] + $_[2] > $_[1] && + $_.sum == $max }); + +say ":Rule 1-4 applied: { @ok.raku }" if $verbose; + +if @ok.elems == 0 +{ + say "()"; +} +elsif @ok.elems == 1 +{ + say "(", @ok[0].join(", "), ")"; +} +else +{ + say "(", @ok.grep( { $_[0] >= $_[1] >= $_[2] })[0].join(", "), ")"; +} diff --git a/challenge-187/arne-sommer/raku/days-together b/challenge-187/arne-sommer/raku/days-together new file mode 100755 index 0000000000..e8558a7323 --- /dev/null +++ b/challenge-187/arne-sommer/raku/days-together @@ -0,0 +1,39 @@ +#! /usr/bin/env raku + +unit sub MAIN (:v(:$verbose)); + +my $year = 2022; + +say days-together({ 'Foo' => { 'SD' => '12-01', 'ED' => '20-01' }, + 'Bar' => { 'SD' => '15-01', 'ED' => '18-01' }}); + + +say days-together({ 'Foo' => { 'SD' => '02-03', 'ED' => '12-03' }, + 'Bar' => { 'SD' => '13-03', 'ED' => '14-03' }}); + + +say days-together({ 'Foo' => { 'SD' => '02-03', 'ED' => '12-03' }, + 'Bar' => { 'SD' => '11-03', 'ED' => '15-03' }}); + +say days-together({ 'Foo' => { 'SD' => '30-03', 'ED' => '05-04' }, + 'Bar' => { 'SD' => '28-03', 'ED' => '02-04' }}); + + +sub days-together ($struct) +{ + my $sf = Date.new($year ~ "-" ~ $struct..split("-").reverse.join("-")).day-of-year; + my $ef = Date.new($year ~ "-" ~ $struct..split("-").reverse.join("-")).day-of-year; + my $sb = Date.new($year ~ "-" ~ $struct..split("-").reverse.join("-")).day-of-year; + my $eb = Date.new($year ~ "-" ~ $struct..split("-").reverse.join("-")).day-of-year; + + say ": $sf, $ef, $sb, $eb" if $verbose; + + return 0 if $sf > $eb; + return 0 if $sb > $ef; + + my $start = max($sf, $sb); + my $end = min($ef, $eb); + + return $end - $start + 1; +} + diff --git a/challenge-187/arne-sommer/raku/magical-triplets b/challenge-187/arne-sommer/raku/magical-triplets new file mode 100755 index 0000000000..fb6b7ea31d --- /dev/null +++ b/challenge-187/arne-sommer/raku/magical-triplets @@ -0,0 +1,32 @@ +#! /usr/bin/env raku + +unit sub MAIN (*@n where @n.elems >= 3, :v(:$verbose)); + +my $max = @n.combinations(3)>>.sum.max; + +say ":Max: $max" if $verbose; + +# my @candidates = @n.combinations(3)>>.permutations[*;*].unique(:with(&[eqv])); +my @candidates = @n>>.Int.combinations(3)>>.permutations[*;*].unique(:with(&[eqv])); + +say ":Permutations: { @candidates.raku }" if $verbose; + +my @ok = @candidates.grep( { $_[0] + $_[1] > $_[2] && + $_[1] + $_[2] > $_[0] && + $_[0] + $_[2] > $_[1] && + $_.sum == $max }); + +say ":Rule 1-4 applied: { @ok.raku }" if $verbose; + +if @ok.elems == 0 +{ + say "()"; +} +elsif @ok.elems == 1 +{ + say "(", @ok[0].join(", "), ")"; +} +else +{ + say "(", @ok.grep( { $_[0] >= $_[1] >= $_[2] })[0].join(", "), ")"; +} -- cgit From 9b716d57b0ebfc7454b5868c1d90f47bc07c0bf4 Mon Sep 17 00:00:00 2001 From: Util Date: Sun, 23 Oct 2022 16:00:18 -0500 Subject: Add TWC 187 solutions by Bruce Gray : Raku only. --- challenge-187/bruce-gray/raku/ch-1.raku | 96 +++++++++++++++++++++++++++++++++ challenge-187/bruce-gray/raku/ch-2.raku | 71 ++++++++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 challenge-187/bruce-gray/raku/ch-1.raku create mode 100644 challenge-187/bruce-gray/raku/ch-2.raku diff --git a/challenge-187/bruce-gray/raku/ch-1.raku b/challenge-187/bruce-gray/raku/ch-1.raku new file mode 100644 index 0000000000..3d3411f325 --- /dev/null +++ b/challenge-187/bruce-gray/raku/ch-1.raku @@ -0,0 +1,96 @@ + +# Not needed (could use Set), but more efficient this way, and these lines are reusable +multi sub infix:<∩> ( Range \a, Range \b --> Range ) { (a,b)».min.max .. (a,b)».max.min } +multi sub infix:<∪> ( Range \a, Range \b --> Range ) { (a,b)».min.min .. (a,b)».max.max } + +sub task1 ( @itineraries ) { + sub offset ( Str $s --> Date ) { + $s ~~ / ^ (\d\d) '-' (\d\d) $ / + orelse die; + + return Date.new(2001, +$1, +$0) + } + + my Range @z = @itineraries.map: -> ($s, $e) { + Range.new( |map &offset, ($s, $e) ); + } + + return elems [∩] @z; +} + +sub get_tests ( ) { + my $test_data = q:to/END/; + Example 1 + + Input: Foo => SD: '12-01' ED: '20-01' + Bar => SD: '15-01' ED: '18-01' + + Output: 4 days + + Example 2 + + Input: Foo => SD: '02-03' ED: '12-03' + Bar => SD: '13-03' ED: '14-03' + + Output: 0 day + + Example 3 + + Input: Foo => SD: '02-03' ED: '12-03' + Bar => SD: '11-03' ED: '15-03' + + Output: 2 days + + Example 4 + + Input: Foo => SD: '30-03' ED: '05-04' + Bar => SD: '28-03' ED: '02-04' + + Output: 4 days + + + Extra 1 + + Input: Foo => SD: '30-03' ED: '05-04' + + Output: 7 days + + Extra 2 + + Input: Foo => SD: '30-03' ED: '05-04' + Bar => SD: '28-03' ED: '02-04' + Baz => SD: '01-04' ED: '02-04' + + Output: 2 days + + END + my regex dashedDate { \d\d \- \d\d } + my regex input { \w+ \s* '=>' \s* 'SD:' \s* \'()\' + \s* 'ED:' \s* \'()\' } + my $re = / + \s* $=[[Example|Extra] \s+ \d+] + \s* 'Input:' \s* + % \s+ + \s* 'Output:' \s* $=[\d+] \s* days? + /; + + my @tests = $test_data.match(:g, $re); + + my @r; + for @tests -> Match $test { + my @starts_and_ends = gather for $test..list -> Match $i { + take $i.map(~*.).cache; + } + push @r, { + name => "$test.: @starts_and_ends[]", + expected => +$test., + in => @starts_and_ends, + }; + } + return @r; +} +use Test; +my @tests = get_tests(); +plan +@tests; +for @tests -> %t { + is task1(%t), %t, %t; +} diff --git a/challenge-187/bruce-gray/raku/ch-2.raku b/challenge-187/bruce-gray/raku/ch-2.raku new file mode 100644 index 0000000000..079da40048 --- /dev/null +++ b/challenge-187/bruce-gray/raku/ch-2.raku @@ -0,0 +1,71 @@ +# Simple, but two passes: +# sub max_list ( @a, &c ) { +# my $max = @a.map(&c).max; +# return @a.grep( *.&c == $max ); +# } + +# Single-pass: +sub max_list ( Iterable $a, Code $c ) { + my ( $max, @r ); + for $a.list -> $aa { + my $cc = $aa.$c; + $max //= $cc; + given $cc cmp $max { + when Order::More { @r = $aa; $max = $cc; } + when Order::Same { @r.push: $aa; } + when Order::Less {} # Do nothing + } + } + return @r; +} + +# Concise, but not better eough to get away from the literal task definition. +# sub valid_triangle_sides ( @abc where *.elems == 3 --> Bool ) { +# return @abc.permutations.map(-> (\a, \b, \c) { a + b > c }).all.so; +# return @abc.permutations.map({ .[0,1].sum > .[2] }).all.so; +# } + +sub valid_triangle_sides ( (\a, \b, \c) --> Bool ) { + return a + b > c + && b + c > a + && a + c > b; +} +sub task2 ( @a ) { + # XXX .combinations does not allow for early exit on $c! So, non-optimal. + my @r = @a.sort(-*).combinations(3).grep(&valid_triangle_sides); + + return @r.&max_list({ .sum }).first({ [≥] .list }) // (); +} + + +constant @fibonacci = ( 1, 1, * + * ... * ).head(50); +constant @powers_of_2 = ( 1, * * 2 ... * ).head(50); +constant @powers_of_2_4 = 1, 4, 4, |@powers_of_2.skip(3); +constant @powers_of_2_1 = @powers_of_2.skip(1) X- 1; + +# From: raku -e 'my @a = (1..^10_000).roll(100); say @a.join(",")' +constant @random_100 = 8188,203,44,2634,2658,603,6912,6292,1518,1047,2341,9358,1238,2154,8715,8558,8550,7253,2547,8800,780,4020,2352,5863,6057,7497,8296,6641,8653,3654,5314,9072,8029,6522,8388,8789,9762,4265,79,7714,9014,8671,3385,9961,4078,6256,6311,5816,1790,1396,8631,7488,4469,9897,1419,6340,957,7876,3604,3218,5495,9876,5696,3233,1635,9845,7164,6546,228,3824,2862,8065,8251,9521,5043,7813,2189,6273,7870,7947,2526,5706,6751,4350,1199,8915,9397,4398,9245,3916,7977,2749,3944,8073,3410,1617,9150,7324,8374,4776; + + +my @tests = + # Original examples from TWC 187: + ( :Ex1(1, 2, 3, 2) , (3, 2, 2) ), + ( :Ex2(1, 3, 2) , () ), + ( :Ex3(1, 1, 2, 3) , () ), + ( :Ex4(2, 4, 3) , (4, 3, 2) ), + + # Extra tests, by author: + ( :Short(2, 4) , () ), + ( :@powers_of_2 , () ), + ( :@powers_of_2_4 , (4, 4, 1) ), + ( :@powers_of_2_1 , () ), + ( :@fibonacci , () ), + ( :@random_100, @random_100.sort(-*).head(3) ), + +; +use Test; +plan +@tests; +for @tests { + my ( $name, $input, $expected ) = .[0].key, .[0].value, .[1]; + is-deeply task2($input), $expected, $name; +} -- cgit From 464e5ff7037bdae758d80848f499a2bb53f5caee Mon Sep 17 00:00:00 2001 From: dcw Date: Sun, 23 Oct 2022 23:07:51 +0100 Subject: imported my solutions to both tasks in C and Perl --- challenge-187/duncan-c-white/C/.cbuild | 2 +- challenge-187/duncan-c-white/C/Makefile | 18 +++ challenge-187/duncan-c-white/C/README | 11 ++ challenge-187/duncan-c-white/C/args.c | 207 ++++++++++++++++++++++++++++ challenge-187/duncan-c-white/C/args.h | 11 ++ challenge-187/duncan-c-white/C/ch-1.c | 116 ++++++++++++++++ challenge-187/duncan-c-white/C/ch-2.c | 188 +++++++++++++++++++++++++ challenge-187/duncan-c-white/C/parseints.c | 105 ++++++++++++++ challenge-187/duncan-c-white/C/parseints.h | 1 + challenge-187/duncan-c-white/C/printarray.c | 39 ++++++ challenge-187/duncan-c-white/C/printarray.h | 1 + challenge-187/duncan-c-white/README | 93 ++++++++++--- challenge-187/duncan-c-white/perl/ch-1.pl | 127 +++++++++++++++++ challenge-187/duncan-c-white/perl/ch-2.pl | 114 +++++++++++++++ 14 files changed, 1010 insertions(+), 23 deletions(-) create mode 100644 challenge-187/duncan-c-white/C/Makefile create mode 100644 challenge-187/duncan-c-white/C/README create mode 100644 challenge-187/duncan-c-white/C/args.c create mode 100644 challenge-187/duncan-c-white/C/args.h create mode 100644 challenge-187/duncan-c-white/C/ch-1.c create mode 100644 challenge-187/duncan-c-white/C/ch-2.c create mode 100644 challenge-187/duncan-c-white/C/parseints.c create mode 100644 challenge-187/duncan-c-white/C/parseints.h create mode 100644 challenge-187/duncan-c-white/C/printarray.c create mode 100644 challenge-187/duncan-c-white/C/printarray.h create mode 100755 challenge-187/duncan-c-white/perl/ch-1.pl create mode 100755 challenge-187/duncan-c-white/perl/ch-2.pl diff --git a/challenge-187/duncan-c-white/C/.cbuild b/challenge-187/duncan-c-white/C/.cbuild index 624a95ebfb..a14ec76520 100644 --- a/challenge-187/duncan-c-white/C/.cbuild +++ b/challenge-187/duncan-c-white/C/.cbuild @@ -1,4 +1,4 @@ -BUILD = ch-1 +BUILD = ch-1 ch-2 CFLAGS = -Wall -g #LDFLAGS = -lm #CFLAGS = -g diff --git a/challenge-187/duncan-c-white/C/Makefile b/challenge-187/duncan-c-white/C/Makefile new file mode 100644 index 0000000000..34d8a4d520 --- /dev/null +++ b/challenge-187/duncan-c-white/C/Makefile @@ -0,0 +1,18 @@ +# Makefile rules generated by CB +CC = gcc +CFLAGS = -Wall -g +BUILD = ch-1 ch-2 + +all: $(BUILD) + +clean: + /bin/rm -f $(BUILD) *.o core a.out + +args.o: args.c +ch-1: ch-1.o args.o +ch-1.o: ch-1.c args.h +ch-2: ch-2.o args.o parseints.o printarray.o +ch-2.o: ch-2.c args.h parseints.h printarray.h +parseints.o: parseints.c args.h parseints.h printarray.h +printarray.o: printarray.c + diff --git a/challenge-187/duncan-c-white/C/README b/challenge-187/duncan-c-white/C/README new file mode 100644 index 0000000000..b7043e9cbb --- /dev/null +++ b/challenge-187/duncan-c-white/C/README @@ -0,0 +1,11 @@ +Thought I'd also have a go at translating ch-1.pl into C.. + +Of course, it can only deal with lists of integers, so the original +examples have to change. + +It produce identical (non-debugging) output to my Perl original. + +It uses several of my regular support modules: +- a command-line argument processing module args.[ch], +- a csvlist-of-int parsing module parseints.[ch], and +- an int-array printing module printarray.[ch]. diff --git a/challenge-187/duncan-c-white/C/args.c b/challenge-187/duncan-c-white/C/args.c new file mode 100644 index 0000000000..d4a2d38b9a --- /dev/null +++ b/challenge-187/duncan-c-white/C/args.c @@ -0,0 +1,207 @@ +#include +#include +#include +#include +#include +#include + + +bool debug = false; + + +// process_flag_noarg( name, argc, argv ); +// Process the -d flag, and check that there are no +// remaining arguments. +void process_flag_noarg( char *name, int argc, char **argv ) +{ + int arg=1; + if( argc>1 && strcmp( argv[arg], "-d" ) == 0 ) + { + debug = true; + arg++; + } + + int left = argc-arg; + if( left != 0 ) + { + fprintf( stderr, "Usage: %s [-d]\n", name ); + exit(1); + } +} + + +// int argno = process_flag_n_args( name, argc, argv, n, argmsg ); +// Process the -d flag, and check that there are exactly +// n remaining arguments, return the index position of the first +// argument. If not, generate a fatal Usage error using the argmsg. +// +int process_flag_n_args( char *name, int argc, char **argv, int n, char *argmsg ) +{ + int arg=1; + if( argc>1 && strcmp( argv[arg], "-d" ) == 0 ) + { + debug = true; + arg++; + } + + int left = argc-arg; + if( left != n ) + { + fprintf( stderr, "Usage: %s [-d] %s\n Exactly %d " + "arguments needed\n", name, argmsg, n ); + exit(1); + } + return arg; +} + + +// int argno = process_flag_n_m_args( name, argc, argv, min, max, argmsg ); +// Process the -d flag, and check that there are between +// min and max remaining arguments, return the index position of the first +// argument. If not, generate a fatal Usage error using the argmsg. +// +int process_flag_n_m_args( char *name, int argc, char **argv, int min, int max, char *argmsg ) +{ + int arg=1; + if( argc>1 && strcmp( argv[arg], "-d" ) == 0 ) + { + debug = true; + arg++; + } + + int left = argc-arg; + if( left < min || left > max ) + { + fprintf( stderr, "Usage: %s [-d] %s\n Between %d and %d " + "arguments needed\n", name, argmsg, min, max ); + exit(1); + } + return arg; +} + + +// process_onenumarg_default( name, argc, argv, defvalue, &n ); +// Process the -d flag, and check that there is a single +// remaining numeric argument (or no arguments, in which case +// we use the defvalue), putting it into n +void process_onenumarg_default( char *name, int argc, char **argv, int defvalue, int *n ) +{ + char argmsg[100]; + sprintf( argmsg, "[int default %d]", defvalue ); + int arg = process_flag_n_m_args( name, argc, argv, 0, 1, argmsg ); + + *n = arg == argc ? defvalue : atoi( argv[arg] ); +} + + +// process_onenumarg( name, argc, argv, &n ); +// Process the -d flag, and check that there is a single +// remaining numeric argument, putting it into n +void process_onenumarg( char *name, int argc, char **argv, int *n ) +{ + int arg = process_flag_n_args( name, argc, argv, 1, "int" ); + + // argument is in argv[arg] + *n = atoi( argv[arg] ); +} + + +// process_twonumargs( name, argc, argv, &m, &n ); +// Process the -d flag, and check that there are 2 +// remaining numeric arguments, putting them into m and n +void process_twonumargs( char *name, int argc, char **argv, int *m, int *n ) +{ + int arg = process_flag_n_args( name, argc, argv, 2, "int" ); + + // arguments are in argv[arg] and argv[arg+1] + *m = atoi( argv[arg++] ); + *n = atoi( argv[arg] ); +} + + +// process_twostrargs() IS DEPRECATED: use process_flag_n_m_args() instead + + +// int arr[100]; +// int nel = process_listnumargs( name, argc, argv, arr, 100 ); +// Process the -d flag, and check that there are >= 2 +// remaining numeric arguments, putting them into arr[0..nel-1] +// and returning nel. +int process_listnumargs( char *name, int argc, char **argv, int *arr, int maxel ) +{ + int arg=1; + if( argc>1 && strcmp( argv[arg], "-d" ) == 0 ) + { + debug = true; + arg++; + } + + int left = argc-arg; + if( left < 2 ) + { + fprintf( stderr, "Usage: %s [-d] list_of_numeric_args\n", name ); + exit(1); + } + if( left > maxel ) + { + fprintf( stderr, "%s: more than %d args\n", name, maxel ); + exit(1); + } + + // elements are in argv[arg], argv[arg+1]... + + if( debug ) + { + printf( "debug: remaining arguments are in arg=%d, " + "firstn=%s, secondn=%s..\n", + arg, argv[arg], argv[arg+1] ); + } + + int nel = 0; + for( int i=arg; i +#include +#include +#include +#include +#include + +#include "args.h" +//#include "parseints.h" +//#include "printarray.h" + + +int dim[] = { -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + +// int day_in_year = yearday( ddmm ); +// Check whether $ddmm is a valid date of format dd-mm where dd is 1..31 +// and mm is 1..12 (and dd <= days_in_month(mm)), returning the day number +// in the year if it is, or -1 if it is invalid. +// +int yearday( char *ddmm ) +{ + // validate overall shape /^(\d\d?)-(\d\d?)$/ + int d, m; + if( sscanf( ddmm, "%d-%d", &d, &m ) != 2 ) return -1; + + if( m < 1 || m > 12 ) return -1; + + if( d < 1 || d > dim[m] ) return -1; + + int dayno = 0; + for( int i=1; i(b)?(a):(b)) + + +// +// +// int noverlap = overlapdays( sd1d, ed1d, sd2d, ed2d ); +// Find out the number of overlapping days between the two ranges +// of dates, as the task describes. Each date is represented by +// a logical day-number-in-the-year. Return 0 if no overlap. +int overlapdays( int sd1d, int ed1d, int sd2d, int ed2d ) +{ + // none if one range finishes before the other + if( ed1d < sd2d || ed2d < sd1d ) return 0; + + int csd = max(sd1d,sd2d); // common start date + int ced = min(ed1d,ed2d); // common end date + + return 1+ced-csd; +} + + +int main( int argc, char **argv ) +{ + int argno = process_flag_n_args( "overlapping-days", argc, argv, + 4, "dd-mm-sd1 dd-mm-ed1 dd-mm-sd2 dd-mm-ed2" ); + + if( debug ) + { + printf( "debug: argno=%d, firstarg=%s\n", argno, argv[argno] ); + } + + char *date = argv[argno++]; + int sd1d = yearday( date ); // days since start of year for sd1 + if( sd1d < 1 ) + { + fprintf( stderr, "Bad dd-mm-sd1 (%s)\n", date ); + exit(1); + } + + date = argv[argno++]; + int ed1d = yearday( date ); // days since start of year for ed1 + if( ed1d < 1 ) + { + fprintf( stderr, "Bad dd-mm-ed1 (%s)\n", date ); + exit(1); + } + + date = argv[argno++]; + int sd2d = yearday( date ); // days since start of year for sd2 + if( sd2d < 1 ) + { + fprintf( stderr, "Bad dd-mm-sd2 (%s)\n", date ); + exit(1); + } + + date = argv[argno++]; + int ed2d = yearday( date ); // days since start of year for ed2 + if( ed2d < 1 ) + { + fprintf( stderr, "Bad dd-mm-ed2 (%s)\n", date ); + exit(1); + } + + printf( "sd1:%d, ed1:%d, sd2:%d, ed2:%d\n", sd1d, ed1d, sd2d, ed2d ); + + int noverlap = overlapdays( sd1d, ed1d, sd2d, ed2d ); + printf( "%d days\n", noverlap ); + + return 0; +} diff --git a/challenge-187/duncan-c-white/C/ch-2.c b/challenge-187/duncan-c-white/C/ch-2.c new file mode 100644 index 0000000000..5d3eeb6cd7 --- /dev/null +++ b/challenge-187/duncan-c-white/C/ch-2.c @@ -0,0 +1,188 @@ +// +// Task 2: Magical Triplets +// +// C version. +// + +#include +#include +#include +#include +#include +#include + +#include "args.h" +#include "parseints.h" +#include "printarray.h" + + +typedef struct { + int a, b, c; + int sum; // computed field: a+b+c +} triplet; + + +typedef struct // a dynamic list of triplets +{ + int n, max; + int maxsum; + triplet *t; // dynarray t[max] allocated, t[0..n-1] in use +} tlist; + + +// tlist t; +// bool alreadyseen = add_tlist( a, b, c, &t ); +// Add the triple (a,b,c) to tlist t unless it's already +// present. Return true if it was already present, else return false. +bool add_tlist( int a, int b, int c, tlist *t ) +{ + for( int i=0; in; i++ ) + { + triplet *p = &(t->t[i]); + if( p->a == a && p->b == b && p->c == c ) + { + return true; + } + } + // not found, add (a,b,c) to t + if( t->n == t->max ) + { + t->max += 100; + t->t = realloc( t->t, t->max ); + assert( t->t != NULL ); + } + triplet *p = &(t->t[t->n++]); + p->a = a; + p->b = b; + p->c = c; + // keep track of triplet sum, and tlist maxsum so far + p->sum = a+b+c; + if( p->sum > t->maxsum ) + { + t->maxsum = p->sum; + } + return false; +} + + +// showtlist( FILE *out, char *name, tlist *t ); +// Display t on out. +void showtlist( FILE *out, char *name, tlist *t ) +{ + fprintf( out, "%s has %d triples, max sum=%d\n", + name, t->n, t->maxsum ); + for( int i=0; in; i++ ) + { + triplet *p = &(t->t[i]); + fprintf( out, "%d+%d+%d=%d\n", p->a, p->b, p->c, p->sum ); + } +} + + +// freetlist( t ); +// Free the tlist t. +void freetlist( tlist *t ) +{ + free( t->t ); + free( t ); +} + + +// tlist *t = pass1( x, nel ); +// generate all triples of 3 distinct elements in x (in +// any order) and find those triples that pass rules 1..3, +// building and returning a tlist t of the triplets found. +// Note that a tlist keeps track of the triplet sums, and +// even the current maximum sum, so it's more like pass1+2 +// of the original Perl code. +// Note that the returned value t must be freed by the caller after use. +// +tlist *pass1( int *x, int nel ) +{ + tlist *result = malloc( sizeof(tlist) ); + assert( result != NULL ); + result->max = 100; + result->n = 0; + result->maxsum = 0; + result->t = malloc( result->max * sizeof(triplet) ); + assert( result->t != NULL ); + + for( int p1=0; p1n == 0 ) + { + printf( "No magic triplets found\n" ); + exit(0); + } + + // pass2: identify which of those triples has the maxsum && has a>=b>=c + for( int i=0; in; i++ ) + { + triplet *p = &(p1t->t[i]); + if( p->sum != p1t->maxsum ) continue; + if( p->a < p->b || p->b < p->c ) continue; + printf( "Found magic triple %d, %d, %d\n", p->a, p->b, p->c ); + } + + freetlist( p1t ); + + free( x ); + return 0; +} diff --git a/challenge-187/duncan-c-white/C/parseints.c b/challenge-187/duncan-c-white/C/parseints.c new file mode 100644 index 0000000000..1b188afe8d --- /dev/null +++ b/challenge-187/duncan-c-white/C/parseints.c @@ -0,0 +1,105 @@ +// Simple routine to parse one or more arguments, +// looking for individual +ints or comma-separated +// lists of +ints. +// + +#include +#include +#include +#include +#include +#include + +#include "args.h" +#include "printarray.h" +#include "parseints.h" + +typedef struct +{ + int nel; // current number of elements + int maxel; // maximum number of elements allocated + int *list; // malloc()d list of integers +} intlist; + + +// +// intlist il.. then initialize il.. then: +// add_one( element, &il ); +// +static void add_one( int x, intlist *p ) +{ + if( p->nel > p->maxel ) + { + p->maxel += 128; + p->list = realloc( p->list, p->maxel ); + assert( p->list ); + } + if( debug ) + { + printf( "PIA: appending %d to result at " + "pos %d\n", x, p->nel ); + } + p->list[p->nel++] = x; +} + + +// +// intlist il.. then initialize il.. then: +// add_one_arg( argstr, &il ); +// +static void add_one_arg( char *argstr, intlist *p ) +{ + int x; + if( !check_unsigned_int(argstr,&x) ) + { + fprintf( stderr, "PIA: arg %s must be +int\n", argstr ); + exit(1); + } + add_one( x, p ); +} + + +// +// int nel; +// int *ilist = parse_int_args( argc, argv, argno, &nel ); +// process all arguments argv[argno..argc-1], extracting either +// single ints or comma-separated lists of ints from those arguments, +// accumulate all integers in a dynarray list, storing the total number +// of elements in nel. This list must be freed by the caller. +int *parse_int_args( int argc, char **argv, int argno, int *nel ) +{ + int *result = malloc( 128 * sizeof(int) ); + assert( result ); + intlist il = { 0, 128, result }; + + if( debug ) + { + printf( "PIA: parsing ints from args %d..%d\n", argno, argc-1 ); + } + for( int i=argno; i +#include + + +// print_int_array( maxw, nelements, results[], sep, outfile ); +// format results[0..nelements-1] as a separated +// list onto outfile with lines <= maxw chars long. +// produces a whole number of lines of output - without the trailing '\n' +void print_int_array( int maxw, int nel, int *results, char sep, FILE *out ) +{ + int linelen = 0; + for( int i=0; i maxw ) + { + fputc( '\n', out ); + linelen = 0; + } else if( i>0 ) + { + fputc( ' ', out ); + linelen++; + } + + linelen += len; + fprintf( out, "%s", buf ); + if( i0 ) + //{ + // fputc( '\n', out ); + //} +} diff --git a/challenge-187/duncan-c-white/C/printarray.h b/challenge-187/duncan-c-white/C/printarray.h new file mode 100644 index 0000000000..40efb83277 --- /dev/null +++ b/challenge-187/duncan-c-white/C/printarray.h @@ -0,0 +1 @@ +extern void print_int_array( int maxw, int nel, int * results, char sep, FILE * out ); diff --git a/challenge-187/duncan-c-white/README b/challenge-187/duncan-c-white/README index 44c69614fa..ce8d8f7676 100644 --- a/challenge-187/duncan-c-white/README +++ b/challenge-187/duncan-c-white/README @@ -1,40 +1,89 @@ -Task 1: Zip List +Task 1: Days Together -You are given two list @a and @b of same size. -Create a subroutine sub zip(@a, @b) that merge the two list as shown in -the example below. +Two friends, Foo and Bar gone on holidays seperately to the same city. You +are given their schedule i.e. start date and end date. -Example +To keep the task simple, the date is in the form DD-MM and all dates +belong to the same calendar year i.e. between 01-01 and 31-12. Also the +year is non-leap year and both dates are inclusive. -Input: @a = qw/1 2 3/; @b = qw/a b c/; -Output: zip(@a, @b) should return qw/1 a 2 b 3 c/; - zip(@b, @a) should return qw/a 1 b 2 c 3/; +Write a script to find out for the given schedule, how many days they +spent together in the city, if at all. +Example 1 + +Input: Foo => SD: '12-01' ED: '20-01' + Bar => SD: '15-01' ED: '18-01' + +Output: 4 days + +Example 2 + +Input: Foo => SD: '02-03' ED: '12-03' + Bar => SD: '13-03' ED: '14-03' + +Output: 0 day + +Example 3 + +Input: Foo => SD: '02-03' ED: '12-03' + Bar => SD: '11-03' ED: '15-03' + +Output: 2 days -MY NOTES: very easy, except for the fact that a Perl subroutine CAN'T -take 2 arrays. Guess he meant array-refs? +Example 4 + +Input: Foo => SD: '30-03' ED: '05-04' + Bar => SD: '28-03' ED: '02-04' + +Output: 4 days + +MY NOTES: pretty easy. Let's do it by hand (no Date modules to inc-date) +given all the constraints, same year, non-leap year. GUEST LANGUAGE: As a bonus, I also had a go at translating ch-1.pl -into C (look in the C directory for that). Of course, that could -only deal with lists of integers, so the examples above have to change. +into C (look in the C directory for that). + + +Task 2: Magical Triplets +You are given a list of positive numbers, @n, having at least 3 numbers. -Task 2: Unicode Makeover +Write a script to find the triplets (a, b, c) from the given list that +satisfies the following rules. -You are given a string with possible unicode characters. -Create a subroutine sub makeover($str) that replace the unicode characters with ascii equivalent. For this task, let us assume it only contains alphabets. +1. a + b > c +2. b + c > a +3. a + c > b +4. a + b + c is maximum. + +In case, you end up with more than one triplets having the maximum then +pick the triplet where a >= b >= c. Example 1 -Input: $str = 'ÃÊÍÒÙ'; -Output: 'AEIOU' + Input: @n = (1, 2, 3, 2); + Output: (3, 2, 2) Example 2 -Input: $str = 'âÊíÒÙ'; -Output: 'aEiOU' + Input: @n = (1, 3, 2); + Output: () + +Example 3 + + Input: @n = (1, 1, 2, 3); + Output: () + +Example 4 + + Input: @n = (2, 4, 3); + Output: (4, 3, 2) +MY NOTES: Ok, sounds like generate+test. Find all triples. Find +triples that pass tests (1)..(3). Then find which triples have the +maximum sum. If only, that's the answer. If more than one, use the +tie break rule. -MY NOTES: Unicode: just say no - hell no. -My terminal doesn't even display the horrible input strings right. -I'm not doing this. Forget it. +GUEST LANGUAGE: As a bonus, I also had a go at translating ch-2.pl +into C (look in the C directory for that). diff --git a/challenge-187/duncan-c-white/perl/ch-1.pl b/challenge-187/duncan-c-white/perl/ch-1.pl new file mode 100755 index 0000000000..4de13bf986 --- /dev/null +++ b/challenge-187/duncan-c-white/perl/ch-1.pl @@ -0,0 +1,127 @@ +#!/usr/bin/perl +# +# Task 1: Days Together +# +# Two friends, Foo and Bar gone on holidays seperately to the same city. You +# are given their schedule i.e. start date and end date. +# +# To keep the task simple, the date is in the form DD-MM and all dates +# belong to the same calendar year i.e. between 01-01 and 31-12. Also the +# year is non-leap year and both dates are inclusive. +# +# Write a script to find out for the given schedule, how many days they +# spent together in the city, if at all. +# +# Example 1 +# +# Input: Foo => SD: '12-01' ED: '20-01' +# Bar => SD: '15-01' ED: '18-01' +# +# Output: 4 days +# +# Example 2 +# +# Input: Foo => SD: '02-03' ED: '12-03' +# Bar => SD: '13-03' ED: '14-03' +# +# Output: 0 day +# +# Example 3 +# +# Input: Foo => SD: '02-03' ED: '12-03' +# Bar => SD: '11-03' ED: '15-03' +# +# Output: 2 days +# +# Example 4 +# +# Input: Foo => SD: '30-03' ED: '05-04' +# Bar => SD: '28-03' ED: '02-04' +# +# Output: 4 days +# +# MY NOTES: pretty easy. Let's do it by hand (no Date modules to inc-date) +# given all the constraints, same year, non-leap year. +# +# GUEST LANGUAGE: As a bonus, I also had a go at translating ch-1.pl +# into C (look in the C directory for that). +# + +use strict; +use warnings; +use feature 'say'; +use feature 'state'; +use Getopt::Long; +use Data::Dumper; +use List::Util qw(min max); +use Function::Parameters; + + +my $debug=0; +die "Usage: overlapping-days [--debug] dd-mm-sd1 dd-mm-ed1 dd-mm-sd2 dd-mm-ed2\n" + unless GetOptions( "debug"=>\$debug ) && @ARGV==4; + + +my @dim = ( -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ); + +=pod + +=head2 my $day_in_year = yearday( $ddmm ); + +Check whether $ddmm is a valid date of format dd-mm where dd is 1..31 +and mm is 1..12 (and dd <= days_in_month(mm)), returning the day number +in the year if it is, or -1 if it is invalid. + +=cut +fun yearday( $ddmm ) +{ + return -1 unless $ddmm =~ /^(\d\d?)-(\d\d?)$/; + my( $d, $m ) = ( $1, $2 ); + return -1 if $m < 1 || $m > 12; + return -1 if $d < 1 || $d > $dim[$m]; + my $dayno = 0; + for( my $i=1; $i<$m; $i++ ) + { + $dayno += $dim[$i]; + } + $dayno += $d; + return $dayno; +} + + +my( $sd1, $ed1, $sd2, $ed2 ) = @ARGV; +my $sd1d = yearday( $sd1 ); # days since start of year for sd1 +die "Bad dd-mm-sd1 ($sd1)\n" if $sd1d<1; +my $ed1d = yearday( $ed1 ); +die "Bad dd-mm-ed1 ($ed1)\n" if $ed1d<1; +my $sd2d = yearday( $sd2 ); +die "Bad dd-mm-sd2 ($sd2)\n" if $sd2d<1; +my $ed2d = yearday( $ed2 ); +die "Bad dd-mm-ed2 ($ed2)\n" if $ed2d<1; + +say "sd1:$sd1d, ed1:$ed1d, sd2:$sd2d, ed2:$ed2d"; + + +=pod + +=head2 my $noverlap = overlapdays( $sd1d, $ed1d, $sd2d, $ed2d ); + +Find out the number of overlapping days between the two ranges +of dates, as the task describes. Each date is represented by a logical +day-number-in-the-year. Return 0 if no overlap. + +=cut +fun overlapdays( $sd1d, $ed1d, $sd2d, $ed2d ) +{ + # none if one range finishes before the other + return 0 if $ed1d < $sd2d || $ed2d < $sd1d; + + my $csd = max($sd1d,$sd2d); # common start date + my $ced = min($ed1d,$ed2d); # common end date + + return 1+$ced-$csd; +} + + +my $noverlap = overlapdays( $sd1d, $ed1d, $sd2d, $ed2d ); +say "$noverlap days"; diff --git a/challenge-187/duncan-c-white/perl/ch-2.pl b/challenge-187/duncan-c-white/perl/ch-2.pl new file mode 100755 index 0000000000..04e0ffe055 --- /dev/null +++ b/challenge-187/duncan-c-white/perl/ch-2.pl @@ -0,0 +1,114 @@ +#!/usr/bin/perl +# +# Task 2: Magical Triplets +# +# You are given a list of positive numbers, @n, having at least 3 numbers. +# +# Write a script to find the triplets (a, b, c) from the given list that +# satisfies the following rules. +# +# 1. a + b > c +# 2. b + c > a +# 3. a + c > b +# 4. a + b + c is maximum. +# +# In case, you end up with more than one triplets having the maximum then +# pick the triplet where a >= b >= c. +# +# Example 1 +# +# Input: @n = (1, 2, 3, 2); +# Output: (3, 2, 2) +# +# Example 2 +# +# Input: @n = (1, 3, 2); +# Output: () +# +# Example 3 +# +# Input: @n = (1, 1, 2, 3); +# Output: () +# +# Example 4 +# +# Input: @n = (2, 4, 3); +# Output: (4, 3, 2) +# +# MY NOTES: Ok, sounds like generate+test. Find all triples. Find +# triples that pass tests (1)..(3). Then find which triples have the +# maximum sum. If only, that's the answer. If more than one, use the +# tie break rule. +# +# GUEST LANGUAGE: As a bonus, I also had a go at translating ch-2.pl +# into C (look in the C directory for that). +# + +use strict; +use warnings; +use feature 'say'; +use feature 'state'; +use Getopt::Long; +use Data::Dumper; + + +my $debug=0; +die "Usage: magic-triple [--debug] csvlist\n" + unless GetOptions( "debug"=>\$debug ) && @ARGV==1; + +my $csvlist = shift; +my @x = split( /,/, $csvlist ); + +die "magic-triple: csvlist $csvlist must contain at least 3 numbers\n" + unless @x>2; + +# pass 1 - generate all triples of 3 distinct elements in @x (in any order) +# and find those triples that pass rules (1)..(3) + +my %seentriple; # a+b+c triples we've already seen + # (only needed because of duplicate elements) + +foreach my $p1 (0..$#x) +{ + foreach my $p2 (0..$#x) + { + next if $p1==$p2; + foreach my $p3 (0..$#x) + { + next if $p1==$p3 || $p2==$p3; + my $a = $x[$p1]; + my $b = $x[$p2]; + my $c = $x[$p3]; + next unless $a + $b > $c; + next unless $b + $c > $a; + next unless $a + $c > $b; + next if $seentriple{"$a+$b+$c"}++; + say "1..3 semi-magic triple $a, $b, $c" if $debug; + } + } +} + +my @p1t = sort keys %seentriple; + +# if there are NO triplets found obeying rules 1..3, report failure +if( @p1t == 0 ) +{ + say "No magic triplets found"; + exit 0; +} + +# pass 2: sort the triples by their sum into @st, then extract those (at +# the front of @st now) with the maximum sum. +my @st = sort { $b->[0] <=> $a->[0] } map { [ eval($_), $_ ] } @p1t; +my $maxval = $st[0]->[0]; +my @maxsumt = map { $st[$_]->[1] } grep { $st[$_]->[0] == $maxval } 0..$#st; + +# pass 3: identify which of those triples has a>=b>=c +foreach my $t (@maxsumt) +{ + $t =~ /^(\d+)\+(\d+)\+(\d+)$/; + my( $a, $b, $c ) = ( $1, $2, $3 ); + next unless $a>=$b && $b>=$c; + $t =~ s/\+/, /g; + say "Found magic triple $t"; +} -- cgit From 7571ef68a4764f5f6bfd9eb3f50612a72996b210 Mon Sep 17 00:00:00 2001 From: Mohammad S Anwar Date: Mon, 24 Oct 2022 00:50:57 +0100 Subject: - Added solutions by Arne Sommer. --- stats/pwc-current.json | 407 +- stats/pwc-language-breakdown-summary.json | 76 +- stats/pwc-language-breakdown.json | 7366 ++++++++++++++--------------- stats/pwc-leaders.json | 400 +- stats/pwc-summary-1-30.json | 44 +- stats/pwc-summary-121-150.json | 108 +- stats/pwc-summary-151-180.json | 100 +- stats/pwc-summary-181-210.json | 100 +- stats/pwc-summary-211-240.json | 100 +- stats/pwc-summary-241-270.json | 50 +- stats/pwc-summary-271-300.json | 56 +- stats/pwc-summary-31-60.json | 28 +- stats/pwc-summary-61-90.json | 100 +- stats/pwc-summary-91-120.json | 34 +- stats/pwc-summary.json | 50 +- 15 files changed, 4519 insertions(+), 4500 deletions(-) diff --git a/stats/pwc-current.json b/stats/pwc-current.json index 51d5518ad4..59d536d2ac 100644 --- a/stats/pwc-current.json +++ b/stats/pwc-current.json @@ -1,156 +1,23 @@ { - "title" : { - "text" : "The Weekly Challenge - 187" - }, - "chart" : { - "type" : "column" - }, - "legend" : { - "enabled" : 0 - }, - "series" : [ - { - "name" : "The Weekly Challenge - 187", - "data" : [ - { - "name" : "Athanasius", - "drilldown" : "Athanasius", - "y" : 4 - }, - { - "y" : 1, - "drilldown" : "Cheok-Yin Fung", - "name" : "Cheok-Yin Fung" - }, - { - "name" : "Colin Crain", - "y" : 1, - "drilldown" : "Colin Crain" - }, - { - "y" : 2, - "drilldown" : "E. Choroba", - "name" : "E. Choroba" - }, - { - "drilldown" : "Flavio Poletti", - "y" : 6, - "name" : "Flavio Poletti" - }, - { - "name" : "Humberto Massa", - "y" : 2, - "drilldown" : "Humberto Massa" - }, - { - "name" : "izem", - "y" : 2, - "drilldown" : "izem" - }, - { - "y" : 3, - "drilldown" : "James Smith", - "name" : "James Smith" - }, - { - "y" : 2, - "drilldown" : "Jorg Sommrey", - "name" : "Jorg Sommrey" - }, - { - "name" : "Luca Ferrari", - "y" : 8, - "drilldown" : "Luca Ferrari" - }, - { - "drilldown" : "Mark Anderson", - "y" : 2, - "name" : "Mark Anderson" - }, - { - "drilldown" : "Matthew Neleigh", - "y" : 2, - "name" : "Matthew Neleigh" - }, - { - "name" : "Mohammad S Anwar", - "drilldown" : "Mohammad S Anwar", - "y" : 4 - }, - { - "y" : 2, - "drilldown" : "Niels van Dijke", - "name" : "Niels van Dijke" - }, - { - "name" : "Peter Campbell Smith", - "drilldown" : "Peter Campbell Smith", - "y" : 3 - }, - { - "y" : 4, - "drilldown" : "Robert DiCicco", - "name" : "Robert DiCicco" - }, - { - "y" : 2, - "drilldown" : "Robert Ransbottom", - "name" : "Robert Ransbottom" - }, - { - "drilldown" : "Roger Bell_West", - "y" : 5, - "name" : "Roger Bell_West" - }, - { - "name" : "Simon Green", - "y" : 3, - "drilldown" : "Simon Green" - }, - { - "y" : 2, - "drilldown" : "Solathian", - "name" : "Solathian" - }, - { - "y" : 5, - "drilldown" : "Stephen G. Lynn", - "name" : "Stephen G. Lynn" - }, - { - "name" : "Tim Potapov", - "drilldown" : "Tim Potapov", - "y" : 2 - }, - { - "name" : "Ulrich Rieke", - "drilldown" : "Ulrich Rieke", - "y" : 3 - }, - { - "name" : "W. Luis Mochan", - "drilldown" : "W. Luis Mochan", - "y" : 3 - } - ], - "colorByPoint" : 1 - } - ], - "yAxis" : { - "title" : { - "text" : "Total Solutions" - } - }, - "tooltip" : { - "followPointer" : 1, - "pointFormat" : "{point.name}: {point.y:f}
", - "headerFormat" : "{series.name}
" - }, "drilldown" : { "series" : [ { - "name" : "Athanasius", + "id" : "Arne Sommer", + "name" : "Arne Sommer", + "data" : [ + [ + "Raku", + 2 + ], + [ + "Blog", + 1 + ] + ] + }, + { "id" : "Athanasius", + "name" : "Athanasius", "data" : [ [ "Perl", @@ -169,28 +36,28 @@ 1 ] ], - "id" : "Cheok-Yin Fung", - "name" : "Cheok-Yin Fung" + "name" : "Cheok-Yin Fung", + "id" : "Cheok-Yin Fung" }, { "id" : "Colin Crain", - "name" : "Colin Crain", "data" : [ [ "Perl", 1 ] - ] + ], + "name" : "Colin Crain" }, { - "id" : "E. Choroba", "name" : "E. Choroba", "data" : [ [ "Perl", 2 ] - ] + ], + "id" : "E. Choroba" }, { "data" : [ @@ -207,28 +74,28 @@ 2 ] ], - "id" : "Flavio Poletti", - "name" : "Flavio Poletti" + "name" : "Flavio Poletti", + "id" : "Flavio Poletti" }, { - "id" : "Humberto Massa", - "name" : "Humberto Massa", "data" : [ [ "Raku", 2 ] - ] + ], + "name" : "Humberto Massa", + "id" : "Humberto Massa" }, { + "id" : "izem", "data" : [ [ "Perl", 2 ] ], - "name" : "izem", - "id" : "izem" + "name" : "izem" }, { "data" : [ @@ -245,18 +112,18 @@ "id" : "James Smith" }, { + "id" : "Jorg Sommrey", + "name" : "Jorg Sommrey", "data" : [ [ "Perl", 2 ] - ], - "id" : "Jorg Sommrey", - "name" : "Jorg Sommrey" + ] }, { - "name" : "Luca Ferrari", "id" : "Luca Ferrari", + "name" : "Luca Ferrari", "data" : [ [ "Raku", @@ -270,22 +137,22 @@ }, { "name" : "Mark Anderson", - "id" : "Mark Anderson", "data" : [ [ "Raku", 2 ] - ] + ], + "id" : "Mark Anderson" }, { + "name" : "Matthew Neleigh", "data" : [ [ "Perl", 2 ] ], - "name" : "Matthew Neleigh", "id" : "Matthew Neleigh" }, { @@ -303,17 +170,16 @@ "id" : "Mohammad S Anwar" }, { + "id" : "Niels van Dijke", "data" : [ [ "Perl", 2 ] ], - "id" : "Niels van Dijke", "name" : "Niels van Dijke" }, { - "id" : "Peter Campbell Smith", "name" : "Peter Campbell Smith", "data" : [ [ @@ -324,7 +190,8 @@ "Blog", 1 ] - ] + ], + "id" : "Peter Campbell Smith" }, { "data" : [ @@ -337,22 +204,21 @@ 2 ] ], - "id" : "Robert DiCicco", - "name" : "Robert DiCicco" + "name" : "Robert DiCicco", + "id" : "Robert DiCicco" }, { - "name" : "Robert Ransbottom", - "id" : "Robert Ransbottom", "data" : [ [ "Raku", 2 ] - ] + ], + "name" : "Robert Ransbottom", + "id" : "Robert Ransbottom" }, { "name" : "Roger Bell_West", - "id" : "Roger Bell_West", "data" : [ [ "Perl", @@ -366,9 +232,11 @@ "Blog", 1 ] - ] + ], + "id" : "Roger Bell_West" }, { + "id" : "Simon Green", "data" : [ [ "Perl", @@ -379,22 +247,20 @@ 1 ] ], - "id" : "Simon Green", "name" : "Simon Green" }, { + "id" : "Solathian", "data" : [ [ "Perl", 2 ] ], - "id" : "Solathian", "name" : "Solathian" }, { "name" : "Stephen G. Lynn", - "id" : "Stephen G. Lynn", "data" : [ [ "Perl", @@ -408,11 +274,12 @@ "Blog", 1 ] - ] + ], + "id" : "Stephen G. Lynn" }, { - "name" : "Tim Potapov", "id" : "Tim Potapov", + "name" : "Tim Potapov", "data" : [ [ "Perl", @@ -431,12 +298,11 @@ 2 ] ], - "id" : "Ulrich Rieke", - "name" : "Ulrich Rieke" + "name" : "Ulrich Rieke", + "id" : "Ulrich Rieke" }, { "id" : "W. Luis Mochan", - "name" : "W. Luis Mochan", "data" : [ [ "Perl", @@ -446,23 +312,176 @@ "Blog", 1 ] - ] + ], + "name" : "W. Luis Mochan" } ] }, - "xAxis" : { - "type" : "category" + "tooltip" : { + "followPointer" : 1, + "headerFormat" : "{series.name}
", + "pointFormat" : "{point.name}: {point.y:f}
" + }, + "title" : { + "text" : "The Weekly Challenge - 187" }, "plotOptions" : { "series" : { + "borderWidth" : 0, "dataLabels" : { - "format" : "{point.y}", - "enabled" : 1 - }, - "borderWidth" : 0 + "enabled" : 1, + "format" : "{point.y}" + } } }, + "legend" : { + "enabled" : 0 + }, + "chart" : { + "type" : "column" + }, + "series" : [ + { + "colorByPoint" : 1, + "name" : "The Weekly Challenge - 187", + "data" : [ + { + "y" : 3, + "name" : "Arne Sommer", + "drilldown" : "Arne Sommer" + }, + { + "name" : "Athanasius", + "y" : 4, + "drilldown" : "Athanasius" + }, + { + "drilldown" : "Cheok-Yin Fung", + "y" : 1, + "name" : "Cheok-Yin Fung" + }, + { + "y" : 1, + "name" : "Colin Crain", + "drilldown" : "Colin Crain" + }, + { + "name" : "E. Choroba", + "y" : 2, + "drilldown" : "E. Choroba" + }, + { + "y" : 6, + "name" : "Flavio Poletti", + "drilldown" : "Flavio Poletti" + }, + { + "name" : "Humberto Massa", + "y" : 2, + "drilldown" : "Humberto Massa" + }, + { + "name" : "izem", + "y" : 2, + "drilldown" : "izem" + }, + { + "y" : 3, + "name" : "James Smith", + "drilldown" : "James Smith" + }, + { + "drilldown" : "Jorg Sommrey", + "y" : 2, + "name" : "Jorg Sommrey" + }, + { + "drilldown" : "Luca Ferrari", + "name" : "Luca Ferrari", + "y" : 8 +