PHP on how to auto combine values in array to given sum

I would like to sum up value(s) in the array to match the nearest answer to given sum number.

  • Following scenario/example is provided 1-5 items, sum up each values to 200 (minimum).
  • If combination of 2 values are 200, then return the keys.
  • Combination of items up to 3 items only. Given 4 items, if combination of 2 items are 205, while other combinations are 210, pick up the first 2 combinations.

I have read and study from many PHP resources but there’s none I can easily and fully understand how to solve my problems for my PHP application.

Given 2 tables as following, my coding only work on either if I change the logical operator.

How to make the coding works for both. Kindly point out mistake form my coding and suggest a solution for me.

Table A:

Item | Name       | Price
----- ------------ --------
1    | Adidas     | 190.00
2    | Nike Run   | 170.00
3    | Puma       | 110.00
4    | Nike Women |  30.00   

The working code for above table A:

$values = [
    1=>320;
    2=>50;
    3=>120;
    4=>10;
    5=>30;
];
echo implode(',', getKeys($values,200));

function getKeys($array, $min, $keys=array())
{	
	// Select the smallest value that less than given value.
	if(empty($keys)){
		$keep[] = array(0,0);
		foreach($arrays as $key=>$value){
			$keep[1] = isset($keep[1]) ? $keep[1] : null;
			if($value <= $min && $value > $keep[1] ){
				$keep[0]=$key;
				$keep[1]=$value;
				break 1;
			}else{
				//$keep[0]=$key;
				$keep[1]=$value;
			}	
		}
		$keys[] = $keep[0];
	}

	$total = 0;
	foreach($keys as $key){
		if(!empty($arrays)){
			$total += $arrays[$key];
		}
	}

	if($total >= $min){
		$keep[] = array(0,0);				
		$keep[1] = $total;
		
		foreach($arrays as $key=>$value){
			if($value >= $min && $value < $keep[1] && !in_array($key, $keys)){
				$keep[0]=$key;
				$keep[1]=$value;
				break 1;
			}
		}
			
		if($total <= $keep[1]){
			if(count($keys) > 3){
				//Restricted only 3 keys to be return, remove smallest value
				$keep[] = array(0,0);		
				
				foreach($arrays as $key=>$value){
					$keep[1] = isset($keep[1]) ? $keep[1] : null;
					if($value <= $min && $value < $keep[1]){
						$keep[0]=$key;
						$keep[1]=$value;
						break 1;
					}else{
						$keep[0]=$key;
						$keep[1]=$value;
					}	
				}
				for($z = 0; $z < count($keys); $z++){
					if($keys[$z] == $keep[0]){
						unset($keys[$z]);
					}
				}
				return $this->getCamp1($array, $min, $keys);
			}else{
				sort($keys);
				return $keys;
			}
		}else{
			unset($keys);
			$keys[] = $keep[0];
			return $this->getKeys($array, $min, $keys);
		}
	}else{
		// Select the next value that can exceed min
		if(!empty($keys)){
			$next = NULL;
			$arrays = array_keys($array);				
			foreach($arrays as $key=>$value){	
				if($value < $min && ($value + $total) >= $min && !in_array($key,$keys)){
					$next=$key;
					break 1;
				}
			}
		}

		if(empty($next)){
			// Pick the next biggest value that less than minimum value ($200)
			$keep[] = array(0,0);				
			$counterCamp = count($array);
			
			foreach($arrays as $key=>$value){
				$keep[1] = $min; 
				if($value < $min && $value < $keep[1]  && !in_array($key, $keys)){
					$keep[0]=$key;
					$keep[1]=$value;
					break 2;
				}else{
					$keep[1]=$value;
				}	
				$counterCamp--;
			}						
			
			//	Reselect value more than 200			
			if($counterCamp == 0){
				foreach($arrays as $key=>$value){
					if($value > $min && $value < $keep[1] && !in_array($key, $keys)){
						$keep[0]=$key;
						$keep[1]=$value;	
						unset($keys);
						break 2;
					}else{
						$keep[0]=$key;
						$keep[1]=$value;
						unset($keys);
						break 2;			
					}
				}
			}						
			$keys[] = $keep[0];
			return $this->getKeys($array, $min, $keys);
		}else{
			$keys[] = $next;
			return $this->getKeys($array, $min, $keys);
		}
	}
}

Expected Result:

Item | Name       | Price
----- ------------ --------
2    | Nike Run   | 170.00
4    | Nike Women |  30.00  

Following table B is not working unless update following coding

Table B:

Item | Name       | Price
----- ------------ --------
1    | Adidas     |  90.00
2    | Nike Run   | 180.00
3    | Puma       |  15.00
4    | Nike Women |  25.00

The working code for above table B:

	// Select the smallest value that less than given value.
	if(empty($keys)){
		$keep[] = array(0,0);
		foreach($arrays as $key=>$value){
			$keep[1] = isset($keep[1]) ? $keep[1] : null;
			if($value <= $min && $value < $keep[1] ){
				$keep[0]=$key;
				$keep[1]=$value;
				break 1;
			}else{
				//$keep[0]=$key;
				$keep[1]=$value;
			}	
		}
		$keys[] = $keep[0];
	}

Desired Result:

Item | Name       | Price
----- ------------ --------
2    | Nike Run   | 180.00
4    | Nike Women |  25.00

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.