I have a working php implementation of Ford Fulkerson algorithm, based on this great article http://www.geeksforgeeks.org/maximum-bipartite-matching/
At the moment, the matrix that control the algorithm can have in its cells a value of 1 or 0, to represent the possibility of every employee to work in that position. I would like to add capacity to the algorithm, basically place in the matrix higher values, like 2, 3 and so on to express the preference to choose an employee instead of another.
Do You have any suggestion on how to edit the algorithm to add capacity?
This is the algorithm code:
function maxMatch($matrix, $cols) {
$match = array();
foreach ($cols as $v => $item) {
$match[$item] = -1;
}
$result = 0;
foreach ($matrix as $u => $row) {
$seen = array();
foreach ($cols as $v => $item) {
$seen[$item] = 0;
}
if ($this->checkVertex($matrix, $u, $seen, $match)) {
print_r($match);
$result++;
}
}
return $match;
}
function checkVertex($matrix, $u, &$seen, &$match) {
foreach ($matrix[$u] as $v => $row) {
if ($matrix[$u][$v] && !$seen[$v]) {
$seen[$v] = TRUE;
if ($match[$v] < 0 || $this->checkVertex($matrix, $match[$v], $seen, $match)) {
$match[$v] = $u;
return TRUE;
}
}
}
return FALSE;
}
This is how I create the matrix:
function createMatrix($year, $month, $day, $shift) {
global $sql;
$result = $sql->query("VERY HUGE SELECT FOR EMPLOYEES AND POSITIONS MATCH");
while ($row = $result->fetch_assoc()) {
$matrix[$row['employee']][$row['position']] = 1;
}
return $matrix;
}
Thanks a lot,
Marco
Related
I have the following iterration:
foreach ($filelines as $indexrow => $line) {
$columns = explode($splitter, $line);
$row = [];
foreach ($columns as $columnindex => $column) {
$column = $this->prepareValue($column);
if (RegexValidation::isNum($column)) {
$row[] = $this->setValue('num', $column, $indexrow, $columnindex);
} else {
if (RegexValidation::isMMYY($column)) {
$row[] = $this->setValue("mmyy", $column, $indexrow, $columnindex);
} else {
if (RegexValidation::isZip($column)) {
$row[] = $this->setValue("zip", $column, $indexrow, $columnindex);
}
}
}
}
$dataset[$indexrow] = $row;
}
I need to fill $row in a specific sequence, first is "zip," then "mmyy," then "num," etc. If there is no field, fill it as empty.
How to do this in the existing loop? Now I have a solution sort result array, but It needs to loop again.
I would use a special key and sort by the key. And - there is an elseif.
foreach ($filelines as $indexrow => $line) {
$columns = explode($splitter, $line);
$row = [];
foreach ($columns as $columnindex => $column) {
$column = $this->prepareValue($column);
$counter = 0;
if (RegexValidation::isNum($column)) {
$row['C_'.$counter++] = $this->setValue('num', $column, $indexrow, $columnindex);
} elseif (RegexValidation::isMMYY($column)) {
$row['B_'.$counter++] = $this->setValue("mmyy", $column, $indexrow, $columnindex);
} elseif (RegexValidation::isZip($column)) {
$row['A_'.$counter++] = $this->setValue("zip", $column, $indexrow, $columnindex);
} else { // If there is no field, fill it as empty
$row['Z_'.$counter++] = '';
}
}
ksort($row);
$dataset[$indexrow] = array_values($row);
}
Use A for the group you want to have first, then B for the group you want next, and so on. If you want to preserve the order within the group, you should have leading zeros on the counter, because A_10 ist sorted before A_9. Change that to A_09, or A_000009 depending on the size of your dataset.
I am trying to expand/multiply an associative array N times and get all possible key combinations.
To do it manually for two times, I would do this:
$copy = $array;
foreach ($array as $key1=>$tmp1) {
foreach ($copy as $key2=>$tmp2) {
$combos[] = array($key1,$key2);
}
}
for expanding three times:
$copy = $copy2 = $arr1;
foreach ($arr1 as $key1=>$qd1) {
foreach ($copy as $key2=>$qd2) {
foreach ($copy2 as $key3=>$qd3) {
$combos[] = array($key1,$key2,$key3);
}
}
}
how would one do this for n-times? $combos should have n-elements for each element as shown.
I looked at the other questions, but it is not quite the same here.
Finally got it:
$array = ['1' => [3, 4], '2' => [5, 6]];
$depth = 2;
function florg ($n, $elems) {
if ($n > 0) {
$tmp_set = array();
$res = florg($n-1, $elems);
foreach ($res as $ce) {
foreach ($elems as $e) {
array_push($tmp_set, $ce . $e);
}
}
return $tmp_set;
}
else {
return array('');
}
}
$output = florg($depth, array_keys($array));
What I did is basically extract the first level keys with array_keys and then created all possibles combinations thanks to https://stackoverflow.com/a/19067650/4585634.
Here's a working demo: http://sandbox.onlinephpfunctions.com/code/94c74e7e275118cf7c7f2b7fa018635773482fd5
Edit: didn't see David Winder comment, but that's basically the idea.
I'm trying to solve a somewhat simple task but can't wrap my head around doing it without a lot of loops and messy code.
I want all to print all combinations of the array below:
$product = array(
array
(
'1X'
),
array
(
'X2'
)
);
producing the following result:
//ROW 1
1
X
//ROW 2
X
2
//ROW 3
1
2
//ROW 4
X
X
this work:
$product = array(
array
(
'1WQ'
),
array
(
'3'
),
array
(
'X'
)
);
//
class Combine{
private $product = array();
private $result = array();
private $format = array();
public function __construct($p=array()){
$this->product = $p;
}
public function process(){
foreach($this->product as $k=>$v){
$this->format[] = str_split($v[0]);
}
$this->result = $this->build();
return $this;
}
public function build()
{
if (!$this->format) {
return array(array());
}
$sub = array_shift($this->format);
$c = $this->build($this->format);
$res = array();
foreach ($sub as $v) {
foreach ($c as $p) {
array_unshift($p, $v);
$res[] = $p;
}
}
return $res;
}
public function response(){
return $this->result;
}
}
//
$combine = new Combine($product);
$resp = $combine->process()->response();
var_dump($resp);
function helperFunction($array, $index, $workArray)
{
$tempArray = array();
$tmpStr = $array[$index][0];
// loop over the current array characters
for( $i = 0; $i < strlen($tmpStr); $i++ )
{
$char = substr($tmpStr, $i, 1);
// first time - add characters to the work array
if (count($workArray) == 0)
{
$tempArray[] = $char;
}
// later round - add characters to existing items
else
{
foreach ($workArray as $workItem)
{
$tempArray[] = $workItem . $char;
}
}
}
// last round
if (count($array) == $index + 1)
{
return $tempArray;
}
// recursion round
else
{
return helperFunction($array, $index + 1, $tempArray);
}
}
$result = helperFunction($product, 0, array());
I have a multidimensional array $array["A"]["B"]["C"]["D"]. The list is longer.
Is there a wildcard that I can use to get ["D"] value in let say ["B"] array?
Something like this, $array["A"]["B"][*]["D"] ?
or $array[*]["B"][*]["D"] ?
Example, I would like to get all prices that were bought on February regardless of the year.
$array[2013][2][23]["ItemName"]["ItemPrice"] .....
If this would work, it would be really wonderful
$array[*][2][*][*]["ItemPrice"]..
any idea?
You could do multiple foreach to loop though every nested array that you want to loop though.
foreach ($array as $a) {
foreach ($a["B"] as $c) {
foreach ($c as $d) {
// Do something with $d
}
}
}
This would be $array[*]["B"][*][*]
Edit: You could combine my suggestion with a while loop.
$innerArray = $array;
while (true) {
foreach ($array as $key => $value) {
if ($key == "D") {
// Do something with this value
} else if (is_array($value)) {
$innerArray = $value;
} else {
break;
}
}
}
Thanks to #Sepehr-Farshid it just crossed my mind that I can use recursive function (Something that I haven't use for quiet a while. So here a example.
$newarray = array();
$tempArray = $oldarray;
$levels[] = 1;
$keys[] = 2;
$levels[] = 4;
$keys[] = "ItemPrice";
$lastLevel =4;
recurArray($tempArray, 0);
function recurArray($array, $level)
{
foreach($array as $key => $value) {
if(array_search($level, $GLOBALS["levels"]) {
$tempKey = array_search($level, $GLOBALS["levels"];
if($key == $GLOBALS["keys"][$tempKey] {
if($level == $GLOBALS["lastLevel"]) $GLOBALS["newarray"] = $value;
else recurArray($value, $level + 1);
}
else { return; }
}
else { recurArray($value, $level + 1); }
}
}
this might not be the optimum way, but it will work and can be refined. :D
Please consider this example
Array
(
[1] => search engine optimization
[2] => engine optimization
[0] => search engine
)
I want to remove engine optimization and search engine because these words are already in the longest phrase. These words are not hard coded, the above result is generated by a function. I did my best to code it but couldn't solve this problem.
EDIT
This is my attempt, looks like people here don't trust and they are good at pressing vote down button. My approach is not adequate so I didn't bother to share it here.
$result = array('search engine', 'search engine optimization', 'engine optimization');
uasort($result, 'string_word_length');
foreach($result as $key=>$phrase) {
if( ($found = array_find($phrase, $result, $key)) != FALSE) {
unset($result[$found]);
}
}
function array_find($needle, $haystack, $skip_key = 0) {
if(!is_array($haystack)) return false;
foreach($haystack as $key=>$value) {
if($skip_key != $key && strpos($value, $needle)!==false) {
echo 'Poped ', $value, ' -- ', $key, ' -- ', $skip_key, '<br />';
return $key;
}
}
return false;
}
function string_word_length($a,$b){
return strlen($b) - strlen($a);
}
What about this (supposing you use php >= 5.3):
$src = array('search engine optimization',
'engine optimization',
'search engine');
$src_array = array();
foreach ($src as $val) {
$src_array[] = explode(' ', $val);
}
usort($src_array, function($a, $b) { return count($a) > count($b); });
foreach ($src_array as $key => $val) {
if ($key + 1 < count($src_array)) {
foreach ($val as $word_key => $word){
for ($i = $key + 1; $i <= count($src_array) - 1; $i++) {
if (in_array($word, $src_array[$i])) {
unset($src_array[$key][$word_key]);
}
}
}
}
}
$result = array_filter($src_array, function($i) { return count($i) > 0; });
$result = array_map(function($i) { return implode(' ', $i); }, $result);
$result = array_values($result);
var_dump($result);
For those who doesn't have php 5.3 installed here is the output result: array(1) { [0]=> string(26) "search engine optimization" }