aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYozen Hernandez <yzhernand@gmail.com>2019-07-14 18:18:18 -0400
committerYozen Hernandez <yzhernand@gmail.com>2019-07-14 18:18:18 -0400
commit48b60a25ce24c5f086d610f72daf686e57f822fe (patch)
tree8ad6146f4bd6b6d2c907242a38ced4455976b6f6
parentea3a62e5bb2fe9dbacd3cd0d990fcf1f070ed517 (diff)
downloadperlweeklychallenge-club-48b60a25ce24c5f086d610f72daf686e57f822fe.tar.gz
perlweeklychallenge-club-48b60a25ce24c5f086d610f72daf686e57f822fe.tar.bz2
perlweeklychallenge-club-48b60a25ce24c5f086d610f72daf686e57f822fe.zip
Added solutions by Yozen Hernandez for challenges 1 and 2 for week 16
-rw-r--r--challenge-016/yozen-hernandez/blog.txt1
-rw-r--r--challenge-016/yozen-hernandez/blog1.txt1
-rwxr-xr-xchallenge-016/yozen-hernandez/perl5/ch-1.pl76
-rwxr-xr-xchallenge-016/yozen-hernandez/perl5/ch-2.pl65
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' );