-
Notifications
You must be signed in to change notification settings - Fork 0
/
miloChallenge.php
166 lines (159 loc) · 4.35 KB
/
miloChallenge.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
<?php
$file = $argv[1]; // le file
$lines = file($file); // make an array of each line
foreach ($lines as $line) {
// le processing
$line = str_replace("\n", '', $line); // remove new line
$halves = preg_split('/;/', $line); // split at semi-colon
$persons = explode(',', $halves[0]); // array of left half, persons
$things = explode(',', $halves[1]); // array of right half, things
$num_rows = count($persons); // num rows for matrix, based off num persons
$num_cols = count($things); // num cols for matrix, based off num things
// le matrix
$matrix = array(array()); // create matrix
for ($i = 0; $i < $num_rows; $i++) { // loop over rows
for ($j = 0; $j < $num_cols; $j++) { // loop over cols per row
// remove everything except for alphabetical letters and returns the length
$itemLen = strlen(preg_replace('/\PL/u', '', $things[$j]));
// remove all spaces
$personLen = strlen(preg_replace('/\s+/', '', $persons[$i]));
if ($itemLen & 1) {
//odd
$numCs = preg_match_all('/[bcdfghjklmnpqrstvwxz]/i', $persons[$i], $matches); // num consonants
$matrix[$i][$j] = $numCs;
} else {
//even
$numVs = preg_match_all('/[aeiouy]/i', $persons[$i], $matches); // num vowels
$matrix[$i][$j] = $numVs*1.5;
}
if (gcd($itemLen, $personLen) != 1) {
$matrix[$i][$j] = $matrix[$i][$j]*1.5;
}
}
}
// uncomment to see cost matrix before augmentation for maximization
// echo $matrix[0][0] . " " . $matrix[0][1] . " " . $matrix[0][2] . "\n";
// echo $matrix[1][0] . " " . $matrix[1][1] . " " . $matrix[1][2] . "\n";
// echo $matrix[2][0] . " " . $matrix[2][1] . " " . $matrix[2][2] . "\n";
// echo "\n";
// le algorithm
$ss = hungry($matrix);
$ss = number_format($ss, 2, '.', ''); // format for 2 decimal points
echo $ss . "\n";
}
// hungarian algorithm to solve matrix assignment
function hungry($matrix) {
$m = padit($matrix);
$max = multimax($m);
$num_rows = count($m);
$num_cols = count($m[0]);
// augment for maximize
for ($i = 0; $i < $num_rows; $i++) {
for ($j = 0; $j < $num_cols; $j++) {
$m[$i][$j] = $max - $m[$i][$j];
}
}
$bignum = 100000; // arbitrarily big number
$u = array_pad(array(), $num_rows, 0);
$v = array_pad(array(), $num_cols, 0);
$ind = array_pad(array(), $num_cols, -1);
for ($i = 0; $i < $num_rows; $i++) {
$links = array_pad(array(), $num_cols, -1);
$mins = array_pad(array(), $num_cols, $bignum);
$visited = array_pad(array(), $num_cols, 0);
$markedI = $i;
$markedJ = -1;
$j = 0;
$done = false;
while (!$done) {
$j = -1;
for ($k = 0; $k < $num_rows; $k++) {
if ($visited[$k] == 0) {
$cur = $m[$markedI][$k] - $u[$markedI] - $v[$k];
if ($cur < $mins[$k]) {
$mins[$k] = $cur;
$links[$k] = $markedJ;
}
if ($j == -1 || $mins[$k] < $mins[$j]) {
$j = $k;
}
}
}
$delta = $mins[$j];
for ($k = 0; $k < $num_cols; $k++) {
if ($visited[$k] == 1) {
$u[$ind[$k]] += $delta;
$v[$k] -= $delta;
} else {
$mins[$k] -= $delta;
}
}
$u[$i] += $delta;
$visited[$j] = 1;
$markedJ = $j;
$markedI = $ind[$j];
if ($markedI == -1) {
$done = true;
}
}
$done = false;
while (!$done) {
if ($links[$j] != -1) {
$ind[$j] = $ind[$links[$j]];
$j = $links[$j];
} else {
$done = true;
}
}
$ind[$j] = $i;
}
$ss = 0;
for ($j = 0; $j < $num_cols; $j++) {
// uncomment to see matrix coordinates
// echo $ind[$j] . ", " . $j . "\n";
$ss += $matrix[$ind[$j]][$j];
}
return $ss;
}
// pad matrix if not square
function padit($matrix) {
$m = $matrix;
$num_rows = count($m);
$num_cols = count($m[0]);
if ($num_rows > $num_cols) { // if tall
for ($i = 0; $i < $num_rows; $i++) {
$m[$i] = array_pad($m[$i], $num_rows, 0);
}
} elseif ($num_cols > $num_rows) { // if wide
for ($i = count($m); $i < $num_cols; $i++) {
$m[$i] = array_pad(array(), $num_cols, 0);
}
}
return $m;
}
// returns maximum value in multidimensional array
function multimax($matrix) {
$num_rows = count($matrix);
$max = array();
for ($i = 0; $i < $num_rows; $i++) {
$max[$i] = max($matrix[$i]);
}
$max = max($max); // max value in entire array
return $max;
}
// returns greatest common factor of two numbers
function gcd($x, $y) {
$x = abs($x);
$y = abs($y);
if($x + $y == 0) {
return 0; // not supposed to happen
} else {
while($x > 0) {
$z = $x;
$x = $y % $x;
$y = $z;
}
return $z;
}
}
?>