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
102
|
use v5.24;
use warnings;
package Stack {
use Scalar::Util qw(refaddr blessed);
my %vals;
my sub getval {
my ($node) = @_;
return defined $$node ? $vals{refaddr $node} : undef;
}
my sub rmval {
my ($node) = @_;
return delete $vals{refaddr $node}
if defined $$node;
return undef;
}
my sub addval {
my ($node, $value) = @_;
return $vals{refaddr $node} = $value
if defined $$node;
return undef;
}
sub new {
my ($self) = @_;
my $package = blessed $self || $self;
my $last = blessed $self ? $self : undef;
return bless \$last, $package;
}
sub push {
my ($self, $value) = @_;
my $new = $self->new;
addval($new, $value);
$_[0] = $new;
return;
}
sub pop {
my ($self) = @_;
if (defined $$self) {
my $value = rmval($self);
$_[0] = $$self;
return $value;
}
return undef;
}
sub min {
my ($self) = @_;
my $min = undef;
my $node = $self;
while ($$node) {
my $value = getval($node);
$min = ($min // $value) < $value ? $min : $value;
$node = $$node;
}
return $min;
}
sub top {
my ($self) = @_;
return getval($self);
}
}
use Test::More;
my $stack = Stack->new;
$stack->push(2);
$stack->push(-1);
$stack->push(0);
is $stack->pop, 0;
is $stack->top, -1;
$stack->push(0);
is $stack->min, -1;
is $stack->pop, 0;
is $stack->pop, -1;
is $stack->top, 2;
is $stack->pop, 2;
is $stack->pop, undef;
is $stack->top, undef;
is $stack->min, undef;
done_testing;
|