aboutsummaryrefslogtreecommitdiff
path: root/challenge-095/brtastic/perl/ch-2.pl
blob: f5dbb17637e306e5ca725bccd38cccac1ce0ee35 (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
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;