site.base_url }}/">The Bear's Den -->

The Bear's Den

Enter at your own risk

Change With No Way Out

Task 1: No Connection

Submitted by: Mohammad Sajid Anwar


You are given a list of routes, @routes.

Write a script to find the destination with no further outgoing connection.

Example 1

Input: @routes = (["B","C"], ["D","B"], ["C","A"])
Output: "A"

"D" -> "B" -> "C" -> "A".
"B" -> "C" -> "A".
"C" -> "A".
"A".

Example 2

Input: @routes = (["A","Z"])
Output: "Z"

Solution

Lazy as I am, I build a graph from the given edges and find the sink vertices therein.

use strict;
use warnings;
use Graph::Directed;

sub no_connection {
    Graph::Directed->new(edges => \@_)->sink_vertices;
}

See the full solution to task 1.

Task 2: Making Change

Submitted by: David Ferrone


Compute the number of ways to make change for given amount in cents. By using the coins e.g. Penny, Nickel, Dime, Quarter and Half-dollar, in how many distinct ways can the total value equal to the given amount? Order of coin selection does not matter.

A penny (P) is equal to 1 cent.
A nickel (N) is equal to 5 cents.
A dime (D) is equal to 10 cents.
A quarter (Q) is equal to 25 cents.
A half-dollar (HD) is equal to 50 cents.

Example 1

Input: $amount = 9
Ouput: 2

1: 9P
2: N + 4P

Example 2

Input: $amount = 15
Ouput: 6

1: D + 5P
2: D + N
3: 3N
4: 2N + 5P
5: N + 10P
6: 15P

Example 3

Input: $amount = 100
Ouput: 292

Solution

Using recursion to solve this task.

Here we’ll consider an amount and a maximum coin. The trivial cases are:

In all other cases:

use strict;
use warnings;
use experimental 'signatures';

sub make_change ($amount, $coin = 4) {
    state $coins = [1, 5, 10, 25, 50];
    if ($coin == 0) {
        if ($amount % $coins->[0] == 0) {
            return [$amount / $coins->[0]];
        } else {
            return ();
        }
    }
    my @comb;
    for (my ($cnt, $val) = (0, 0);
        $val <= $amount;
        $cnt++, $val += $coins->[$coin]) {
        if ($val == $amount) {
            push @comb, [(0) x $coin, $cnt];
        } else {
            push @comb, [@$_, $cnt]
                for make_change($amount - $val, $coin - 1);
        }
    }

    @comb;
}

If we want to present the individual combinations as shown in the examples, we need to format the resulting arrays. The requested count is just the size of the result.

sub fmt {
    state $name = [qw(P N D Q HD)];
    my @coins;
    for (my $i = $#_; $i >= 0; $i--) {
        my $c = $_[$i];
        push @coins, $c x ($c != 1) . $name->[$i] if $c;
    }

    join ' + ', @coins;
}

See the full solution to task 2.


If you have a question about this post or if you like to comment on it, feel free to open an issue in my github repository.