# RabbitFarm

### 2023-01-08

#### Prime the Gaps!

*The examples used here are from the weekly challenge problem statement and demonstrate
the working solution.*

## Part 1

*You are given a list of integers, @list. Write a script to find the total pairs in the
sorted list where 2 consecutive elements has the max gap. If the list contains less
then 2 elements then return 0.*

### Solution

```
use v5.36;
sub largest_gap{
my(@numbers) = @_;
my $gap = -1;
map{ $gap = $numbers[$_] - $numbers[$_ - 1] if $numbers[$_] - $numbers[$_ - 1] > $gap } 1 .. @numbers - 1;
return $gap;
}
sub gap_pairs{
my(@numbers) = @_;
return 0 if @numbers < 2;
my $gap = largest_gap(@numbers);
my $gap_count;
map { $gap_count++ if $numbers[$_] - $numbers[$_ - 1] == $gap } 1 .. @numbers - 1;
return $gap_count;
}
MAIN:{
say gap_pairs(3);
say gap_pairs(2, 5, 8, 1);
}
```

### Sample Run

```
$ perl perl/ch-1.pl
0
2
```

### Notes

Probably these two subroutines could be combined into one without too much trouble, but it still seems cleaner to me this way.

Do an initial pass over the list to determine the largest gap.

Perform a second pass over the list and count up all pairs which have the maximum gap.

An interesting issue came up. I've been trying to avoid the use of a map in a void context. This is just due to the general principal to use map as a function and use its return value rather than rely on side effects.

As part of this reformative effort I have been doing more with for in a postfix position. I discovered this when working this problem:

`{say $_ if $_ % 2 == 0} for 0 .. 9`

will not work. Perl gets confused by the
postfix `if`

within the block, apparently.

But there is a work around! Add `do`

and all is well.

`do {say $_ if $_ % 2 == 0} for 0 .. 9`

Of course the equivalent `map`

works just fine as you'd
expect `map {say $_ if $_ % 2 == 0} 0 .. 9)`

E. Choroba pointed out this is due to postfix
`for`

being a statement modifier which doesn't know what to do with blocks. But why does
`do`

fix this? I am still unclear on why that is. Even with the `do`

it's still a block!
Apparently perl will view it as a statement, for the purposes of the postfix `for`

?

UPDATE: Turns out that the `do {}`

construct qualifies as a *Simple Statement*. From the
perldoc: *Note that there are
operators like eval {}, sub {}, and do {} that look like compound statements, but
aren't--they're just TERMs in an expression--and thus need an explicit termination when
used as the last item in a statement.*

## Part 2

*You are given an integer $n > 0. Write a script to print the count of primes less
than $n.*

### Solution

```
use v5.36;
use Math::Primality q/is_prime/;
sub prime_count{
return 0 + grep { is_prime $_ } 2 .. $_[0] - 1;
}
MAIN:{
say prime_count(10);
say prime_count(15);
say prime_count(1);
say prime_count(25);
}
```

### Sample Run

```
$ perl perl/ch-2.pl
4
6
0
9
```

### Notes

The Math::Primality module makes this quite easy! In fact, I am not sure there is that much to elaborate on. Check primality using is_prime() and we're done!

## References

posted at: 19:30 by: Adam Russell | path: /perl | permanent link to this entry

The Weekly Challenge 198 (Prolog Solutions)

*The examples used here are from the weekly challenge problem statement and demonstrate
the working solution.*

## Part 1

*You are given a list of integers, @list. Write a script to find the total pairs in the
sorted list where 2 consecutive elements has the max gap. If the list contains less
then 2 elements then return 0.*

### Solution

```
largest_gap(Numbers, LargestGap):-
largest_gap(Numbers, -1, LargestGap).
largest_gap([], LargestGap, LargestGap).
largest_gap([_|[]], LargestGap, LargestGap).
largest_gap([A, B|Numbers], Gap, LargestGap):-
G is B - A,
(G > Gap, largest_gap([B|Numbers], G, LargestGap));
largest_gap([B|Numbers], Gap, LargestGap).
gap_pairs(Numbers, GapPairs):-
length(Numbers, L),
L =< 2,
GapPairs = 0.
gap_pairs(Numbers, GapPairs):-
length(Numbers, L),
L > 2,
largest_gap(Numbers, LargestGap),
gap_pairs(Numbers, LargestGap, 0, GapPairs).
gap_pairs([], _, GapPairs, GapPairs).
gap_pairs([_|[]], _, GapPairs, GapPairs).
gap_pairs([A, B|Numbers], LargestGap, Pairs, GapPairs):-
LargestGap #= B - A,
succ(Pairs, P),
gap_pairs([B|Numbers], LargestGap, P, GapPairs).
gap_pairs([A, B|Numbers], LargestGap, Pairs, GapPairs):-
LargestGap #\= B - A,
gap_pairs([B|Numbers], LargestGap, Pairs, GapPairs).
```

### Sample Run

```
$ gprolog --consult-file prolog/ch-1.p
| ?- gap_pairs([3], Pairs).
Pairs = 0 ?
(1 ms) yes
| ?- gap_pairs([2, 5, 8, 1], Pairs).
Pairs = 2 ?
yes
| ?-
```

### Notes

At first glance this code may look more complex than it really is. All we are doing is , first, computing the largest gap between any two adjacent numbers. Then, second, seeing which pairs have exactly this gap.

## Part 2

*You are given an integer $n > 0. Write a script to print the count of primes less
than $n.*

### Solution

```
primes_under_n(N, NumberPrimes):-
findall(Prime, (between(2, N, I), fd_prime(I), Prime = I), Primes),
length(Primes, NumberPrimes).
```

### Sample Run

```
$ gprolog --consult-file prolog/ch-2.p
| ?- primes_under_n(10, Primes).
Primes = 4
yes
| ?- primes_under_n(15, Primes).
Primes = 6
yes
| ?- primes_under_n(1, Primes).
Primes = 0
yes
| ?- primes_under_n(25, Primes).
Primes = 9
yes
```

### Notes

This solution is short and sweet! No reason or the writeup to be longer than the code itself, right?

## References

posted at: 13:29 by: Adam Russell | path: /prolog | permanent link to this entry