# ETOOBUSY ðŸš€ minimal blogging for the impatient

# PWC191 - Twice Largest

**TL;DR**

Here we are with TASK #1 from The Weekly Challenge #191. Enjoy!

# The challenge

You are given list of integers,

`@list`

.Write a script to find out whether the largest item in the list is at least twice as large as each of the other items.

Example 1`Input: @list = (1,2,3,4) Output: -1 The largest in the given list is 4. However 4 is not greater than twice of every remaining elements. 1 x 2 <= 4 2 x 2 <= 4 2 x 3 > 4`

Example 2`Input: @list = (1,2,0,5) Output: 1 The largest in the given list is 5. Also 5 is greater than twice of every remaining elements. 1 x 2 <= 5 2 x 2 <= 5 0 x 2 <= 5`

Example 3`Input: @list = (2,6,3,1) Output: 1 The largest in the given list is 6. Also 6 is greater than twice of every remaining elements. 2 x 2 <= 6 3 x 2 <= 6 1 x 2 <= 6`

Example 4`Input: @list = (4,5,2,3) Output: -1 The largest in the given list is 5. Also 5 is not greater than twice of every remaining elements. 4 x 2 > 5 2 x 2 <= 5 3 x 2 > 5`

# The questions

I guess weâ€™re gradually transitioning towards TDC - *Test Driven
Challenges*. This is not bad per-se, we would just need a few more
examples.

Soâ€¦

- What should we return? Assuming
`-1`

for false and`1`

for true. - What should we return if we are provided an empty list? This is tough,
Iâ€™ll just assume that
`-1`

is good. - What should we return if we only have one single entry in the list?
This timeâ€¦ Iâ€™ll assume that
`1`

is good. - What should we do with repeated value? Iâ€™ll assume that they can be ignored.

OK, letâ€™s move on toâ€¦

# The solution

The most efficient algorithm would need to look *at least* at all
elements and actually needs looking at each of them at most once. So we
have a good linear complexity, by doing this (assuming enough stuff in
the array):

```
# initialize from the first two elements
my ($v1, $v2) = @list[0] < @list[1] ? @list[1,0] : @list[0,1];
# sweep the rest of the list
my $i = 1;
while (++$i < @list) {
($v1, $v2) = (@list[$i], $v1) if @list[$i] > $v1;
}
# now we can check if $v1 >= 2 * $v2
```

I *hope* that the code above is valid in *both* Raku and Perl
(even though itâ€™s going to raise a few warnings with the latter).

Anyway.

On the other handâ€¦ the fastest (programmer-wise, mind you!) solution can involve sorting the array in reverse order, and take the maximum value (ending up in first position) and the second-to-maximum value (ending up in second position) and compare them. Which is what we do in Raku here:

```
#!/usr/bin/env raku
use v6;
sub MAIN (*@list) { put twice-largest(@list) }
sub twice-largest (@list) {
my ($top, $next) = @list.sort({ $^a <=> $^b }).reverse.flat;
return -1 unless defined $top;
return 1 unless defined $next;
return ($top >= 2 * $next) ?? 1 !! -1;
}
```

With a little twist, in our Perl translation weâ€™ll move the checks
*before* doing the sorting, but for anything less itâ€™s just the same
algorithm as above:

```
#!/usr/bin/env perl
use v5.24;
use warnings;
use experimental 'signatures';
no warnings 'experimental::signatures';
say twice_largest(@ARGV);
sub twice_largest (@list) {
return -1 unless @list > 0;
return 1 unless @list > 1;
my ($top, $next) = reverse sort { $a <=> $b } @list;
return ($top >= 2 * $next) ? 1 : -1;
}
```

Well, nothing more to add I daresayâ€¦ stay safe!

*Comments? Octodon, Twitter, GitHub, Reddit, or drop me a line!*