aboutsummaryrefslogtreecommitdiff
path: root/challenge-208/0rir/raku/ch-2.raku
blob: b3c410e894738d20206091a8eef4c5c69e942690 (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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#!/usr/bin/env raku
# :vim ft=raku sw=4 expandtab  # 🦋 ∅ ≡ ∩ ≢ ∈ « ␤ » ∴
use v6.d;
use Test;

=begin comment
208-2: Duplicate and Missing    Submitted by: Mohammad S Anwar

Given an array of integers in sequence with one missing and one duplicate;
find the duplicate and missing integer in the given array. Return -1 if none
found.  Assume the array contains no more than one duplicate and missing.

Example 1:

Input: @nums = (1,2,2,4)
Output: (2,3)

Duplicate is 2 and Missing is 3.
Example 2:

Input: @nums = (1,2,3,4)
Output: -1

No duplicate and missing found.
=end comment

my @Test-bad = [];
my @Test =
    ( (1,),      Array,     ),
    ( (1,1),     Array,     ),
    ( (1,2),     Array,     ),
    ( (1,3),     Array,     ),
    ( (1,2,3,4), Array,     ),
    ( (1,1,3),   (1,2),     ),
    ( (1,3,3),   (3,2),     ),
    ( (2,2,3),   (2,1),     ),
    ( (2,3,3),   (3,4),     ),
    ( (1,2,3,3), (3,4),     ),
    ( (1,2,2,4), (2,3),     ),

    (( -10,       -10,     Empty, |(-810)),    (-10,  -9)),
    (( Empty,      -9,            |(-910)),    ( -9, -10)),
    (( |(-109),    9,            Empty   ),    (  9,  10)),
    (( |(-108), Empty,    10,    10      ),    ( 10,   9)),
    (( |(-100), Empty,     2,    |(210) ),    (  2,   1)),
    (( |(-100),   0,     Empty,  |(210) ),    (  0,   1)),

    (( -10000,         -10000,  Empty,  |(-999810000)),   (-10000,  -9999)),
    (( Empty,           -9999,          |(-999910000)),   ( -9999, -10000)),
    (( |(-100009999),   9999,          Empty,        ),   (  9999,  10000)),
    (( |(-100009998),  Empty,  10000,  10000         ),   ( 10000,   9999)),
    (( |(-100000),     Empty,  2,      |(210000)    ),   (     2,      1)),
    (( |(-100000),      0,     Empty,  |(210000)    ),   (     0,      1)),

    (( |(-10000099998),  Empty,  100000,  100000     ),   ( 100000,  99999)),

    ( (-100100), Array),
;

# too small
multi sub dupe-and-miss( @a where .end < 2 ) { Array }

# simplify fenceposts on full pass  TODO process tail not head micro-optim
multi sub dupe-and-miss( @a where @a[0] == @a[1] --> Array ) {
    when @a[2] > @a[1] + 1 {
        return [ @a.head, @a.head+1 ]
    }
    return [@a.head, @a.head -1  ];
}

# common case                  # above TODO  shave tail not head
multi sub dupe-and-miss( @a --> Any ) {
    for 1..^@a.end -> $i {
        if @a[$i] == @a[$i + 1] {
            if @a[$i-1] == @a[$i] -2 {
                return [ @a[$i], @a[$i] -1]
            } else {
                return [ @a[$i], @a[$i] +1]
    }   }   }
    return Array;
}

plan +@Test-bad + @Test;

for @Test-bad ->  @t {
    is dupe-and-miss( @t), Array, 'no match';
}

for @Test ->  ( @in, @exp) {
    is dupe-and-miss( @in), @exp, "&dupe-and-miss @in[0] to @in[@in.end]";
}

done-testing;

my @n = (-77),
        (|(-5…-2), 0, |(05));
for @n -> @num {
    print "\nInput: @num = @num[]\nOutput: ", &dupe-and-miss( @num) // -1;
}