RabbitFarm

2021-11-28

A Binary Addition Simulation / Nth from a Sorted Multiplication: Table The Weekly Challenge 140

The examples used here are from The Weekly Challenge problem statement and demonstrate the working solution.

Part 1

You are given two decimal-coded binary numbers, $a and $b. Write a script to simulate the addition of the given binary numbers.

Solution


use strict;
use warnings;
sub add_binary{
    my($x, $y) = @_;
    my $sum = ""; 
    my @a = reverse(split(//, $x));            
    my @b = reverse(split(//, $y));            
    if(@b > @a){
        my @c = @b;
        @b = @a;
        @a = @c;   
    } 
    my $carry = 0; 
    for(my $d = 0; $d <= @a - 1; $d++){ 
        my $d0 = $a[$d]; 
        my $d1 = $b[$d];
        if($d1){
            $sum = "0$sum", $carry = 0 if $d0 == 1 && $d1 == 1 && $carry == 1;  
            $sum = "1$sum", $carry = 0 if $d0 == 1 && $d1 == 0 && $carry == 0; 
            $sum = "0$sum", $carry = 1 if $d0 == 1 && $d1 == 1 && $carry == 0; 
            $sum = "0$sum", $carry = 1 if $d0 == 0 && $d1 == 1 && $carry == 1; 
            $sum = "0$sum", $carry = 0 if $d0 == 0 && $d1 == 0 && $carry == 0; 
            $sum = "1$sum", $carry = 0 if $d0 == 0 && $d1 == 0 && $carry == 1; 
            $sum = "0$sum", $carry = 1 if $d0 == 1 && $d1 == 0 && $carry == 1; 
            $sum = "1$sum", $carry = 0 if $d0 == 0 && $d1 == 1 && $carry == 0; 
        } 
        else{
            $sum = "0$sum", $carry = 1, next if $d0 == 1 && $carry == 1;  
            $sum = "1$sum", $carry = 0, next if $d0 == 0 && $carry == 1;  
            $sum = "0$sum", $carry = 0, next if $d0 == 0 && $carry == 0;  
            $sum = "1$sum", $carry = 0, next if $d0 == 1 && $carry == 0;  
        }  
    } 
    $sum = "$carry$sum" if $carry == 1;  
    return $sum; 
}

MAIN:{
    print add_binary(11, 1) . "\n"; 
    print add_binary(101, 1) . "\n"; 
    print add_binary(100, 11) . "\n"; 
}

Sample Run


$ perl perl/ch-1.pl
100
110
111

Notes

I have an unusual fondness for Perl's right hand conditional. But that is pretty obvious from the way I wrote this, right?

Part 2

You are given 3 positive integers, $i, $j and $k. Write a script to print the $kth element in the sorted multiplication table of $i and $j.

Solution


use strict;
use warnings;
sub nth_from_table{
    my($i, $j, $k) = @_;
    my @table;
    for my $x (1 .. $i){
        for my $y (1 .. $j){
            push @table, $x * $y; 
        }  
    }  
    return (sort {$a <=> $b} @table)[$k - 1];   
} 

MAIN:{
    print nth_from_table(2, 3, 4) . "\n";  
    print nth_from_table(3, 3, 6) . "\n";  
} 

Sample Run


$ perl perl/ch-2.pl 
3
4

Notes

Full Disclosure: At first I wanted to do this in some convoluted way for fun. After experimenting with, like, nested maps for a few minutes I lost all interest in "fun" and just went with a couple of for loops!

References

Challenge 140

posted at: 17:16 by: Adam Russell | path: /perl | permanent link to this entry

The Weekly Challenge 140 (Prolog Solutions)

The examples used here are from the weekly challenge problem statement and demonstrate the working solution.

Part 1

You are given two decimal-coded binary numbers, $a and $b. Write a script to simulate the addition of the given binary numbers.

Solution


:-initialization(main).

sum_carry(0, 0, 1, 1, 1).  
sum_carry(1, 0, 1, 0, 0).  
sum_carry(0, 1, 1, 1, 0). 
sum_carry(0, 1, 0, 1, 1). 
sum_carry(0, 0, 0, 0, 0). 
sum_carry(1, 0, 0, 0, 1).  
sum_carry(0, 1, 1, 0, 1). 
sum_carry(1, 0, 0, 1, 0). 
sum_carry(0, 1, 1, 1).   
sum_carry(1, 0, 0, 1). 
sum_carry(0, 0, 0, 0). 
sum_carry(1, 0, 1, 0).    

add_binary(A, B, Sum):-
    number_chars(A, AChars),   
    number_chars(B, BChars),        
    reverse(AChars, ACharsReverse),  
    reverse(BChars, BCharsReverse),  
    add_binary(ACharsReverse, BCharsReverse, 0, [], Sum).  
add_binary([], [], 0, SumAccum, Sum):-
    number_chars(Sum, SumAccum).  
add_binary([], [], 1, SumAccum, Sum):-   
    number_chars(Sum, ['1'|SumAccum]).  
add_binary([H|T], [], Carry, SumAccum, Sum):-
    number_chars(D, [H]), 
    sum_carry(S, C, D, Carry), 
    number_chars(S, [N]),  
    add_binary(T, [], C, [N | SumAccum], Sum).  
add_binary([H0|T0], [H1|T1], Carry, SumAccum, Sum):-
    number_chars(D0, [H0]), 
    number_chars(D1, [H1]), 
    sum_carry(S, C, D0, D1, Carry), 
    number_chars(S, [N]),  
    add_binary(T0, T1, C, [N | SumAccum], Sum).  

main:-
    add_binary(11, 1, X0),
    write(X0), nl, 
    add_binary(101, 1, X1),
    write(X1), nl, 
    add_binary(100, 11, X2),
    write(X2), nl, 
    halt. 

Sample Run


$ gplc prolog/ch-1.p 
$ prolog/ch-1   
100
110
111

Notes

The approach here may seem just a little strange for "simulating a binary addition", but it seemed like a fun idea, given the small number of combinations, to just store all the intermediate results and then retrieve them as needed. This all seems to work ok, except that maybe going back and forth between numbers and chars is a little clunky.

Part 2

You are given 3 positive integers, $i, $j and $k. Write a script to print the $kth element in the sorted multiplication table of $i and $j.

Solution


:-initialization(main).

multiply(I, J, N):-
    between(1, I, Ith),
    between(1, J, Jth),
    N is Ith * Jth.

multiplication_table(I, J, Table):-
    bagof(N, multiply(I, J, N), Table).   

nth_from_table(I, J, K, N):-
    multiplication_table(I, J, Table),  
    msort(Table, SortedTable),   
    nth(K, SortedTable, N).  

main:-
    nth_from_table(2, 3, 4, N0),
    write(N0), nl, 
    nth_from_table(3, 3, 6, N1),
    write(N1), nl, 
    halt.   

Sample Run


$ gplc prolog/ch-2.p 
$ prolog/ch-2  
3
4

Notes

It's maybe a little confusing, to me anyway, that GNU Prolog's msort/2 does not merge duplicates but sort/2 does. Other than that I have to say that I really like this bit of Prolog. It seems very clean to me in that no recursion was required, everything is handled via Prolog itself.

References

Challenge 140

posted at: 16:59 by: Adam Russell | path: /prolog | permanent link to this entry