Weekly Challenge in Raku Week 102


This weeks challenges are quite fun and simple enough (after a bit of thought). I'll quickly run through my results and some thoughts on doing it in Raku.

Challenge 1

So I learn lots of fun maths stuff doing the weekly challenge. Rare numbers are weird and there's not many of them. The code I came up with goes like this :

sub rares(UInt \l) {
  ((10**(l - 1))..((10**l)-1)).race.grep( -> \i { rare(i) } );

So lets break that down : ((10**(l - 1))..((10**l)-1)) give us the range of all l digit long numbers. Then we put in a race to get threading easily then we grep with our rare function... And here it is :

sub rare(Int \r) returns Bool {
  my \f = r.flip;
  square(r - f) && square( r + f );    

So here we flip the value to be tested (note we're using Raku's dynamic typing here. r is an Int, flip is a String method so f is a string but then we treat it as an Int straight after. Nice and simple. Of course now we've got another function, square.

multi sub square(Int $ where * <= 0) returns Bool { False }

multi sub square(Int \i) returns Bool { my \s = i.sqrt; s == s.Int; }

Our square function tests if our value is a perfect square. Firstly if it's a negative number then it's never going to work (I learned that the hard way testing if 12 is a rare number). Then if not we calculate the square root and see if it matches the Integer casting of itself.

Of course here be some dragons, calcualating square roots is horrible and slow for larger numbers. (The 9 digit run of this code takes... well I've got bored waiting for it on my VM that I'm currently using). I thought about adding caching but then there's the fun of that and threading so I decided to stick with the functional purity of the code.

It's pretty and I like that, if you want it to be fast get some more cores ;) My full solution includes a test suite and a main wrapper but they are pretty simple.

Challenge 2

At first glance this seemed quite complicated. Then I had a little thought about it and the word recursion popped up in my brain. It does that quite a lot, but this time it seemed to be right. Seriously you can't use recursion to solve every problem, I mean how to you recurse chosing what you want for dinner? (Answers on a postcard please).

Anyway. Lets have a think. We want a function hash-count that takes and integer and returns a string. If the integer is 1 you return a "#" and if it's 0 you return ""...

multi sub hash-count(1) { "#" }
multi sub hash-count(0) { "" }

So those definitely look like ending conditions of a recusrsive function. For any other positive integer the string ends with the number (call it $x) and a "#". This is put after the result of calling our function with $x less then the length of our string. So if $x is 5 then we have 5# which is length 2 so we call hash-count(5-2) and bingo... recursion.

multi sub hash-count(UInt $x) {
  hash-count($x - ($x.chars + 1) ) ~ $x ~ '#';

And there we go, nice and simple. Again Raku's multi method calls make recursion a doddle, probably why I reach for it so often when doing challanges.

I hope this has been interesting. More later.