Tamam, bu sorun aslında lineer dizilerinin etrafında dönmektedir. 1 minimum değeri ile diziyi göz önünde bulundurun:
f(n) = 1 + 2 + ... + n - 1 + n
Böyle bir dizisinin toplamı eşittir:
f(n) = n * (n + 1) / 2
yani n = 4 için, bir örnek olarak, toplamı 10 olan 4 farklı numaralar hiçbir sıfır ile asgari toplam seçiyoruz ve hiçbir olumsuzluk 10 ise bu demektir Şimdi tersten gidin:.. Eğer 10 toplam ve varsa 4 sayı sonra tek bir combination (1,2,3,4) orada olduğunu.
Yani ilk sizin toplam alt sınır olarak en az yüksek olup olmadığını kontrol etmeniz gerekir. Daha az ise, hiçbir söz yok. Eşit ise, bir arada tam olarak mevcuttur. Eğer daha yüksek olursa daha karmaşık alır.
Şimdi kısıtlamaları 12 4 ile sayılar toplam vardır hayal. Biz f (4) = 10 olduğunu tespit ettik. Ama eğer ilk (en düşük) sayı 2 nedir?
2 + 3 + 4 + 5 = 14
Yani ilk sayı 1'den yüksek olamaz. Size ilk numarayı biliyorum. Şimdi 11 (12-1 olmak) toplam 3 sayı dizisi oluşturur.
1 + 2 + 3 = 6
2 + 3 + 4 = 9
3 + 4 + 5 = 12
İkinci sayı biri olamaz çünkü 2 olmak zorundadır. 3 ile başlayan, üç sayı minimum toplamı 12 ve biz 11 eklemek zorunda çünkü 3 olamaz.
3 mümkün olan en düşük olmak (2 - 1 - 12) Şimdi 9'a kadar eklemek iki numaralarını bulabilirsiniz.
3 + 4 = 7
4 + 5 = 9
Üçüncü sayı 3 veya 4 olabilir. Üçüncü sayı son sabittir bulundu ile. Iki olası kombinasyonlar:
1, 2, 3, 6
1, 2, 4, 5
Sen genel bir algoritma içine bu açabilirsiniz. Bu yinelenen bir uygulama düşünün:
$all = all_sequences(14, 4);
echo "\nAll sequences:\n\n";
foreach ($all as $arr) {
echo implode(', ', $arr) . "\n";
}
function all_sequences($total, $num, $start = 1) {
if ($num == 1) {
return array($total);
}
$max = lowest_maximum($start, $num);
$limit = (int)(($total - $max) / $num) + $start;
$ret = array();
if ($num == 2) {
for ($i = $start; $i <= $limit; $i++) {
$ret[] = array($i, $total - $i);
}
} else {
for ($i = $start; $i <= $limit; $i++) {
$sub = all_sequences($total - $i, $num - 1, $i + 1);
foreach ($sub as $arr) {
array_unshift($arr, $i);
$ret[] = $arr;
}
}
}
return $ret;
}
function lowest_maximum($start, $num) {
return sum_linear($num) + ($start - 1) * $num;
}
function sum_linear($num) {
return ($num + 1) * $num / 2;
}
Çıktı:
All sequences:
1, 2, 3, 8
1, 2, 4, 7
1, 2, 5, 6
1, 3, 4, 6
2, 3, 4, 5
Bunun bir uygulama tüm dizileri almak ve rastgele birini seçmek için olacaktır. Bu, ya da ne yaptığınızı için yararlı veya gerekli olmayabilir eşit olası tüm kombinasyonları ağırlıklandırılarak avantajına sahiptir.
Bu, büyük toplamları veya yukarıda algoritma yerine her değer $limit
ile $start
aralığında rastgele elemanı döndürmek için değiştirilebilir, bu durumda elemanları, büyük sayılarla hantal hale gelecektir .