-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclass.all_different_directions.php
130 lines (120 loc) · 2.9 KB
/
class.all_different_directions.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
<?php
/*
* This file is part of the https://github.com/petruchek/problem.all_different_directions
*
* @author Val Petruchek <[email protected]>
*/
class All_Different_Directions
{
var $directions = [];
function __construct()
{
}
/**
* Parse input string into array into special structure [x,y,[commands]]
*
* @param string $s one line containing both person's location [x,y] and that person's directions
* @return array
*/
private function parse_direction($s)
{
//remove double spaces and tidy the string up
$s = trim(preg_replace('!\s+!', ' ', $s));
$_p = explode(' ', $s);
$dir = [];
$dir['x'] = $_p[0];
$dir['y'] = $_p[1];
$dir['commands'] = [];
for ($i=2;$i<count($_p);$i+=2)
{
$dir['commands'][] = [$_p[$i],$_p[$i+1]];
}
return $dir;
}
/**
* Process direction from single person by parsing it and computing that person's direction.
*
* Saves destination coordinates [end_x, end_y] into that same array of that person.
*
* @param string $s one line containing both person's location [x,y] and that person's directions
* @return void
*/
public function process_direction($s)
{
$dir = $this->parse_direction($s);
$destination = $this->compute_direction($dir);
list($dir['end_x'], $dir['end_y']) = $destination;
$this->directions[] = $dir;
}
/**
* Compute single person's destination from their position and set of commands
*
* @param array $dir [x,y,[commands]] special structure as returned by parse_direction()
* @return array [x,y] destination coordinates
*/
private function compute_direction($dir)
{
$x = $dir['x'];
$y = $dir['y'];
$a = 0;
foreach ($dir['commands'] as $command)
{
list ($keyword, $parameter) = $command;
switch ($keyword)
{
case 'start':
$a = $parameter;
break;
case 'turn':
$a += $parameter;
break;
case 'walk':
$deg = deg2rad($a);
$x += cos($deg)*$parameter;
$y += sin($deg)*$parameter;
break;
}
}
return [$x, $y];
}
/**
* The power of linear algebra - get distance between two points.
*
* @param float $x1
* @param float $y1
* @param float $x2
* @param float $y2
* @return float
*/
private function get_distance($x1,$y1,$x2,$y2)
{
return sqrt(($x1-$x2)**2+($y1-$y2)**2);
}
/**
* 1. Calculate the average point of all advised destinations.
*
* 2. Calculate the worst offset among all advised destinations.
*
* @return array [x,y,worst]
*/
public function get_average_destination()
{
$n = count($this->directions);
$x_sum = $y_sum = 0;
for ($i=0;$i<$n;$i++)
{
$x_sum += $this->directions[$i]['end_x'];
$y_sum += $this->directions[$i]['end_y'];
}
$x = $x_sum/$n;
$y = $y_sum/$n;
$worst = 0;
for ($i=0;$i<$n;$i++)
{
$offset = $this->get_distance($this->directions[$i]['end_x'],$this->directions[$i]['end_y'],$x,$y);
if ($offset > $worst)
$worst = $offset;
}
return [$x,$y,$worst];
}
}