Idiomatische Clojure zum Auswählen zwischen zufälligen gewichteten Auswahlen

8

Während ich in Clojure plane, habe ich ein kleines Beispielprogramm erstellt, um eine zufällige Auswahl aus einer Liste von Auswahlmöglichkeiten auszuwählen.

Die Grundidee besteht darin, über die Auswahlmöglichkeiten (denen ein Gewicht zugewiesen wurde) zu iterieren und ihre Gewichtung in einen Bereich zu drehen, dann eine Zufallszahl innerhalb des Gesamtbereichs auszuwählen, um eine auszuwählen. Es ist vielleicht nicht das eleganteste Design, aber nehmen wir es als selbstverständlich.

Was würde ich anders machen als mein Beispiel unten?

Ich bin nicht an allgemeinen Programmstrukturvorschlägen, Namensabständen usw. interessiert, hauptsächlich an Ihrem Ansatz zu jeder Funktion.

Ich bin besonders daran interessiert, wie ein erfahrener Clojurer die "Augment" -Funktion angehen würde, bei der ich die externe Variable "cur" verwenden musste, um auf das vorherige Ende des Bereichs zu verweisen.

%Vor%     
Hejazzman 22.01.2013, 17:03
quelle

4 Antworten

6

Rich Hickey's etwas veraltete (2008) Lösung von amants.clj :

%Vor%

Stuart Halloways neuere (2012) Lösung von data.generators :

%Vor%     
dribnet 04.04.2013, 22:52
quelle
6

Ich schlage vor, einige Probleme bei Ссылка zu machen, während ich Clojure lerne. Sie können den Top-Benutzern "folgen" und sehen, wie sie Probleme lösen.

Hier ist eine Lösung. Es ist wieder nicht das effizienteste, da ich darauf bedacht war, es einfach zu halten und keine fortgeschritteneren Ideen und Konstrukte zu verwenden, die du später lernen wirst.

%Vor%

Um die Gewichte in Intervalle umzuwandeln, machen wir nur eine kumulative Summe:

%Vor%

Das zufällige Intervall finden:

%Vor%

Hinweis *1 in der REPL bezieht sich auf den zuletzt gedruckten Wert, *2 auf den nächsten, usw. Wir haben also nach einer zufälligen Ganzzahl zwischen 0 (inklusive) und 33 (exklusiv) gefragt. Diese 33 möglichen Auswahlen entsprechen der Summe der Gewichte. Als nächstes haben wir die Anzahl der Intervalle gezählt, die wir durchlaufen müssen, um diese Nummer zu finden. Hier war die Zufallszahl 13.

%Vor%

Wir finden unsere Zufallszahl 2 in. Beachten Sie, dass wir, um hier zu landen, mindestens 11, aber weniger als 31 haben müssen, also 20 Möglichkeiten, was genau das Gewicht von ... ist.

%Vor%

Also, dies alles in eine Funktion zusammenzufassen:

%Vor%

Lass es uns testen:

%Vor%     
A. Webb 22.01.2013 20:15
quelle
4

Oft hilft es, das Problem in Schichten zu lösen, die unabhängig voneinander gelöst werden können. Augment macht das sehr gut bei der Zuweisung von Bereichen, obwohl das Ergebnis mit den normalen Sequenzfunktionen schwieriger zu konsumieren ist, wenn man zufällig eine auswählt. Wenn Sie das Ziel von augment so ändern, dass es eine normale seq erzeugt, dann wird das Augmentationsproblem sauberer von der zufälligen Auswahl getrennt. Wenn die Gewichte ganze Zahlen sind, können Sie eine Liste mit der Gewichtsnummer jedes Elements erstellen und dann eine nach dem Zufallsprinzip auswählen:

%Vor%

und reduzieren Sie es dann auf eine einzige Liste:

%Vor%

und wählen Sie eins mit rand-nth :

%Vor%

ps: Kartenliterale lassen die Dinge besser aussehen: die Leserseite beschreibt diese schön

%Vor%

Verwenden Sie lassen Sie Dinge Namen innerhalb von Funktionen geben:

%Vor%     
Arthur Ulfeldt 22.01.2013 18:08
quelle
0

Die open source bigml Sampling-Bibliothek ist eine weitere Option. Ich habe es mit einigem Erfolg benutzt. Es ist viel besser dokumentiert und hat eine nette API.

    
leeor 29.08.2015 21:11
quelle

Tags und Links