aboutsummaryrefslogtreecommitdiff
path: root/challenge-136/james-smith/README.md
blob: 742f1c6c9eb13c363f7eeb16b581b28f87fd1b61 (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
[< Previous 135](https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-135/james-smith) |
[Next 137 >](https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-137/james-smith)

# Perl Weekly Challenge #136


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-136/james-smith/perl

# Task 1 -  Two friendly

***You are given 2 positive numbers, `$m` and `$n`. Write a script to find out if the given two numbers are "Two friendly".***

*Two positive numbers, `m` and `n` are two friendly when `gcd(m, n) = 2 ^ p` where `p > 0`. The greatest common divisor (gcd) of a set of numbers is the largest positive number that divides all the numbers in the set without remainder.*

## The solution

The logic of our solution is (1) find the GCD; (2) check they are not co-prime (GCD = 1); (3) The GCD is a power of 2

We can test the last case by converting the GCD into binary - and checking to see if it has the form `10+`. Alternatively we can use `&` and `>>=` to remove trailing zeros.

All that gives us the simple function....

```perl
sub friendly {
  my($a,$b) = @_;
  ($a,$b) = ($b,$a%$b) while $b; ## Compute GCD
  return 0 if $a == 1;           ## Co-prime not friendly
  $a>>=1 until $a&1;             ## Remove trailing 0s
  return $a == 1 ? 1 : 0;        ## Friendly iff
}

```

# Task 2 - Fibonacci Sequence

***You are given a positive number `$n`. Write a script to find how many different sequences you can create using Fibonacci numbers where the sum of unique numbers in each sequence are the same as the given number.***

## Solution

There are two bits to this:
 * get a list of fibonacci numbers `<= $n`. Easier to find list up to the first fibonnaci number `> $n`.
   * We have a cache of the fibonnaci numbers - we just need to extend it to include all those fibonnaci numbers below `$n` (if required).
 * get a list of sums of these numbers which equal `$n`
   * We call a generic "get-sum" method where we pass in our target number and array of fibonacci numbers
   * this get-sum method is then call recursively to count the number of totals
 
```perl

my @fib;

sub fib_sum {
  my $n = shift;
  push @fib, $fib[-1] + $fib[-2] while $n > $fib[-1];
  return sum( $n, grep { $_ <= $n }  @fib );
}

sub sum {
  local $_;
  my ( $t, @n ) = @_;
  return 1 unless $t;
  return 0 if $t < 0;
  my $c = 0;
  $c += sum( $t - $_, @n ) while $_ = shift @n;
  return $c;
}

```