diff options
| author | Mohammad S Anwar <Mohammad.Anwar@yahoo.com> | 2019-07-14 23:29:11 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-07-14 23:29:11 +0100 |
| commit | 854b911434e4bd4e334fc0c6ebe3ae2a995c044f (patch) | |
| tree | db7b976e54245bf0ceb5ac11345ace7e2b11f96c | |
| parent | 84a5bb4ee385c8b1bf1c5df7ffe924266d520fca (diff) | |
| parent | 48b60a25ce24c5f086d610f72daf686e57f822fe (diff) | |
| download | perlweeklychallenge-club-854b911434e4bd4e334fc0c6ebe3ae2a995c044f.tar.gz perlweeklychallenge-club-854b911434e4bd4e334fc0c6ebe3ae2a995c044f.tar.bz2 perlweeklychallenge-club-854b911434e4bd4e334fc0c6ebe3ae2a995c044f.zip | |
Merge pull request #375 from yzhernand/ch-016-yozen
Added solutions by Yozen Hernandez for challenges 1 and 2 for week 16
| -rw-r--r-- | challenge-016/yozen-hernandez/blog.txt | 1 | ||||
| -rw-r--r-- | challenge-016/yozen-hernandez/blog1.txt | 1 | ||||
| -rwxr-xr-x | challenge-016/yozen-hernandez/perl5/ch-1.pl | 76 | ||||
| -rwxr-xr-x | challenge-016/yozen-hernandez/perl5/ch-2.pl | 65 |
4 files changed, 143 insertions, 0 deletions
diff --git a/challenge-016/yozen-hernandez/blog.txt b/challenge-016/yozen-hernandez/blog.txt new file mode 100644 index 0000000000..1ddbec47c1 --- /dev/null +++ b/challenge-016/yozen-hernandez/blog.txt @@ -0,0 +1 @@ +https://yzhernand.github.io/posts/perl-weekly-challenge-16-1/ diff --git a/challenge-016/yozen-hernandez/blog1.txt b/challenge-016/yozen-hernandez/blog1.txt new file mode 100644 index 0000000000..ebd8a5e82a --- /dev/null +++ b/challenge-016/yozen-hernandez/blog1.txt @@ -0,0 +1 @@ +https://yzhernand.github.io/posts/perl-weekly-challenge-16-2/ diff --git a/challenge-016/yozen-hernandez/perl5/ch-1.pl b/challenge-016/yozen-hernandez/perl5/ch-1.pl new file mode 100755 index 0000000000..659da45c52 --- /dev/null +++ b/challenge-016/yozen-hernandez/perl5/ch-1.pl @@ -0,0 +1,76 @@ +#!/usr/bin/env perl + +use v5.24; +use strict; +use warnings; +use feature qw(signatures); +no warnings "experimental::signatures"; +use Benchmark::Forking qw(cmpthese); + +# Pythagoras Pie Puzzle, proposed by Jo Christian Oterhals. + +# At a party a pie is to be shared by 100 guest. The first guest gets 1% of the +# pie, the second guest gets 2% of the remaining pie, the third gets 3% of the +# remaining pie, the fourth gets 4% and so on. + +# Write a script that figures out which guest gets the largest piece of pie. + +sub list_pie_remaining { + + # Other guests get a percent of the remaining 99/100: + # 99/100*(2/100) for the second, leaving (99/100)*(98/100) + # for the third guest, and so on... + # So lets just generate a list with the amount of pie left + # for each guest + my @remaining_pie = (1); + + # my @pie_shares = (1/100); + my %largest_piece = ( guest => -1, size => 0 ); + + for my $i ( 1 .. 99 ) { + push @remaining_pie, ( ( 100 - $i ) / 100 ) * $remaining_pie[-1]; + + ( ( $remaining_pie[-2] - $remaining_pie[-1] ) > $largest_piece{size} ) + ? @largest_piece{ "guest", "size" } + = ( $i, $remaining_pie[-2] - $remaining_pie[-1] ) + : next; + + # push @pie_pieces, $remaining_pie[-2]-$remaining_pie[-1]; + } + + return \%largest_piece; +} + +sub track_last_piece { + my $remaining_pie = 1; + my $last_piece = 0; + + for my $i ( 1 .. 100 ) { + my $new_piece + = $remaining_pie - ( ( 100 - $i ) / 100 ) * $remaining_pie; + + if ( $new_piece < $last_piece ) { + return { guest => ( $i - 1 ), size => $last_piece }; + } + + $last_piece = $new_piece; + $remaining_pie -= $new_piece; + } + + return undef; +} + +use Test::More tests => 2; +is(list_pie_remaining()->{guest}, 10, "10th guest gets the largest piece of the pie (using list)"); +is(track_last_piece()->{guest}, 10, "10th guest gets the largest piece of the pie (last only)"); + +cmpthese( + -10, + { 'list_pie_remaining' => \&list_pie_remaining, + 'track_last_piece' => \&track_last_piece + } +); + +# Rate list_pie_remaining track_last_share +# list_pie_remaining 43203/s -- -88% +# track_last_piece 368816/s 754% --
\ No newline at end of file diff --git a/challenge-016/yozen-hernandez/perl5/ch-2.pl b/challenge-016/yozen-hernandez/perl5/ch-2.pl new file mode 100755 index 0000000000..930b493af0 --- /dev/null +++ b/challenge-016/yozen-hernandez/perl5/ch-2.pl @@ -0,0 +1,65 @@ +#!/usr/bin/env perl + +use v5.24; +use strict; +use warnings; +use feature qw(signatures); +no warnings "experimental::signatures"; +use Carp; +use Digest::SHA qw(sha256); +use Math::BigInt try => 'GMP'; + +# Write a script to validate a given bitcoin address. Most Bitcoin addresses are +# 34 characters. They consist of random digits and uppercase and lowercase +# letters, with the exception that the uppercase letter “O”, uppercase letter +# “I”, lowercase letter “l”, and the number “0” are never used to prevent visual +# ambiguity. A bitcoin address encodes 25 bytes. The last four bytes are a +# checksum check. They are the first four bytes of a double SHA-256 digest of +# the previous 21 bytes. For more information, please refer wiki page. Here are +# some valid bitcoin addresses: + +# 1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2 +# 3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy + +my @b58_chars = split //, + '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; +my %b58 = map { $b58_chars[$_] => $_ } ( 0 .. 57 ); + +sub b58_decode ($btc_addr) { + my $val = Math::BigInt->new(); + my $base = Math::BigInt->new(58); + my @btc_arr = reverse split( //, $btc_addr ); + + while ( my ( $i, $v ) = each @btc_arr ) { + croak("Invalid bitcoin address") unless (exists $b58{$v}); + $val = $base->copy()->bpow($i)->bmuladd($b58{$v}, $val); + } + + # Decode value to bytes + my $decoded = $val->to_bytes(); + + # 0-padding + $decoded = (chr(0) x (25-length($decoded))) . $decoded; + return $decoded; +} + +sub btc_valid ($btc_addr) { + # return undef unless ( $btc_addr =~ m/[1-9a-km-zA-HJ-NP-Z]{26,34}/ ); + + my $decoded = b58_decode($btc_addr); + + # The last four bytes are a checksum check. They are the first four bytes of + # a double SHA-256 digest of the previous 21 bytes. + my $checksum = substr $decoded, -4; + my $data = substr $decoded, 0, 21; + + return ( $checksum eq substr(sha256( sha256($data) ), 0, 4) ) ? substr($decoded, 0, 1) : undef; +} + +use Test::More tests => 4; +is(unpack("H*", b58_decode('1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2')), lc'0077BFF20C60E522DFAA3350C39B030A5D004E839AF415766B', "b58 decode works"); +is(unpack("H*", b58_decode('3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy')), lc'05B472A266D0BD89C13706A4132CCFB16F7C3B9FCB81FCFC02', "b58 decode works"); +ok( defined btc_valid('1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2'), + 'First test address is valid' ); +ok( defined btc_valid('3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy'), + 'Second test address is valid' ); |
