You've got all the correct combinations now, but you're still checking many more than you need to (as evidenced by the many permutations your result shows). Also, you're omitting the last item that hits the 15.05 mark.
I have a PHP version that does 209 iterations of the recursive call (it does 2012 if I get all permutations). You can reduce your count if right before the end of your loop, you pull out the item you just checked.
I don't know CF syntax, but it will be something like this:
<cfelse>
<!--- less than 15.50 --->
<!--<cfoutput>#arguments.currentCombo# < 15.05 (traversing)</cfoutput><br />-->
<cfset found = testCombo(CC, CT, arguments.apps) />
------- remove the item from the apps array that was just checked here ------
</cfif>
</cfloop>
EDIT: For reference, here's my PHP version:
<?
function rc($total, $string, $m) {
global $c;
$m2 = $m;
$c++;
foreach($m as $i=>$p) {
if ($total-$p == 0) {
print "$string $i\n";
return;
}
if ($total-$p > 0) {
rc($total-$p, $string . " " . $i, $m2);
}
unset($m2[$i]);
}
}
$c = 0;
$m = array("mf"=>215, "ff"=>275, "ss"=>335, "hw"=>355, "ms"=>420, "sp"=>580);
rc(1505, "", $m);
print $c;
?>
Output
mf mf mf mf mf mf mf
mf hw hw sp
209
EDIT 2:
Since explaining why you can remove the elements will take a little more than I could fit in a comment, I'm adding it here.
Basically, each recursion will find all combinations that include the currently search element (e.g., the first step will find everything including at least one mixed fruit). The easiest way to understand it is to trace the execution, but since that will take a lot of space, I'll do it as if the target was 6.45.
MF (2.15)
MF (4.30)
MF (6.45) *
FF (7.05) X
SS (7.65) X
...
[MF removed for depth 2]
FF (4.90)
[checking MF now would be redundant since we checked MF/MF/FF previously]
FF (7.65) X
...
[FF removed for depth 2]
SS (5.50)
...
[MF removed for depth 1]
At this point, we've checked every combination that includes any mixed fruit, so there's no need to check for mixed fruit again. You can use the same logic to prune the array at each of the deeper recursions as well.
Tracing through it like this actually suggested another slight time saver -- knowing the prices are sorted from low to high means that we don't need to keep checking items once we go over the target.