aboutsummaryrefslogtreecommitdiff
path: root/challenge-018/feng-chang/perl6/ch-2.p6
blob: f8fcc687ac1918c18c0a6eeb97dcd7b2c4cda4a7 (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
#!/bin/env perl6

class task {
    has UInt $.priority;
    has Str  $.id;
}

class PriorityQueue {
    has UInt @!priorities;      # keep sorted
    has      %!queue{ UInt };   # UInt => task array

    submethod BUILD() {
        @!priorities = ();
        %!queue      = %();
    }

    method is_empty(--> Bool) { %!queue.elems == 0 }

    method add-new-task(UInt:D $priority, task:D $task) {
        my UInt $start = 0;
        my UInt $end   = max(0, @!priorities.elems - 1);

        while ($end - $start > 1) {
            my UInt $index = ($start + $end) / 2;

            if $priority < @!priorities[$index] {
                $start = $index;
            } elsif $priority > @!priorities[$index] {
                $end = $index;
            } else { # $priority == @!priorities[$index]
                %!queue{ $priority }.push($task);
            }
        }

        put("end - start should be 0 or 1: { $end - $start }");
        @!priorities.splice($start, 0, [$priority]);
        %!queue{ $priority } = [$task];
    }

    method insert-with-priority(UInt:D $priority, Str:D $task-id) {
        my $new-task = task.new(priority => $priority, id => $task-id);
        self.add-new-task($priority, $new-task);
    }

    method pull-highest-priority-element() {
        return Nil if %!queue.elems == 0;

        my $t = %!queue{ @!priorities[0] }.pop;
        if %!queue{ @!priorities[0] }.elems == 0 {
            %!queue{ @!priorities[0] }:delete;
            @!priorities.pop;
        }
        return $t;
    }

    method elems { [@!priorities.elems, %!queue.elems] }
}

use Test;
plan 5;

my PriorityQueue $que = PriorityQueue.new;

is True, $que.is_empty, 'default queue is empty';

$que.insert-with-priority(3, 'task one');
is [1, 1], $que.elems, 'task queue length is 1 after 1 insertion';

my $t = $que.pull-highest-priority-element;
is 3, $t.priority, 'task priority is 3';
is 'task one', $t.id, 'task is correct';

is [0, 0], $que.elems, 'task queue length is 0 after element is pulled';