Как реализовать многопоточность для рекурсивной функции - PullRequest
0 голосов
/ 05 мая 2018

Рассмотрим простую игру для двух игроков, в которую играют следующим образом: в ряд выложено четное количество монет. По очереди каждый игрок убирает монету на одном из концов ряда. Цель состоит в том, чтобы иметь наибольшее значение в монетах, когда все монеты были взяты.

Игрок один находит сумму всех монет с четным номером и всех монет с нечетным номером. Если сумма монет с нечетным номером выше, игрок один берет самую левую монету; в противном случае он берет самое правое.

У второго игрока теперь есть выбор с нечетным количеством монет. Взятие первой или последней монеты приведет к несколько другому списку монет для первого игрока. Второй игрок использует результат рекурсивного поиска, чтобы определить, выбрать первую или последнюю монету.

И я хочу иметь возможность каким-то образом реализовать многопоточность в рекурсивной функции p2-helper, только теперь убедитесь, как это сделать. Любые предложения или идеи будут с благодарностью, спасибо!

(ns game.core
  (:gen-class))

; function that returns the vector of a string (split up by spaces)
(defn vector-from-string [s]
  (drop 1 (map read-string (clojure.string/split (clojure.string/trim-newline s) #" "))))

; function that returns the slurped string of a read-in file
(defn string-from-file [f]
  (slurp f))

; function that returns the sum of all the odd-indexed items in a vector
(defn sum-of-evens [v]
  (reduce + (take-nth 2 (rest v))))

; function that returns the sum of all the odd-indexed items in a vector
(defn sum-of-odds [v]
  (reduce + (take-nth 2 v)))

; function that returns the vector that is left after player one moves, and then the coin that player one took
(defn p1 [v]
  (if (> (sum-of-odds v) (sum-of-evens v))
    [(drop 1 v) (first v)]
    [(drop-last v) (last v)]))

; nearly identical to 'p1' but this function only returns the affected vector after player 1 has moved
(defn p2-p1 [v]
  (if (even? (count v))
    (if (> (sum-of-odds v) (sum-of-evens v))
      (drop 1 v)
      (drop-last v))
    (drop 0 v)))

; recursive search for player two
(defn p2-helper [v]
  (if (or (= (count v) 1) (= (count v) 0))
    (reduce + v)
    (max (+ (p2-helper (drop 1 (p2-p1 v))) (first (p2-p1 v))) (+ (p2-helper (drop-last (p2-p1 v))) (last (p2-p1 v))))))

; function that returns the vector that is left after player two moves, and then the coin that player two took
(defn p2 [v]
  (if (> (+ (p2-helper (drop 1 (p2-p1 v))) (first (p2-p1 v))) (+ (p2-helper (drop-last (p2-p1 v))) (last (p2-p1 v))))
    [(drop 1 v) (first v)]
    [(drop-last v) (last v)]))

; function to play the game out until no coins are left
(defn play-game [v]
  (def coins v)
  (def p1score 0)
  (def p2score 0)
  (while (not (empty? coins))
    (do
      (let [[new-vec score] (p1 coins)]
        (def coins new-vec)
        (def p1score (+ p1score score)))
      (let [[new-vec score] (p2 coins)]
        (def coins new-vec)
        (def p2score (+ p2score score)))))
  (println "player 1 score:" p1score)
  (println "player 2 score:" p2score))

; main
(defn -main [& args]
  (let [v (vector-from-string (string-from-file "10.txt")) ]
    (play-game v)))

1 Ответ

0 голосов
/ 05 мая 2018

Первоначальный подход заключается в добавлении @(future (p2-helpet ... вокруг каждого рекурсивного вызова. это, вероятно, будет запускать слишком много потоков и работать медленнее.

вторым подходом может быть изменение помощников для помещения работы в очередь задач и создания некоторых потоков для их обработки. это будет лучше, хотя все еще может быть медленнее.

Я бы продолжил улучшать его, развернув рекурсию с помощью вызова trampoline, чтобы остановить его перебор стека. затем попробуйте сделать параллельный верхний уровень или два верхних уровня.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...