Я не знаю, как вы устанавливаете вес.
Но учтите:
[2,3,6,10,20]
and needed = 21
Тогда алгоритм не найдет его (без совпадения), когда очевидно решение: 2 + 3 + 6 + 10
Итак, вы должны рекурсивно вызывать алгоритм поиска, когда он не работает, после удаления из весов первого выбранного вами значения.
Это не очень чисто, но, кажется, работает (в коде, некоторые проблемы на детской площадке)
func searchIt(weightsSearch: [Int], neededSearch: Int) -> (needs: [Int], remainingWeights: [Int], found: Bool) {
var total = neededSearch // The current working total
var needs = [Int]() // The resulting weights needed
var remaining = weightsSearch
var firstNotYetSelected = true
var position = weightsSearch.count - 1
for weight in weightsSearch.reversed() {
if weight <= total {
needs.append(weight)
total -= weight
if firstNotYetSelected {
remaining.remove(at : position)
}
firstNotYetSelected = false
position -= 1
}
}
return (needs, remaining, total == 0)
}
var needs = [Int]() // The resulting weights needed
var remainingWeights = weights
var foundIt: Bool
repeat {
(needs, remainingWeights, foundIt) = searchIt(weightsSearch: remainingWeights, neededSearch: needed)
if foundIt {
print("Need \(needs) for \(needed)")
break
} else {
print("No match yet for \(needed)")
}
} while remainingWeights.count >= 1
с тестовым набором
let weights = [2,3,6,10,20]
let needed = 21
получаем
No match yet for 21
Need [10, 6, 3, 2] for 21
Если вам нужны ВСЕ решения, замените оператор break на continue.
С тестовым набором
let weights = [2,3,6,10,15,20]
let needed = 21
мы получаем 2 решения
No match for 21
No match for 21
Need [15, 6] for 21
Need [10, 6, 3, 2] for 21
No match for 21
No match for 21
No match for 21