Angenommen, ich habe eine Liste von Zahlen, und ich muss wissen, wie viele Elemente ich von Anfang an auswählen müsste, um mindestens die gewünschte Summe zu erhalten.Gibt es eine funktionale Programmiersprache für "vom Anfang einer Liste auswählen und reduzieren, bis das Ergebnis ein Prädikat erfüllt"?
Der Algorithmus ist trivial: Ich wähle Zahlen vom Anfang der Liste, bis die Summe aller ausgewählten Zahlen einen bestimmten Betrag übersteigt.
ich es in imperativen Stil so schreiben könnte:
fun pickEnough(list: List<Double>, enough: Double): List<Double>? {
var soFar = 0.0
var index = 0
for (index in 0..list.size) {
soFar += list[index]
if (soFar > enough) {
return list.subList(0, index)
}
}
return null
}
Eine ineffiziente, aber allgemeinere Lösung alle möglichen Teil-Listen generieren würde und die erste, deren Reduktion Pick Ergebnis ist gut genug:
fun <T> pickEnough(list: List<T>, reducer: (T, T) -> T, enough: (T) -> Boolean): List<T>? =
list.indices
.map { index -> list.sublist(0, index) }
.first { sublist -> enough(sublist.reduce(reducer)) }
pickEnough(listOf(5,8,0,0,8), { a, b -> a + b}, { it > 10 }) // [5, 8]
Gibt es ein festgelegtes funktionales Idiom dafür, oder vielleicht eine Kombination von solchen, die in der Leistung und Ausdruckskraft besser sind als mein Versuch, dieses Stück zu verallgemeinern?
Das Beispiel ist in Kotlin, aber ich würde eine sprachunabhängige Antwort bevorzugen, obwohl Antworten in jeder Sprache geschätzt werden, solange sie höhere Idiome darstellen, die diese Operation beschreiben.
Ja, Haskell hat ähnliche 'scanl' (& c) -Funktionen: https://en.wikipedia.org/wiki/Prefix_sum#Scan_higher_order_function –
Diese Antwort ist nicht in Kotlin, und ist nicht direkt tragbar. –
@JaysonMinard - Die Frage fragt nach einer sprachunabhängigen Antwort und 'scan' und' takeWhile' sind sprachunabhängige Konzepte. – Lee