diff options
| author | Mohammad S Anwar <Mohammad.Anwar@yahoo.com> | 2022-11-28 02:43:01 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-11-28 02:43:01 +0000 |
| commit | 4a0736675714e2285c79506fa53e85505d028ecb (patch) | |
| tree | fea6901812e8a38e1875ed5da3da8b2461b621d2 | |
| parent | bfd764e1bd9c861cd92064e74a327e9b80732e12 (diff) | |
| parent | 395ae0a74243c7e4a7aca93fb7bbf83675ce5dbc (diff) | |
| download | perlweeklychallenge-club-4a0736675714e2285c79506fa53e85505d028ecb.tar.gz perlweeklychallenge-club-4a0736675714e2285c79506fa53e85505d028ecb.tar.bz2 perlweeklychallenge-club-4a0736675714e2285c79506fa53e85505d028ecb.zip | |
Merge pull request #7167 from Util/branch-for-challenge-192
Add TWC 192 blog post and solutions by Bruce Gray (Raku, Perl, and Rust)
| -rw-r--r-- | challenge-192/bruce-gray/blog.txt | 1 | ||||
| -rw-r--r-- | challenge-192/bruce-gray/perl/ch-1.pl | 17 | ||||
| -rw-r--r-- | challenge-192/bruce-gray/perl/ch-2.pl | 65 | ||||
| -rw-r--r-- | challenge-192/bruce-gray/raku/ch-1.raku | 27 | ||||
| -rw-r--r-- | challenge-192/bruce-gray/raku/ch-2.raku | 54 | ||||
| -rw-r--r-- | challenge-192/bruce-gray/rust/ch-1.rs | 35 | ||||
| -rw-r--r-- | challenge-192/bruce-gray/rust/ch-2.rs | 73 |
7 files changed, 272 insertions, 0 deletions
diff --git a/challenge-192/bruce-gray/blog.txt b/challenge-192/bruce-gray/blog.txt new file mode 100644 index 0000000000..2bac4e7dde --- /dev/null +++ b/challenge-192/bruce-gray/blog.txt @@ -0,0 +1 @@ +http://blogs.perl.org/users/bruce_gray/2022/11/twc-192-frosting-a-cake-without-flipping-the-spatula.html diff --git a/challenge-192/bruce-gray/perl/ch-1.pl b/challenge-192/bruce-gray/perl/ch-1.pl new file mode 100644 index 0000000000..2197d0a95f --- /dev/null +++ b/challenge-192/bruce-gray/perl/ch-1.pl @@ -0,0 +1,17 @@ +use v5.36; +sub task1 ($n) { + return oct '0b' . sprintf('%b', $n) =~ tr/01/10/r; +} + + +my @tests = ( + [ 5, 2 ], + [ 4, 3 ], + [ 6, 1 ], +); +use Test::More; +plan tests => 0+@tests; +for (@tests) { + my ( $in, $expected ) = @{$_}; + is task1($in), $expected, "task1($in) == $expected"; +} diff --git a/challenge-192/bruce-gray/perl/ch-2.pl b/challenge-192/bruce-gray/perl/ch-2.pl new file mode 100644 index 0000000000..497d1c6930 --- /dev/null +++ b/challenge-192/bruce-gray/perl/ch-2.pl @@ -0,0 +1,65 @@ +use v5.36; +use List::Util qw<sum0 reductions>; +sub functional ( @a ) { + my $s = sum0 @a; + + return -1 if $s % @a; + my $target = $s / @a; + + return sum0 map { abs $_ } + reductions { $a + $b } + map { $_ - $target } + @a; +} +sub task2 ( @a ) { + return -1 if sum0(@a) % scalar(@a); + my $target = sum0(@a) / scalar(@a); + + my ($count, $mound) = 0, 0; + for my $n (@a) { + $mound += $n - $target; + $count += abs $mound; + } + + die "Cannot happen: $mound" unless $mound == 0; + + return $count; +} + +my @tests = ( + # Examples from task: + [ [1, 0, 5], 4 ], + [ [0, 2, 0], -1 ], + [ [0, 3, 0], 2 ], + + # Invented: + [ [4,0,0,0], 6], + [ [3,1,0,0], 5], + [ [3,0,1,0], 4], + [ [3,0,0,1], 3], + [ [2,2,0,0], 4], + [ [2,0,2,0], 2], + [ [2,0,0,2], 2], + [ [2,1,1,0], 3], + [ [2,1,0,1], 2], + [ [2,0,1,1], 1], + [ [1,1,1,1], 0], + [ [1,2,1,0], 2], + [ [1,2,0,1], 1], + [ [1,1,2,0], 1], + [ [1,1,0,2], 1], + + [ [2+(8*1000), 2, 2, 2, 2, 2, 2, 2], 1000*sum0(1..7) ], + [ [2, 2, 2, 2, 2, 2, 2, 2+(8*1000)], 1000*sum0(1..7) ], + [ [2, 2, 2, 2, 2, 2, 2+(8*1000), 2], 1000*sum0(1..6, 1) ], + + [ [6,3,3,3,3,0,3,3,3,3,0,1,3,3,3,6,5], 15+15+10], # For the blog post +); + +use Test::More; +plan tests => 2*@tests; +for (@tests) { + my ( $in_aref, $expected ) = @{$_}; + is task2(@{$in_aref}), $expected; + is functional(@{$in_aref}), $expected; +} diff --git a/challenge-192/bruce-gray/raku/ch-1.raku b/challenge-192/bruce-gray/raku/ch-1.raku new file mode 100644 index 0000000000..4af0b6a0ab --- /dev/null +++ b/challenge-192/bruce-gray/raku/ch-1.raku @@ -0,0 +1,27 @@ +# Faster, by about 10x +sub all_ones ( UInt $n --> UInt ) { ( 1 +< ($n.log2.floor + 1) ) - 1 } +sub fast1 ( UInt $n --> UInt ) { $n +^ all_ones($n) } + +# Clearer: +sub task1 ( UInt $n --> UInt ) { + return $n.base(2) + .trans( <0 1> => <1 0> ) + .parse-base(2); +} + + +my @tests = + ( 5, 2 ), + ( 4, 3 ), + ( 6, 1 ), +; +use Test; +plan +@tests + 1; +for @tests -> ( $in, $expected ) { + is task1($in), $expected, "task1($in) == $expected"; +} +{ + my Range $r = 1 .. (2 ** 14); + my Bool $ok = not defined first { .&task1 != .&fast1 }, $r.list; + ok $ok, "Two different approaches over {$r.raku}"; +} diff --git a/challenge-192/bruce-gray/raku/ch-2.raku b/challenge-192/bruce-gray/raku/ch-2.raku new file mode 100644 index 0000000000..afadbcea43 --- /dev/null +++ b/challenge-192/bruce-gray/raku/ch-2.raku @@ -0,0 +1,54 @@ +# Because I still have 60-characters-worth of residual evil left over from Halloween: +sub golfed(@a){(@a.sum!%%+@a)??-1!!([\+](@a X-(@a.sum div+@a)))».abs.sum} + +sub task2 ( @a --> Int ) { + return -1 if @a.sum !%% +@a; + + my $target = @a.sum div @a.elems; + + my ($count, $mound) = 0, 0; + for @a -> $a { + $mound += $a - $target; + $count += $mound.abs; + } + + die "Cannot happen: $mound" unless $mound == 0; + + return $count; +} + +my @tests = + # Examples from task: + ( (1, 0, 5), 4 ), + ( (0, 2, 0), -1 ), + ( (0, 3, 0), 2 ), + + # Invented: + ( (4,0,0,0), 6), + ( (3,1,0,0), 5), + ( (3,0,1,0), 4), + ( (3,0,0,1), 3), + ( (2,2,0,0), 4), + ( (2,0,2,0), 2), + ( (2,0,0,2), 2), + ( (2,1,1,0), 3), + ( (2,1,0,1), 2), + ( (2,0,1,1), 1), + ( (1,1,1,1), 0), + ( (1,2,1,0), 2), + ( (1,2,0,1), 1), + ( (1,1,2,0), 1), + ( (1,1,0,2), 1), + + ( (2+(8*1000), 2, 2, 2, 2, 2, 2, 2), 1000*(1..7).sum ), + ( (2, 2, 2, 2, 2, 2, 2, 2+(8*1000)), 1000*(1..7).sum ), + ( (2, 2, 2, 2, 2, 2, 2+(8*1000), 2), 1000*(|(1..6),1).sum ), + ( (6,3,3,3,3,0,3,3,3,3,0,1,3,3,3,6,5), 15+15+10), # For the blog post +; + +use Test; +plan 2*@tests; +for @tests -> ( $in, $expected ) { + is task2($in), $expected; + is golfed($in), $expected; +} diff --git a/challenge-192/bruce-gray/rust/ch-1.rs b/challenge-192/bruce-gray/rust/ch-1.rs new file mode 100644 index 0000000000..9a5a39be34 --- /dev/null +++ b/challenge-192/bruce-gray/rust/ch-1.rs @@ -0,0 +1,35 @@ +fn flip_bits(n: u32) -> u32 { + let all_ones = (n + 1).next_power_of_two() - 1; + + return n ^ all_ones; +} + +// Run with either of: +// rustc --test rust/ch-1.rs && ./ch-1 +// rustc rust/ch-1.rs && ./ch-1 99999 + +fn main() { + let n: u32 = std::env::args().nth(1).expect("missing command-line argument") + .parse().expect("failed to parse"); + + println!("flip_bits({}) == {}", n, flip_bits(n)); +} + +#[test]fn task_example_01() { assert_eq!(flip_bits( 5), 2) } +#[test]fn task_example_02() { assert_eq!(flip_bits( 4), 3) } +#[test]fn task_example_03() { assert_eq!(flip_bits( 6), 1) } +#[test]fn test_range_1_64() { + + let got: Vec<u32> = (1..(64+1)).map(flip_bits).collect(); + + assert_eq!(got, vec![ + 0, + 1, 0, + 3, 2, 1, 0, + 7, 6, 5, 4, 3, 2, 1, 0, + 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, + 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 63 + ]) +} diff --git a/challenge-192/bruce-gray/rust/ch-2.rs b/challenge-192/bruce-gray/rust/ch-2.rs new file mode 100644 index 0000000000..729c90d211 --- /dev/null +++ b/challenge-192/bruce-gray/rust/ch-2.rs @@ -0,0 +1,73 @@ +// Run with either of: +// rustc --test rust/ch-2.rs && ./ch-2 +// rustc rust/ch-2.rs && ./ch-2 3 6 3 + +fn task2 ( a : Vec<i32> ) -> i32 { + let sum : i32 = a.iter().sum(); + let len : i32 = a.len() as i32; + + if sum % len != 0 { + return -1; + } + + let target = sum / len; + + // Raku code: ( [\+] ( @a X- target ) )».abs.sum + return a.iter() + .scan(0, |state, &x| { *state += x - target; Some(*state) }) + .map(|x| { x.abs() }) + .sum(); +} + +fn main () { + let input : Vec<i32> = std::env::args() + .skip(1) + .map(|x| { x.parse::<i32>().unwrap() }) + .collect(); + + assert!( !input.is_empty(), "Error: Need integer arguments on the command-line" ); + + println!("task2({:?}) = {:?}", input.clone(), task2(input)); +} + +#[test]fn task_example_01() { assert_eq!(task2( vec![1, 0, 5] ), 4) } +#[test]fn task_example_02() { assert_eq!(task2( vec![0, 2, 0] ), -1) } +#[test]fn task_example_03() { assert_eq!(task2( vec![0, 3, 0] ), 2) } + +#[test]fn test_misc_01() { assert_eq!(task2( vec![4,0,0,0] ), 6) } +#[test]fn test_misc_02() { assert_eq!(task2( vec![3,1,0,0] ), 5) } +#[test]fn test_misc_03() { assert_eq!(task2( vec![3,0,1,0] ), 4) } +#[test]fn test_misc_04() { assert_eq!(task2( vec![3,0,0,1] ), 3) } +#[test]fn test_misc_05() { assert_eq!(task2( vec![2,2,0,0] ), 4) } +#[test]fn test_misc_06() { assert_eq!(task2( vec![2,0,2,0] ), 2) } +#[test]fn test_misc_07() { assert_eq!(task2( vec![2,0,0,2] ), 2) } +#[test]fn test_misc_08() { assert_eq!(task2( vec![2,1,1,0] ), 3) } +#[test]fn test_misc_09() { assert_eq!(task2( vec![2,1,0,1] ), 2) } +#[test]fn test_misc_10() { assert_eq!(task2( vec![2,0,1,1] ), 1) } +#[test]fn test_misc_11() { assert_eq!(task2( vec![1,1,1,1] ), 0) } +#[test]fn test_misc_12() { assert_eq!(task2( vec![1,2,1,0] ), 2) } +#[test]fn test_misc_13() { assert_eq!(task2( vec![1,2,0,1] ), 1) } +#[test]fn test_misc_14() { assert_eq!(task2( vec![1,1,2,0] ), 1) } +#[test]fn test_misc_15() { assert_eq!(task2( vec![1,1,0,2] ), 1) } + +#[test]fn test_large_01() { + let got = task2( vec![2 + (8*1000), 2, 2, 2, 2, 2, 2, 2] ); + let expected = 1000 * (1..(7+1)).sum::<i32>(); + assert_eq!(got, expected); +} +#[test]fn test_large_02() { + let got = task2( vec![2, 2, 2, 2, 2, 2, 2, 2 + (8*1000)] ); + let expected = 1000 * (1..(7+1)).sum::<i32>(); + assert_eq!(got, expected); +} +#[test]fn test_large_03() { + let got = task2( vec![2, 2, 2, 2, 2, 2, 2 + (8*1000), 2] ); + let expected = 1000 * (1+(1..(6+1)).sum::<i32>()); + assert_eq!(got, expected); +} + +#[test]fn for_blog_post_01() { + let got = task2( vec![6,3,3,3,3,0,3,3,3,3,0,1,3,3,3,6,5] ); + let expected = 15+15+10; + assert_eq!(got, expected); +} |
