-
Notifications
You must be signed in to change notification settings - Fork 0
/
is-the-electric-garage-door-open.php
180 lines (143 loc) · 4.73 KB
/
is-the-electric-garage-door-open.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
<?php
/**
* Code Golf: Is the electric garage door open?
*
* @link http://codegolf.stackexchange.com/questions/79668/is-the-electric-garage-door-open
*/
// Include the code-golf framework; it loads the testing frameworks
require 'a/CodeGolfFramework.php';
/**
* A class for the problem at hand
*/
class ElectricGarageDoor extends ACodeGolfProblem
{
/////////////////////////////////////////////////////////////////////////
// Actions
//
/**
* Run all the tests; this method is invoked when the program is launched without arguments
*
* @return int
*/
public function runTests()
{
// Run the test cases provided in the problem
$this->testDoorStatus([], '100% D');
$this->testDoorStatus([20], '0% U');
$this->testDoorStatus([10], '0% U');
$this->testDoorStatus([5], '50% D');
$this->testDoorStatus([20, 20], '100% D');
$this->testDoorStatus([10, 10], '100% D');
$this->testDoorStatus([5, 5], '0% U');
$this->testDoorStatus([1, 2, 3], '100% D');
$this->testDoorStatus([8, 9, 10, 11], '0% U');
$this->testDoorStatus([11, 10, 9, 8, 7], '20% U');
return 0;
}
/**
* Test helper. Test both scripts (plain and golfed version) using the test framework.
* Check their actual output against the expected output.
*
* @param int[] $delays the input argument (the number of seconds to wait before pushing the button)
* @param string $expected the expected program output
*/
protected function testDoorStatus(array $delays, $expected)
{
// Format the input for display
$input = implode(' ', $delays);
// Put the script path in front of the arguments; the real program gets its arguments from the command line
array_unshift($delays, __FILE__);
// Test the plain-code function
it(
sprintf("turns input '%s' into output '%s' -- clear version", $input, $expected),
$this->getFunctionOutput(function () use ($delays) { $this->handleDoor($delays); }) === $expected
);
// Test the golfed function
it(
sprintf("turns input '%s' into output '%s' -- golfed version", $input, $expected),
$this->getFunctionOutput(function () use ($delays) { $this->hndlDr($delays); }) === $expected
);
}
/////////////////////////////////////////////////////////////////////////
// Handling of the golfed code
//
/**
* Return the golfed source code.
*
* @return string
*/
public function getTheGolfedCode()
{
// It's the code of self::hndlDr() method
return parent::getFunctionBody('hndlDr', __CLASS__);
}
/**
* Run the golfed code using the arguments provided in the command line.
* Throw an InvalidArgumentException when this is not possible.
*
* @param int $argc
* @param array $argv
* @return int the exit code
* @throws InvalidArgumentException
*/
public function runTheGolfedCode($argc, array $argv)
{
// Run the code
$this->hndlDr($argv);
echo("\n");
// Success
return 0;
}
/////////////////////////////////////////////////////////////////////////
// The solution of the problem
//
/**
* This is the plain code.
*
* @param array $listDelays
* @return int
*/
private function handleDoor(array $listDelays)
{
// The door is down (0% open)
$pos = 0; // 0 .. 10
// It will move up
$dir = +10;
// The initial button push starts the door moving up
$run = 0;
// Handle each button push
foreach ($listDelays as $delay) {
if ($run) {
$pos = min(max($pos + $delay * $dir, 0), 100);
if (0 < $pos && $pos < 100) {
$run = 0;
}
$dir = -$dir;
} else {
$run = 1;
}
}
// Complete the last move, if any
if ($run) {
$pos = min(max($pos + 10 * $dir, 0), 100);
$dir = - $dir;
$run = 0;
}
echo $pos . '% ' . ($dir + 10 ? 'U' : 'D');
}
/**
* This is the golfed code.
*
* @param array $argv
* @return string
*/
private function hndlDr(array $argv)
{
$d=$argv[]=10;foreach($argv as$a)if($r){$p=min(max($p+$a*$d,0),100);$r=$p<1||99<$p;$d=-$d;}else$r=1;echo"$p% ".DU[$d>0];
}
}
/////////////////////////////////////////////////////////////////////////
// Create the problem and let it run
//
exit((new ElectricGarageDoor($argc, $argv))->run());
// This is the end of file; no closing PHP tag