Last active
August 29, 2015 14:10
-
-
Save strategio/aab09506da23f3c59013 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* | |
* The challenge is to split an array of integer in various groups, | |
* trying to have the sum of each group closer to each other... | |
* | |
* split-challenge.php | |
* 04-dec-2014 | |
* | |
* @package Divider | |
* @author Strategio <[email protected]> | |
*/ | |
Class Divider { | |
private $values; | |
private $split; | |
private $target; | |
public function __construct($values=array(), $split=1) | |
{ | |
// Set values and split if defined | |
$this->setValues($values); | |
$this->setSplit($split); | |
} | |
/** | |
* Set values to split | |
* @param array | |
* @return Divider | |
*/ | |
public function setValues($values) | |
{ | |
$this->values = $values; | |
return $this; | |
} | |
/** | |
* Set number of groups to split | |
* @param integer | |
* @return Divider | |
*/ | |
public function setSplit($split) | |
{ | |
// Avoid dividing by zero | |
if(0 == $split) | |
$split = 1; | |
$this->split = abs($split); | |
return $this; | |
} | |
/** | |
* Main method to create and dispatch the groups | |
* Then display the results | |
* @param void | |
* @return void | |
*/ | |
public function resolve() | |
{ | |
// Define target | |
$this->target = round(array_sum($this->values) / $this->split); | |
// Sort values | |
asort($this->values); | |
// Invert sort from biggest to smallest | |
$this->values = array_reverse($this->values); | |
// For each group, make iteration | |
$groups = array(); | |
for($i=0; $i<$this->split; $i++) { | |
$group = array(); | |
$target = $this->target; | |
while ($target > 0) { | |
$value = $this->_use_closer_to_target($target); | |
$group[] = $value; | |
$target = $target - $value; | |
if(count($this->values) == 0) | |
break; | |
} | |
$groups[$i] = $group; | |
} | |
// Display results | |
foreach ($groups as $key => $value) { | |
echo '<p>'.implode(' + ', $value).' = '.array_sum($value).'</p>'; | |
} | |
} | |
/** | |
* Find the closest number from target within | |
* the values array. Then remove this value from the array | |
* and returns it. | |
* @param integer | |
* @return integer | |
*/ | |
private function _use_closer_to_target($target) | |
{ | |
$best_gap = false; | |
$best_gap_key = false; | |
foreach ($this->values as $key => $value) { | |
$gap = abs($target - $value); | |
// Compare current gap to best gap | |
if(false == $best_gap || $gap < $best_gap) { | |
$best_gap = $gap; | |
$best_gap_key = $key; | |
} | |
// don't go further if target reached | |
if(0 == $gap) | |
break; | |
} | |
$value = $this->values[$best_gap_key]; | |
unset($this->values[$best_gap_key]); | |
return $value; | |
} | |
} | |
?> | |
<html> | |
<head> | |
<title>Defi</title> | |
</head> | |
<body> | |
<form> | |
<input type="text" name="values" placeholder="Values" value="<?php echo isset($_GET['values']) ? $_GET['values'] : ''; ?>" style="width:300px"> | |
<input type="number" name="split" placeholder="Split" value="<?php echo isset($_GET['split']) ? $_GET['split'] : '1'; ?>"> | |
<button name="resolve">Resolve</button> | |
</form> | |
<pre> | |
<?php | |
$values = explode(',', $_GET['values']); //array(1,14,12,8,6,5,11,9,7,2,2,4,7,1,6,2,8); | |
$split = $_GET['split']; | |
$divider = new Divider(); | |
$divider->setValues($values)->setSplit($split)->resolve(); | |
?> | |
</pre> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment