Я решал задачу программирования на Ruby, и после ее завершения я подумал, что мне следует попробовать применить свои ограниченные знания Clojure для реализации того же самого. Я потратил немало времени, но не смог заставить его работать.
Задача: у нас есть массив типов монет и ожидаемая сумма. Как лучше всего представить ту сумму с имеющимися у нас типами монет, тратя минимальное количество монет. Таким образом, для представления 325 с типами монет [100, 50, 20, 10, 5] мы бы получили следующий результат: [100, 100, 100, 20, 5].
Вот мой код Ruby, который, кажется, работает:
def calc(coin_types, expected)
calc_iter(coin_types.sort.reverse, expected, [])
end
def calc_iter(coin_types, expected, coins)
sum = coins.sum
return coins if sum == expected
return nil if sum > expected
coin_types.each do |type|
result = calc_iter(coin_types, expected, coins + [type])
return result if result
end
nil
end
# test
calc([25, 10], 65) # should return [25, 10, 10, 10, 10]
А теперь две из моих неудачных реализаций Clojure:
1) (чтобы бежать, нужно вечно, поэтому мне пришлось его убить):
(defn calc [types expected]
(let [types (reverse (sort types))]
(loop [coins []]
(let [sum (count coins)]
(if (= sum expected)
coins
(if (> sum expected)
nil
(first (filter #(not (nil? %))
(map #(recur (cons % coins))
types)))))))))
2) (этот завершает за разумное количество раз, но возвращает неправильный результат):
(defn calc-iter [types expected coins]
(let [sum (count coins)]
(if (= sum expected)
coins
(if (> sum expected)
nil
(first (filter #(not (nil? %))
(map #(calc-iter types
expected
(cons % coins))
types)))))))
(defn calc [types expected]
(calc-iter (reverse (sort types))
expected
[]))