aboutsummaryrefslogtreecommitdiff
path: root/challenge-055/noud/raku/ch-2.p6
blob: 0ae0ed46c1199dc5ce2b59067a07a36a544672b6 (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
# Wave Array
#
# Any array N of non-unique, unsorted integers can be arranged into a wave-like
# array such that n1 ≥ n2 ≤ n3 ≥ n4 ≤ n5 and so on.
#
# For example, given the array [1, 2, 3, 4], possible wave arrays include [2,
# 1, 4, 3] or [4, 1, 3, 2], since 2 ≥ 1 ≤ 4 ≥ 3 and 4 ≥ 1 ≤ 3 ≥ 2. This is not
# a complete list.
#
# Write a script to print all possible wave arrays for an integer array N of
# arbitrary length.
#
# Notes:
#
# When considering N of any length, note that the first element is always
# greater than or equal to the second, and then the ≤, ≥, ≤, … sequence
# alternates until the end of the array.


# The difficulty is that we have to find all wave arrays. If we only had to
# give one wave function you could easily sort the array and flip some
# neighbours.
# I created a recurrent subroutine that takes two elements from the the array,
# sorts them descending, and computes all wave arrays of the remaining elements
# in the array. Combining the two elements with the wave (sub)arrays, when the
# second element is smaller than the first element in the wave (sub)array,
# gives all wave arrays. I'm curious to find out if there are better ways.

sub wave-sort(@a) {
    if (@a.elems == 0) {
        return [[],];
    } elsif (@a.elems == 1) {
        return [[@a.head],];
    }

    my @ret = [];

    @a = @a.sort.reverse;
    for 0..^@a.elems -> $i {
        for ($i+1)..^@a.elems -> $j {
            my $cur1 = @a[$i];
            my $cur2 = @a[$j];
            my @rest = [|(@a[0..^$i]), |(@a[($i+1)..^$j]), |(@a[($j+1)..*-1])];
            if (@rest.elems > 0) {
                for wave-sort(@rest) -> @r {
                    if ($cur2 <= @r.head) {
                        @ret.push([$cur1, $cur2, |(@r)]);
                    }
                }
            } else {
                @ret.push([$cur1, $cur2]);
            }
        }
    }
    return @ret;
}

say wave-sort([1]);
say wave-sort([1, 2]);
say wave-sort([1, 2, 3]);
say wave-sort([1, 2, 3, 4]);
say wave-sort([1, 2, 3, 4, 5]);