Perl Weekly Challenge 50: overlapping ranges and nobel numbers

PWC 50 - Task 1

2..7

3..9

~~

sub overlap( Range $a, Range $b ) { return $b.max > $a.max > $b.min || $b.max > $a.min > $b.min; } sub merge( Range $a, Range $b ) { return Range.new: min( $a.min, $b.min ), max( $b.max, $a.max ); }

$b.max > $a.max > $b.min

$b.max > $a.max && $a.max > $b.min

while ( @ranges.elems ) { if overlap( @ranges[ 0 ], @ranges[ 1 ] ) { # merge the ranges @merged-ranges.push: merge( @ranges[ 0 ], @ranges[ 1 ] ); @ranges.shift; @ranges.shift; } else { # dont' merge, push the first one @merged-ranges.push: @ranges[ 0 ]; @ranges.shift; } }

while ( @ranges.elems ) { my $a = @ranges.shift; my $b = @ranges[ 0 ]; @merged-ranges.push( Range.new( min( $a.min, $b.min ), max( $a.max, $b.max ) ) ) && @ranges.shift && next if $b.max > $a.max > $b.min || $b.max > $a.min > $b.min; @merged-ranges.push: $a; }

if

Range

&& next

else

PWC 50 - Task 2

my @L = (1..50).List.pick: $how-many; # first approach: use a grep to count how # many elemnts are there my @nobel; for @L -> $a { @nobel.push( $a ) if @L.grep( { $a < $_ } ).elems == $a; }

List

pick

grep

grep

@nobel

x

@L .= sort; for 0 .. @L.elems - 1 { @nobel.push( @L[ $_ ] ) if @L[ $_ ] == @L.elems - $_; }

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 50 The first task involved overlapping ranges, unluckily the smartmatching operators checks for containing ranges, so while the rangesandare overlapping, to regard to the task, they are not in sense of theMy first solution was quite simple: implement a couple of functions to check if the ranges overlap and build a merging match:The only smart thing used here is the formthat Raku allows and that other languages have to express like. The final merge is made by the min and max values found between the ranges.The other tricky part is that the list of ranges must be searched in pairs, but in the case of a merge two pairs are removed, otherwise only one is:Please note that, in the case there is an overlap, both ranges are shifted out of the array, otherwise only the first one is removed. This makes the next iteration continuing from exactly the second range that did not match.However, it is possible to write the whole thing in a way that is less readable but much more compact:The first range is always shifted out of the array, since it will either be merged or pushed as it is into the final result array. Then the trick is about the postponed: in the case there is a merge a newis build, and also the second range is shifted out of the array and the iteration proceeds to the next cycle. Otherwise, the first range is pushed as it is. The usage ofrepresents a dirty way of implementing a postfixThe second task was about Nobel numbers: given a list a number is a Nobel one if there exactly the same number of its value greater than it in the list.The first solution was quite straightforward:First of all, I convert a range into ato use themethod that, in a list accepts the number of elements to randomly picks.After that, I perform a loop over all the elements andall the elements greater than the one I’m inspecting. If theped list has a number of elements that match the value I’m inspecting, such element is appended to the list ofnumbers as final result.However, this is not the only one approach: if you order the list before you scan for values, you can perform a little smarter approach. In fact, once the list is sorted, the number at positionmust have exactly other elements after it that matches its value, so: