aboutsummaryrefslogtreecommitdiff
path: root/challenge-142/james-smith/README.md
blob: 342c7379748bc2d73a80e3c2d444f6132ee8ef37 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
[< Previous 141](https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-141/james-smith) |
[Next 143 >](https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-143/james-smith)
# Perl Weekly Challenge #142

You can find more information about this weeks, and previous weeks challenges at:

  https://theweeklychallenge.org/

If you are not already doing the challenge - it is a good place to practise your
**perl** or **raku**. If it is not **perl** or **raku** you develop in - you can
submit solutions in whichever language you feel comfortable with.

You can find the solutions here on github at:

https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-142/james-smith/perl

# Challenge 1 - Divisor Last Digit

***You are given positive integers, `$m` and `$n`.  Write a script to find total count of divisors of `$m` having last digit `$n`.***

## The solution

```perl
sub divisor_last_digit {
  my($m,$n)=@_;
  ($n==1?1:0)+grep{$_%10==$n}
              map{$m%$_?():$m==$_*$_?($_):($_,$m/$_)}
              2..sqrt$m;
}
```

 * First we find all the factors - by looping over all values between `2` and the square root of `$m`. If the value is a factor, so is `$m/$_`.
 * We have a special case when `$m` is a square to avoid including the square root twice.
 * We then `grep` to obtain those which have the correct last digit.
 * There is one extra special case if `$n` is `1` we have to add `1` as `1` is a factor which we miss out in our calculations (so we don't
   equally get `$m` as a factor).

# Challenge 2 - Sleep sort

***Another joke sort similar to JortSort suggested by champion Adam Russell. You are given a list of numbers. Write a script to implement Sleep Sort.***

To perform a sleep sort - we loop through the list of numbers, sleeping for `$value` seconds and updating the list of results with `$value`

## The solution

We need to parallelise this process

There are different ways of doing this `fork`, `threads`, `Promises`.

We will go for the `threads` approach as it easier to implement that `Promises` but doesn't eat at memory by forking lots of times.

```perl
use threads;
use threads::shared;
use Time::HiRes qw(sleep);

my @res :shared;
my @list=map{0.001*int rand 3000}1..20;

say "@list";

sub sleeper {sleep$_[0];push@res,$_[0]}

threads->new( \&sleeper, $_ ) for @list;

$_->join for threads->list;

say for @res;
```

## Notes

 * We create a test set of 20 values between `0` and `3`.
 * We fire off all the threads (`threads->new`)
 * Wait for them to finish `$_->join for threads->list`
 * Return the results.
 * As well as `use threads`, we also `use threads::shared`. This lets us declare the results array `@res` shareable across all processes, which we need to collect the values.

## Caveat

Not all threads start at the same time so sometimes results don't quite come back in the same order - especially if values are close together.