2016-09-28 2 views
1

Учитывая дерево, закодированное как набор вложенных списков (например, (+ 2 (+ 2 1) (+ 1 3 2))), существует ли известный алгоритм в Clojure, который стохастически пересекает дерево, применяя параметрически поставленную функцию в одном узле с равной вероятностью «посадки» на любом узле? Примечание: прогулка заканчивается после преобразования одного узла.стохастический обход дерева в Clojure

Я ожидаю, что алгоритм должен вести себя следующим образом:

(def tree '(1 (1 (1 1 1) 1) 1)) 
(stochastic-tree-f-app inc tree) => (1 (1 (1 2 1) 1) 1) 
(stochastic-tree-f-app inc tree) => (1 (1 (1 1 2) 1) 1) 
(stochastic-tree-f-app inc tree) => (2 (1 (1 1 1) 1) 1) 
(stochastic-tree-f-app inc tree) => (1 (1 (1 1 1) 1) 2) 
(stochastic-tree-f-app dec tree) => (1 (1 (1 1 1) 0) 1) 
+0

Так как только вы трансформировали один узел, прогулка закончится, это правильно? – ClojureMostly

+0

@ClojureMostly, да, это правильно –

+0

Решение, которое приходит на ум: 1. Пройдите дерево через bfs или dfs, возвращая количество узлов 2. подайте это число на генератор случайных чисел, подавая результат (между 0 и n) до 3. третьего d/bfs, который пересекает граф число раз, заданное генератором случайных чисел 4. apply f –

ответ

4

Использование clojure.zip:

(require '[clojure.zip :as z]) 

(defn stochastic-tree-f-app [f tree] 
    (let [zp (z/zipper list? seq (fn [_ c] c) tree) 
     nodes (->> (iterate z/next zp) 
        (take-while (complement z/end?)) 
        (filter (comp integer? z/node)) 
        (into []))] 
    (-> (rand-nth nodes) 
     (z/edit f) 
     z/root))) 
+1

это более красивый –

1

Вы можете просто использовать clojure.walk если последнее требование может быть снято (т.е. ... прогулка заканчивается после того, как один узел преобразуется). Или пройдите по узлам с помощью молнии и завершите редактирование. Использование clojure.walk:

(use 'clojure.walk) 

(def tree '(1 (1 (1 1 1) 1) 1)) 

(defn stochastic-tree-f-app [f tree] 
    (let [cnt (atom 0) 
     _ (postwalk #(if (integer? %) (swap! cnt inc)) tree) 
     idx (rand-int @cnt)] 
    (reset! cnt 0) 
    (postwalk #(if (and (integer? %) (= idx (swap! cnt inc))) 
       (f %) 
       %) 
       tree))) 

user> (stochastic-tree-f-app inc tree) 
(2 (1 (1 1 1) 1) 1) 
user> (stochastic-tree-f-app inc tree) 
(1 (1 (1 1 1) 2) 1) 
+0

это прекрасный –

Смежные вопросы