用Clojure检查闰年

时间:2014-04-09 01:08:49

标签: clojure

我坚持使用运算符,如何测试多个条件。我非常接近,但我坚持用clojure解决这个问题。

(defn leap [year] (cond (and (zero? (rem year 4)) (zero? (rem year 100))) true :else false))

感谢您的帮助。

4 个答案:

答案 0 :(得分:5)

您正在使用and,但您的逻辑错误且不应使用and

(defn leap
  [year]
  (cond (zero? (mod year 400)) true
        (zero? (mod year 100)) false
        (zero? (mod year 4)) true
        :default false))

(这是根据wikipedia page for Leap Year上列出的公历中的闰年规则。)

我避免使用嵌套逻辑运算符,因为cond的目的是简化将复杂的嵌套条件转换为选择第一个适当选择的线性选择序列。

理想情况下,应该使用像clj-time这样的库来表示任何时间/日期逻辑,因为这些事情总是比预期的要困难得多。

此外,人们可以使用condp,但在这种情况下,我认为它的混淆程度超过了澄清:

(condp #(zero? (mod %2 %))
    year
  400 true
  100 false
  4 true
  false)

答案 1 :(得分:4)

请勿重新发明轮子,请使用clj-timenumber-of-days-in-the-month

(require 'clj-time.core)

(defn leap-year? [year]
  (= 29 (clj-time.core/number-of-days-in-the-month year 2)))

或者:

(defn leap-year? [year]
  (= 366 (clj-time.core/in-days
           (clj-time.core/interval (clj-time.core/date-time year 1 1)
                                   (clj-time.core/date-time (+ 1 year) 1 1)))))

答案 2 :(得分:3)

你忘了一个案例(如果年份可以被400整除怎么办?),第一个条件不对。这是另一种方法,如this回答中所述:

(defn leap [year]
  (cond (not (zero? (mod year 4)))   false
        (not (zero? (mod year 100))) true
        (zero? (mod year 400))       true
        :else false))

同样来自同一个链接,这是另一个可能更快的解决方案,虽然更难理解:

(defn leap [year]
  (and (zero? (bit-and year 3))
       (or (not (zero? (mod year 25)))
           (zero? (bit-and year 15)))))

答案 3 :(得分:0)

更好,我认为,没有明确的truefalse

(defn leap? [year]
  (let [div? #(->> % (mod year) zero?)]
    (and (div? 4) (or (not (div? 100)) (div? 400)))))

我们可以通过定义

来更清楚
(defmacro implies [p q] (or (not p) q))

...并且表达了函数的主体:

(and (div? 4) (implies (div? 100) (div? 400)))

注意:leap?是一个谓词,因此通常以?结尾。