Perl Weekly Challenge 113: sums and trees

One way to let me improve my knowledge about Raku (aka Perl 6) is to implement programs in it. Unluckily, I don’t have any production code to implement in Raku yet (sob!). So, why not try solving the Perl Weekly Challenge tasks?

In the following, the assigned tasks for Challenge 113.

PWC 113 - Task 1

The first task was quite simple to me: given a number and a digit we need to find out every number containing only one repetition of the digit that, summed together, provide the number given as argument.

sub MAIN( Int $N where { $N > 0 },
          Int $D where { $D >= 0 && $D.Str.chars == 1 } ) {
    given (1 ..^ $N).grep( * ~~ / $D /).sum {
        when $N { '1'.say }
        default { '0'.say }
    }
    
}


The idea is quite simple:
  • I produce all available numbers between 1 and the given target number $N;
  • I exclude from such list every number that does contain more than one digit $D;
  • I compute the sum of such list;
  • if such sum is equal to $N I do print 1, else I print 0.

PWC 113 - Task 2

The second problem was a little too complicated to me, since it involved binary trees. In particular, given a tree I was asked to substitute every node with the sum of the remaining nodes of the tree.
The difficult was that, given a node, I needed to substitute it with the sum of all nodes up and down from the current node.
I decided to implement a Node class with common attributes such as $value as its content, $left and $right as pointers to children.

class Node {
    has Int $.value;

    has  $.left is rw;
    has  $.right is rw;

    method sum() {
        my $sum = $!value;
        $sum += $_.sum if ( $_ ) for ( $!left, $!right );
        return $sum;
    }

    method map( &block ) {
        self.new: value => block( $!value ),
            left => $!left.map( &block ),
            right => $!right.map( &block );
    }

    method say() {
        "{ $!value }".say;
        "\t Left  = { $!left.value }".say if $!left;
        "\t Right = { $!right.value }".say if $!right;

        $!left.say if $!left;
        $!right.say if $!right;
    }

    
}


The sum method provides the sum of the whole part of the three starting from the current Node, so that given the root node I can compute the sum of the whole tree.
The trick here was to implement a map-like method that accepts a block of code and executes it against the sum of the node and its children.
In particular the map method creates a new Node instance, the one that is going to substitute the node. Such substitute has the value computed as the block of code passed to map, and then recursively does map on the children nodes.
The program therefore is as follows:

sub MAIN() {

    my $root = Node.new:
    value => 1
        , left => Node.new( value => 2, left => Node.new( value => 4, left => Node.new( value => 7 ) ) )
        , right => Node.new( value => 3, left => Node.new( value => 5 ), right => Node.new( value => 6 ) );

    $root = $root.map: { $root.sum - $_ if $_  };
    $root.say;
}




When map is invoked the block of code is { $root.sum - $_ if $_ }, so it computes the sum of the whole tree ($root.sum) and substracts the value of the current node value ($_ is a number because map passes $!value to the block of code as topic).
Recursively doing this makes the tree a new one with the nodes changed to the requested values.

I hate tree! There is some machinery to avoid empty spaces here and there, and also I placed the uniqueness of the solutions up to the permutation level, so that the final array @solutions is already made by unique lists.
The printing also evolved so that I can correctly print step or steps. The result is:

% raku ch-2.p6 5

Possible solution:
1 step 1 step 1 step 1 step 1 step 
Possible solution:
2 steps 1 step 1 step 1 step 
Possible solution:
1 step 2 steps 1 step 1 step 
Possible solution:
1 step 1 step 2 steps 1 step 
Possible solution:
1 step 1 step 1 step 2 steps 
Possible solution:
2 steps 2 steps 1 step 
Possible solution:
2 steps 1 step 2 steps 
Possible solution:
1 step 2 steps 2 steps 


And this is it.

The article Perl Weekly Challenge 113: sums and trees has been posted by Luca Ferrari on May 18, 2021