clojure中的折叠散列函数
折叠散列函数将其输入(在本例中为int)分解为p长度的段并添加这些部分。如果clojure中的折叠散列函数,clojure,hash-function,Clojure,Hash Function,折叠散列函数将其输入(在本例中为int)分解为p长度的段并添加这些部分。如果(非(=(mod input p)0)),即输入的长度不是p的倍数,则最后一段的长度可以是小于p的任意长度 以下是我目前的代码: (def firstX (fn [x item] (take x (str item)))) (def remX (fn [x item] (drop x (str item)))) (def divItemEq (fn [a digits] (co
(非(=(mod input p)0))
,即输入的长度不是p的倍数,则最后一段的长度可以是小于p的任意长度
以下是我目前的代码:
(def firstX
(fn [x item]
(take x (str item))))
(def remX
(fn [x item]
(drop x (str item))))
(def divItemEq
(fn [a digits]
(cond (> digits (count (str a))) (a)
true (cons (list (firstX digits a)) (divItemEq (remX digits a) digits)))))
(def sumDigits
(fn [x]
(reduce + x)))
(def exItem1 76123451001214)
(print (sumDigits (divItemEq exItem1 3)))
此时,无限递归(堆栈溢出)发生,因为DiviItemEq中的递归条件从未满足。我试图修复此问题导致了各种类型/类型转换错误
关于如何改进
divItemEq
?我不确定您不想使用哪些其他核心功能,但我提出了以下解决方案:
(defn chars->int [chars]
(Integer/parseInt (apply str chars)))
(defn int-partition [n count]
(loop [acc [] xs (str n)]
(if (seq xs)
(recur (conj acc (chars->int (take count xs))) (drop count xs))
acc)))
(int-partition 76123451001214 3)
;; yields
[761 234 510 12 14]
(reduce + (int-partition 76123451001214 3))
;; yields
1531
请注意,此版本不是惰性的,可能不适用于大型输入。您可能希望使用修改它。我不确定您不想使用哪些其他核心功能,但我提出了以下解决方案:
(defn chars->int [chars]
(Integer/parseInt (apply str chars)))
(defn int-partition [n count]
(loop [acc [] xs (str n)]
(if (seq xs)
(recur (conj acc (chars->int (take count xs))) (drop count xs))
acc)))
(int-partition 76123451001214 3)
;; yields
[761 234 510 12 14]
(reduce + (int-partition 76123451001214 3))
;; yields
1531
请注意,此版本不是惰性的,可能不适用于大型输入。您可能希望使用修改它。这里有很多地方需要改进,第一个是使用更惯用的
defn
而不是(def name(fn
scheme。接下来是您的姓名,我发现您的姓名不太清楚。其他人已经为您指明了使用分区的方向,我同意这一点,但在下面的解决方案中,我试图遵循您方法的精神
正如你自己发现的那样,将数字转换为数字序列是很有意义的,因为我们无论如何都需要序列运算。所以让我们从这个开始:
(defn decimal-digits [number]
(letfn [(ddigits-helper [number result]
(if (number > 0)
(recur (int (/ number 10)) (conj result (mod number 10)))
result))]
(ddigits-helper number '())))
这种方法使用简单的数学来收集数字。它还显示了使用recur
进行递归,并使用累加器(result
参数)来收集中间结果
下面是两个初始函数,我们假设它们现在在数字列表上运行:
(defn new-part [number size]
(take size number))
(defn rest-part [number size]
(drop size number))
如前所述,您还可以使用分区
或在
处拆分
现在,您的主要功能可以如下所示:
(defn partition-number
[number size]
(let [digits (decimal-digits number)]
(cond (> size (count digits)) digits
true (cons (new-part digits size)
(partition-number
(digits-to-decimal (rest-part digits size))
size)))))
这在风格上与您的方法非常接近,但表明我们需要将数字转换回数字,因为这正是分区号
所期望的
(defn digits-to-decimal [digits]
(let [powers-of-ten (iterate (partial * 10) 1)
digits (reverse digits)]
(reduce +
(map-indexed (fn [position digit]
(* digit (nth powers-of-ten position)))
digits))))
但是,如果我们重新构造分区号
以同时使用带有累加器的helper函数,我们还可以使用recur
,这就是在clojure中避免递归调用时破坏堆栈的方法:
(defn partition-number
[number size]
(letfn [(partnumb-helper [digits size result]
(cond (> size (count digits)) (conj result digits)
true (recur (rest-part digits size)
size
(conj result (new-part digits size)))))]
(partnumb-helper (decimal-digits number) size '[])))
请注意,这样我们也可以随时在数字和数字之间进行转换。这里有很多地方需要改进,第一个是使用更惯用的defn
而不是(def name(fn
scheme。接下来是您的姓名,我发现您的姓名不太清楚。其他人已经为您指明了使用分区的方向,我同意这一点,但在下面的解决方案中,我试图遵循您方法的精神
正如你自己发现的那样,将数字转换为数字序列是很有意义的,因为我们无论如何都需要序列运算。所以让我们从这个开始:
(defn decimal-digits [number]
(letfn [(ddigits-helper [number result]
(if (number > 0)
(recur (int (/ number 10)) (conj result (mod number 10)))
result))]
(ddigits-helper number '())))
这种方法使用简单的数学来收集数字。它还显示了使用recur
进行递归,并使用累加器(result
参数)来收集中间结果
下面是两个初始函数,我们假设它们现在在数字列表上运行:
(defn new-part [number size]
(take size number))
(defn rest-part [number size]
(drop size number))
如前所述,您还可以使用分区
或在
处拆分
现在,您的主要功能可以如下所示:
(defn partition-number
[number size]
(let [digits (decimal-digits number)]
(cond (> size (count digits)) digits
true (cons (new-part digits size)
(partition-number
(digits-to-decimal (rest-part digits size))
size)))))
这在风格上与您的方法非常接近,但表明我们需要将数字转换回数字,因为这正是分区号
所期望的
(defn digits-to-decimal [digits]
(let [powers-of-ten (iterate (partial * 10) 1)
digits (reverse digits)]
(reduce +
(map-indexed (fn [position digit]
(* digit (nth powers-of-ten position)))
digits))))
但是,如果我们重新构造分区号
以同时使用带有累加器的helper函数,我们还可以使用recur
,这就是在clojure中避免递归调用时破坏堆栈的方法:
(defn partition-number
[number size]
(letfn [(partnumb-helper [digits size result]
(cond (> size (count digits)) (conj result digits)
true (recur (rest-part digits size)
size
(conj result (new-part digits size)))))]
(partnumb-helper (decimal-digits number) size '[])))
请注意,这样我们也可以随时在数字和数字之间转换。您已经解释了实际行为(StackOverflowerError
);您可以给出预期/期望的行为吗?期望的行为:(diviteeq exItem1 3)计算为((761)(234)(510)(012)(14)),传递给sumDigits。该应用程序产生1531。旁注:我在第二次检查时更正了递归情况。我预计我的问题源于我对Clojure类型系统的初步理解。改用。我希望避免内置函数,但感谢分区@jmargolisvtI su的建议假设我的问题是将int输入转换为类似lat(原子列表)的东西,您已经解释了实际行为(StackOverflowerError
);您能给出预期/期望的行为吗?期望的行为:(diviteeq exItem1 3)计算为((761)(234)(510)(012)(14)),传递给sumDigits。该应用程序产生1531。旁注:我在第二次检查时更正了递归情况。我预计我的问题源于我对Clojure类型系统的初步理解。改用。我希望避免内置函数,但感谢分区@jmargolisvtI su的建议我的问题是把int输入转换成lat(原子列表)之类的东西,回答得很好