Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
4clojure回文数超时问题_Clojure - Fatal编程技术网

4clojure回文数超时问题

4clojure回文数超时问题,clojure,Clojure,我不明白为什么在我发布解决方案时,4clojure上的回文数字拼图会超时。在我的本地REPL上,一切都很快。我发现了这一点,它可以工作,但它的性能与我的解决方案类似。我知道有很多代码,但问题并不容易。希望这些评论有助于理解这个想法 (defn palindrome [n] (let [ ;; given a number return a string digits (fn [^String x] (String/valueOf x))

我不明白为什么在我发布解决方案时,4clojure上的回文数字拼图会超时。在我的本地REPL上,一切都很快。我发现了这一点,它可以工作,但它的性能与我的解决方案类似。我知道有很多代码,但问题并不容易。希望这些评论有助于理解这个想法

(defn palindrome [n] 
  (let [ ;; given a number return a string
        digits (fn [^String x]  (String/valueOf x))              
    ;; given a string return the length
        digits-count  (fn [^String x] ( .length x) ) 
    ;; given an input sequence of digits, return a number. e.g. (seqstr (seq "1234")) => 1234
        seqstr  #(Long/parseLong (apply str %)) 
    ;; true when the given string has an even number of digits:
    even-digits? #(even? (digits-count %)) 
    ;; return the left middle of a string. For even-digit strings returns the 'real' left part, for odd-digit strings returns one digit more. 
    ;; e.g. (left-middle "12345678") => "1234"
    ;; e.g. (left-middle "1234567")  => "1234"
        left-middle #(if (even-digits? %) 
              (subs % 0 (quot (digits-count % ) 2) ) 
          (subs % 0 (inc (quot (digits-count % ) 2)))) 
    ;; mirror a given number. 
    ;; (mirror [1234 :even] ) => 12344321
    ;; (mirror [1234 :odd] )  => 1234321
        mirror (fn [[num dig]]
           (let [ d (seq (digits num))]
            (if (= :even dig) (seqstr (concat d (reverse d)))    
                        (seqstr (concat d (drop 1 (reverse d)))))))

    ;; initialize loop given a string. Returns a vector given a starting point.
    ;; (init "12345678") => [1234 :even 10000]
    ;; (init "1234567" ) => [1234 :odd  10000]
    ;; the first item in the vector contains the number we start the iteration with.
    ;; the flag indicates whether we should mirror it to an even or odd-digit number
    ;; the goal (power of 10) indicates when the next switch between odd/even-digit numbers will occur
    init #(let [s (left-middle %)] 
           (vector (Long/parseLong s) 
                (if (even-digits? %) :even :odd) 
            (long (Math/pow 10 (digits-count s)))))

    ;; given a vector (see structure above), determine the next step
      ;;(next  [999 :even 1000] ) => [1000 :odd 10000] . When finished mirroring even-digit numbers of length 3, continue with mirroring 4-digit odd-digit numbers
      ;;(next [9999 :odd 10000] ) => [1000 :even 10000]. When finished mirroring odd-digit numbers of length 4, continue with mirroring 4-digit even-digit numbers
    ;;(next [123 :odd 1000])    => [124 :odd 1000]. The normal case.
    next (fn [[num even goal]] 
         (let [m (inc num)] 
          (if (= m goal)
            (if (= even :even)
              [goal :odd (* 10 goal)]
              [(/ goal 10) :even goal])
            [m even goal] )))
   i  (init (digits n)) 
   palindromes (iterate next i) ] 
  (filter (partial <= n ) (map mirror palindromes))))
我真的不明白4clojure主页上的“超时”标准是什么。在我看来,1秒以下的每件事都应该有效。我在JRE 7上使用了Clojure 1.5.1,在JRE 6上使用了Clojure 1.2.1

这是我第四次尝试解决这个难题,我的大多数解决方案都与测试5相矛盾,但我不清楚说它慢有什么意义。我用的内存太多了吗?递归?我不熟悉这门语言,如果有任何冷冰冰的暗示,我将不胜感激:

我的第一个解决方案稍微慢一点,但在我的机器上完成大约600毫秒

(defn palindrome [n] 
  (let [
    digits         #(seq (str %))      ;; given a number return a seq of its digits
    digits-count   #(count (digits %)) ;; given a number return how many digits it has 
    seqstr         #(Long/parseLong (apply str %))  ;; seq to number
    start          (seqstr (take (/ (digits-count n) 2) (digits n)))
    digits-range   #(map long (range (max (Math/pow 10 (dec %)) start) (Math/pow 10 %)))  ;; return all numbers of given digits length
    mirror         #(let [d (digits %1)]
                       (if (true? %2) (seqstr (concat d (reverse d)))     ;; mirror 1234 true  => 12344321 even number of digits 
                                      (seqstr (concat d (drop 1 (reverse d)))))) ;; mirror 1234 false => 1234321  odd number of digits

    digits-seq     #(drop (/ (digits-count %) 2) (range)) ;; e.g. when input number has 10 digits, result is a seq: 5, 6, 7, 8, ....
                                                          ;;      when input number has  9 digits, result is a seq: 5, 6, 7, 8, ....
    input-even     (even? (digits-count n))                                                   
    ]
(filter #(<= n %) (cons 0 (mapcat #(concat (map (fn [x]  (mirror x false))  (if (and input-even (* 2 %)) [] (digits-range %))) 
                                  (map (fn [x]   (mirror x true ))  (digits-range %)) ) (digits-seq n) ))))) 
(defn回文[n]
(让[
数字#(seq(str%);;给定一个数字,返回其数字序列
数字计数#(计数(位数%);;给定一个数字,返回它有多少位数
seqstr#(Long/parseLong(apply str%);seq到数字
开始(seqstr(取(/(数字计数n)2)(数字n)))
数字范围#(映射长(最大范围(数学/功率10(dec%))开始)(数学/功率10%);返回给定数字长度的所有数字
镜像#(让[d(数字%1)]
(如果(真?%2)(seqstr(concat d(反向d));;镜像1234真=>12344321偶数位数
(seqstr(concat d(drop 1(反方向为d '));;镜像1234 false=>1234321奇数位数
数字顺序#(下降(/(数字计数%)2)(范围));例如,当输入数字有10位时,结果是顺序:5、6、7、8、。。。。
当输入的数字有9位时,结果是一个序列:5,6,7,8。。。。
输入偶数(偶数?(数字计数n))
]

(filter#)(每个4clojure拼图都有一个或多个教学目的。您有正确的算法,但超时测试会惩罚您使用太多从和到字符串的转换

罪魁祸首是镜像函数,它将数字转换为字符串,对其进行操作,然后将其转换回数字

尝试插入此替代方案,它不需要字符串转换和操作:

    mirror (fn [[num dig]]
             (loop [a num, r (if (= dig :even) num (quot num 10))]
               (if (= 0 r)
                 a
                 (recur (+ (* a 10) (mod r 10)), (quot r 10)))))
以下是一个基于您的原始帖子的完整解决方案,仅做了一些其他小改动:

(fn palindrome [n] 
  (let [even-digits? #(even? (count %)) 
        left-middle #(if (even-digits? %) 
                       (subs % 0 (quot (count % ) 2) ) 
                       (subs % 0 (inc (quot (count % ) 2)))) 
        mirror (fn [[num dig]]
                 (loop [a num r (if (= dig :even) num (quot num 10))]
                   (if (= 0 r)
                     a
                     (recur (+ (* a 10) (mod r 10)) (quot r 10)))))
        init #(let [s (left-middle %)] 
                (vector (Long/parseLong s) 
                        (if (even-digits? %) :even :odd) 
                        (long (Math/pow 10 (count s)))))
        nextp (fn [[num even goal]] 
               (let [m (inc num)] 
                 (if (= m goal)
                   (if (= even :even)
                     [goal :odd (* 10 goal)]
                     [(/ goal 10) :even goal])
                   [m even goal] )))
        i  (init (str n)) 
        palindromes (iterate nextp i) ] 
    (filter (partial <= n ) (map mirror palindromes))))
(fn回文[n]
(让[偶数数字?#(偶数)(计数%)
左中#(如果(偶数?%)
(子项%0(引用(计数%)2))
(子项%0(包括(计数%2)))
镜像(fn[[num dig]]
(循环[a num r(if=dig:偶数)num(quot num 10))]
(如果(=0 r)
A.
(重复出现(+(*A10)(ModR10))(引用R10()()))
init#(让[s(左中%)]
(向量(长/长解析)
(如果(偶数?):偶数:奇数)
(长(数学/战力10(计数s '))))
nextp(fn[[num偶数目标]]
(让[m(inc num)]
(如果(=m目标)
(如果(=偶数:偶数)
[目标:单数(*10个目标)]
[(/目标10):偶数目标])
[m偶数目标]))
i(初始(strn))
回文(迭代nextp i)]

(过滤器(部分)我认为“超时”是为每个拼图单独设置的标准。4clojure的目标是教学性的,其中一部分是帮助您了解哪些操作和哪些操作不好。将数字转换为字符串,然后再将其转换为字符,这远远不是执行此任务的最有效方式。代码更短,可读性更强这就大大缩短了解谜的时间。我不知道,但也有可能作者通过模仿某些函数(例如字符串转换)来玩弄肮脏的把戏。同样,出于教学目的,这些函数比REPL中的要慢得多。我很清楚数字转换为字符串(和返回)的过程转换,但在4clojure上,它总是说明什么是不允许使用的。对于这个谜题,我看不到任何限制。@noisesmith:你缺少一个证据来证明你所说的无效。我链接到的解决方案在任何数量级上都没有优于我的解决方案。当然,Clojure人提供的代码看起来都非常有用更容易理解,但除非我解决了一个难题,否则我无法访问它。我在这里问的问题是,帮助我理解在4clojure门户上发布时可能出现的错误。@a.webb:实际上,在我早期的尝试中,我使用的字符串操作较少,但我认为当我移动到WAR时,它可能会提供更好的性能ds字符串,因为它们在jvm中进行了大量优化。因此,我发布的解决方案是尝试在repl上以最快的速度运行,但可以肯定的是,当它们惩罚此类函数时,我永远无法完成此难题。感谢您的提示。尽管使用镜像函数,它仍然超时,我可能需要交换更多的字符串操作。但是我我猜你对模拟的评论可能是原因。我知道把整数放在字符串中可以让我很容易地访问数字,但我不认为这种欺骗是他们的教学目的。对我来说,教学的关键是从中间的数字迭代,而不是镜像数字。当然,我也可以用向量来做。我会给出它a今晚试试。Thanx。对,我做的另一个小改动一定起到了作用。发布了通过的完整代码。你可以在awebb下看到我的回答较差但通过。我忍不住自己尝试一个不使用字符串的解决方案。即时工作。如果你感兴趣,这里的代码:。@shaft Cool.a solution
    mirror (fn [[num dig]]
             (loop [a num, r (if (= dig :even) num (quot num 10))]
               (if (= 0 r)
                 a
                 (recur (+ (* a 10) (mod r 10)), (quot r 10)))))
(fn palindrome [n] 
  (let [even-digits? #(even? (count %)) 
        left-middle #(if (even-digits? %) 
                       (subs % 0 (quot (count % ) 2) ) 
                       (subs % 0 (inc (quot (count % ) 2)))) 
        mirror (fn [[num dig]]
                 (loop [a num r (if (= dig :even) num (quot num 10))]
                   (if (= 0 r)
                     a
                     (recur (+ (* a 10) (mod r 10)) (quot r 10)))))
        init #(let [s (left-middle %)] 
                (vector (Long/parseLong s) 
                        (if (even-digits? %) :even :odd) 
                        (long (Math/pow 10 (count s)))))
        nextp (fn [[num even goal]] 
               (let [m (inc num)] 
                 (if (= m goal)
                   (if (= even :even)
                     [goal :odd (* 10 goal)]
                     [(/ goal 10) :even goal])
                   [m even goal] )))
        i  (init (str n)) 
        palindromes (iterate nextp i) ] 
    (filter (partial <= n ) (map mirror palindromes))))