-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmonke.php
executable file
·184 lines (154 loc) · 4.45 KB
/
monke.php
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#!/usr/bin/php
<?php
interface Operation {
function calc(int $old): int;
}
class SquareOp implements Operation {
function calc(int $old): int {
return $old * $old;
}
}
class MultiplyOp implements Operation {
private $value;
public function __construct($value) {
$this->value = (int)$value;
}
function calc(int $old): int {
return $old * $this->value;
}
}
class AddOp implements Operation {
private $value;
public function __construct($value) {
$this->value = (int)$value;
}
function calc(int $old): int {
return $old + $this->value;
}
}
class Monke {
public $items;
public $op;
public $div_by;
public $if_true;
public $if_false;
public $inspection_count;
public function __construct($items, $op, $div_by, $if_true, $if_false) {
$this->items = $items;
$this->op = $op;
$this->div_by = (int)$div_by;
$this->if_true = (int)$if_true;
$this->if_false = (int)$if_false;
$this->inspection_count = 0;
}
}
function must_read_line() {
$line = fgets(STDIN);
if($line === false) {
fprintf(STDERR, "Error: Unexpected end of input\n");
die(1);
}
return rtrim($line);
}
function parse_single_monkey() {
// Allow any number of empty lines before monkeys
do {
$line = fgets(STDIN);
if($line === false) return null;
$line = trim($line);
} while($line === "");
if(substr($line, 0, 7) !== "Monkey ") {
fprintf(STDERR, "Error: Expected monkey identifier line, got something else\n");
die(1);
}
// Ideally the monkey's ID should be parsed here,
// but they're all ordered by ID in the input, so whatever
$line = must_read_line();
if(substr($line, 0, 18) !== " Starting items: ") {
fprintf(STDERR, "Error: Expected list of starting items, got something else\n");
die(1);
}
$items = array_map('intval', explode(", ", substr($line, 18)));
$line = must_read_line();
if(substr($line, 0, 23) !== " Operation: new = old ") {
fprintf(STDERR, "Error: Expected operation specification, got something else\n");
die(1);
}
$args = explode(' ', substr($line, 23));
if($args[0] === '*') {
if($args[1] === "old") {
$op = new SquareOp();
} else {
$op = new MultiplyOp(intval($args[1]));
}
} else if($args[0] === '+') {
$op = new AddOp(intval($args[1]));
} else {
fprintf(STDERR, "Error: Unrecognized operation \"%s\" (expected \"*\" or \"+\")\n", $args[0]);
die(1);
}
$line = must_read_line();
if(substr($line, 0, 21) !== " Test: divisible by ") {
fprintf(STDERR, "Error: Expected division test specification, got something else\n");
die(1);
}
$div_by = intval(substr($line, 21));
$line = must_read_line();
if(substr($line, 0, 29) !== " If true: throw to monkey ") {
fprintf(STDERR, "Error: Expected true-action specification, got somthing else\n");
die(1);
}
$if_true = intval(substr($line, 29));
$line = must_read_line();
if(substr($line, 0, 30) !== " If false: throw to monkey ") {
fprintf(STDERR, "Error: Expected false-action specification, got somthing else\n");
die(1);
}
$if_false = intval(substr($line, 30));
return new Monke($items, $op, $div_by, $if_true, $if_false);
}
function parse_input() {
$monkeys = [];
while(($monke = parse_single_monkey()) !== null) $monkeys[] = $monke;
return $monkeys;
}
# -- end of definitions, parse arguments
if($argc < 1) {
fprintf(STDERR, "Error: You must specify mode of operation (either \"--part1\", or \"--part2\")\n");
die(2);
}
if($argv[1] === "--part1") {
$LIMIT = 20;
$DIV_BY = 3;
} else if($argv[1] === "--part2") {
$LIMIT = 10000;
$DIV_BY = 1;
} else {
fprintf(STDERR, "Error: Unrecognized argument \"%s\" (expected either \"--part1\", or \"--part2\")\n", $argv[1]);
die(2);
}
# -- args parsed, start script proper
$monkeys = parse_input();
// The proper way would be to calculate the GCD, but eh
$modulus = 1;
foreach($monkeys as $monke) $modulus *= $monke->div_by;
for($round = 1; $round <= $LIMIT; ++$round) {
foreach($monkeys as $idx => $monke) {
foreach($monke->items as $item) {
$item = $monke->op->calc($item);
if($DIV_BY !== 1) $item = floor($item / $DIV_BY);
$item %= $modulus;
$dest = (($item % $monke->div_by) == 0) ? $monke->if_true : $monke->if_false;
$monkeys[$dest]->items[] = $item;
}
$monkeys[$idx]->inspection_count += count($monke->items);
$monkeys[$idx]->items = [];
}
}
$ic = [];
foreach($monkeys as $idx => $monke) {
echo "Monkey ", $idx, " inspected ", $monke->inspection_count, " items.\n";
$ic[] = $monke->inspection_count;
}
rsort($ic, SORT_NUMERIC);
echo "Level of monkey business: ", $ic[0] * $ic[1], "\n";