Het is tijd op de oplossing prijs te geven. Ik zal beginnen met de oplossing van EternalFlamez. Deze oplossing geeft het juiste resultaat, en er is geen gebruik gemaakt van recursie.
<?php
$arr = array(7);
base();
function base() {
global $arr;
show();
while(getLastNotOne() != -1) {
doItAll();
show();
}
}
function doItAll() {
global $arr;
$c = count($arr);
//Pakt achterste waarde die groter is dan 1
$i = getLastNotOne();
//Verkleint het getal gevonden op pos $i. (4 -> 3 + 1 // 3 -> 2 + 1 // 2 -> 1 + 1)
array_splice($arr, $i, count($arr) - $i, decreaseAtPos($arr, $i));
//Als er een getal groter is dan de 1e is het een duplicaat (4 + 2 == 2 + 4)
while(isOneLargerThanPrev() != -1) {
$k = isOneLargerThanPrev();
//Als het een duplicaat is dan moet er gewoon doorgegaan worden.
array_splice($arr, $k, count($arr) - $k, decreaseAtPos($arr, $k));
}
}
//Er wordt een subarray gemaakt van $arr die begint op $pos.
//Als alleen de 1e geen 1 is, worden ze samengevoegd. (Zie count_ones())
//Anders wordt de 1e waarde verlaagd, en een 1 toegevoegd aan het einde van de array.
//Bijv: $arr = array(4, 2, 1); De subarray wordt array(2, 1), die wordt dan door deze functie array(1, 1, 1).
//Dit wordt dan weer teruggevoegd in de originele array, waardoor het array(4, 1, 1, 1) wordt.
function decreaseAtPos($arr, $pos) {
$arr = array_splice($arr, $pos);
if(count($arr) > 1) {
$c = count_ones();
if($c == count($arr) - 1) {
array_splice($arr, 1, count($arr), array($c + 1));
}
else {
array_push($arr, 1);
}
}
else {
array_push($arr, 1);
}
$arr[0]--;
return $arr;
}
//Displayt de array.
function show() {
global $arr;
$count = count($arr);
$text = '';
for($i = 0; $i < $count; $i++) {
if($i != 0) {
$text .= ' + ';
}
$text .= $arr[$i];
}
echo($text. '<br/>');
}
//Returnt achterste waarde die groter is dan 1.
function getLastNotOne() {
global $arr;
$c = count($arr);
for($i = $c - 1; $i >= 0; $i--) {
if($arr[$i] != 1) {
return $i;
}
}
return -1;
}
//Telt aantal enen om te mergen zodra het klaar is met een reeks.
//Bijv: (4 + 2 => 4 + 1 + 1 => 3 + 3)
function count_ones() {
global $arr;
$r = 0;
$c = count($arr);
for($i = 0; $i < $c; $i++) {
if($arr[$i] == 1) {
$r++;
}
}
return $r;
}
//Kijkt of de waarde al langs is geweest. Returnt -1 als het niet zo is, anders getLastNotOne().
function isOneLargerThanPrev() {
global $arr;
$c = count($arr);
$smallest = $arr[1];
for($i = 1; $i < $c; $i++) {
if($arr[$i] > $smallest || $arr[$i] > $arr[0]) {
return getLastNotOne();
}
else {
$smallest = $arr[$i];
}
}
return -1;
}
?>
Toon Meer
De oplossing van victor geeft op dit moment nog niet exact het juiste resultaat. Hij is er nog mee bezig en wil dat nog oplossen. Zijn oplossing geeft wel alle oplossingen maar enkele dubbele (2 + 1 + 1 en 1 + 2 + 1 bijvoorbeeld). Zijn oplossing is (tot nu toe) als volgt:
<?php
function get_numbers($getal)
{
$oplossingen = array();
if($getal == 1)
{
array_push($oplossingen, '1');
}
for($i = 1; $i < $getal ; $i++)
{
foreach(get_numbers($getal-$i) as $oplossing)
{
array_push($oplossingen, $oplossing.'+'.$i);
}
}
array_push($oplossingen, $getal);
$oplossingen = array_unique($oplossingen);
return $oplossingen;
}
echo '<pre>';
print_r(get_numbers(4));
echo '</pre>';
?>
Toon Meer
Dan als laatste nog mijn eigen oplossing, die wel gebruik maakt van recursie:
<?php
function getPartitions($number, $previous = -1, $prefix = "") {
if($number <= $previous || $previous == -1) {
echo $prefix . $number . "<br />\n";
}
for($i = 1; $i < $number; $i++) {
if(($number - $i) <= $previous || $previous == -1) {
getPartitions($i, ($number - $i), $prefix . ($number - $i) . " ");
}
}
}
echo getPartitions(7);
Toon Meer
Wat vinden jullie van de oplossingen? En wat vinden jullie van de uitdaging? Is dit voor herhaling vatbaar? Zou je wel meedoen als de opdracht makkelijker is (mocht je nu niet hebben meegedaan)? Ik hoor graag feedback!