Skip to content

Instantly share code, notes, and snippets.

@strategio
Last active August 29, 2015 14:10
Show Gist options
  • Save strategio/aab09506da23f3c59013 to your computer and use it in GitHub Desktop.
Save strategio/aab09506da23f3c59013 to your computer and use it in GitHub Desktop.
<?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 <strategio@strategio.fr>
*/
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