aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Pankoff <ccntrq@screenri.de>2021-11-24 18:40:37 +0100
committerAlexander Pankoff <ccntrq@screenri.de>2021-11-24 18:40:37 +0100
commitf689e98205eb99b05d49063e5b2b2eccbaca945a (patch)
treed82f057e9a6c8f197deab687c7b490aea1a95c68
parent9b2be2ba1121ac6a5ea2ec93374a8beb846e2b19 (diff)
downloadperlweeklychallenge-club-f689e98205eb99b05d49063e5b2b2eccbaca945a.tar.gz
perlweeklychallenge-club-f689e98205eb99b05d49063e5b2b2eccbaca945a.tar.bz2
perlweeklychallenge-club-f689e98205eb99b05d49063e5b2b2eccbaca945a.zip
Add operator overloading to challenge 140-01
-rw-r--r--challenge-140/alexander-pankoff/perl/ch-1.pl87
1 files changed, 61 insertions, 26 deletions
diff --git a/challenge-140/alexander-pankoff/perl/ch-1.pl b/challenge-140/alexander-pankoff/perl/ch-1.pl
index 37981f5430..139791fb6b 100644
--- a/challenge-140/alexander-pankoff/perl/ch-1.pl
+++ b/challenge-140/alexander-pankoff/perl/ch-1.pl
@@ -3,7 +3,8 @@ use warnings;
use feature qw'say signatures';
no warnings 'experimental::signatures';
-use List::Util qw(max);
+use Carp;
+use List::Util;
run() unless caller();
@@ -12,43 +13,77 @@ sub run() {
my $b = prompt_for_binary('b');
say "Result:";
- say( add_binarys( $a, $b ) );
+ say Binary->new($a) + $b;
+}
+sub prompt_for_binary($name) {
+ say "Enter binary number $name";
+ chomp( my $number = <STDIN> );
+
+ if ( $number !~ m/^[01]+$/ ) {
+ say "Invalid binary number.";
+ return prompt_for_binary($name);
+ }
+
+ return $number;
}
-sub add_binarys ( $a, $b ) {
+package Binary {
+ use overload '+' => 'add';
+ use overload '""' => sub { ${ shift() } };
- my @a_digits = reverse split( '', $a );
- my @b_digits = reverse split( '', $b );
+ sub new ( $class, $number ) {
+ if ( $number !~ m/^[01]+$/ ) {
+ Carp::confess("Invalid binary number: $number");
+ }
- # we walk the digits of the binary numbers starting with the least
- # significant digit, add the digits individually, carry the carry around
- # with us and build our result from the back
- my ( $out, $carry ) = ( '', 0 );
- for ( 0 .. max( $#a_digits, $#b_digits ) ) {
- my $res;
- ( $res, $carry ) =
- add_binary_digits( $a_digits[$_] // 0, $b_digits[$_] // 0, $carry );
- $out = $res . $out;
+ return bless \$number, $class;
}
- return $carry ? $carry . $out : $out;
+ sub add {
+ my ( $self, $other ) = @_;
+ if ( ref $other ) {
+ if ( UNIVERSAL::isa( $other, ref $self ) ) {
+ return Binary->new(
+ BinaryUtil::add_binarys( ${$self}, ${other} ) );
+ }
+ else {
+ Carp::confess( "Can't add a ", ref $other, " to a ",
+ ref $self );
+ }
+ }
+ else {
+ $self->add( Binary->new($other) );
+ }
+ }
}
-sub add_binary_digits ( $a, $b, $carry ) {
- my $c = $a + $b + $carry;
+package BinaryUtil {
- return $c >= 3 ? ( 1, 1 ) : $c == 2 ? ( 0, 1 ) : ( $c, 0 );
+ sub add_binarys ( $a, $b ) {
-}
+ my @a_digits = reverse split( '', $a );
+ my @b_digits = reverse split( '', $b );
+
+ # we walk the digits of the binary numbers starting with the least
+ # significant digit, add the digits individually, carry the carry around
+ # with us and build our result from the back
+ my ( $out, $carry ) = ( '', 0 );
+ for ( 0 .. List::Util::max( $#a_digits, $#b_digits ) ) {
+ my $res;
+ ( $res, $carry ) = add_binary_digits( $a_digits[$_] // 0,
+ $b_digits[$_] // 0, $carry );
+ $out = $res . $out;
+ }
+
+ return $carry ? $carry . $out : $out;
+ }
+
+ sub add_binary_digits ( $a, $b, $carry ) {
+ my $c = $a + $b + $carry;
+
+ return $c >= 3 ? ( 1, 1 ) : $c == 2 ? ( 0, 1 ) : ( $c, 0 );
-sub prompt_for_binary($name) {
- say "Enter binary number $name";
- chomp( my $number = <STDIN> );
- if ( $number !~ m/^[01]+$/ ) {
- say "Invalid binary number.";
- return prompt_for_binary($name);
}
- return $number;
}