Data shapes

Leap
Leap in Clojure
(def leap-shapes
  #{{:by-4 true :by-100 true :by-400 true}
    {:by-4 true :by-100 false :by-400 false}})

(defn- to-shape [year]
  {:by-4 (zero? (mod year 4))
   :by-100 (zero? (mod year 100))
   :by-400 (zero? (mod year 400))})

(defn leap-year? [year]
  (->> year
       to-shape
       leap-shapes
       some?))

We can define a data structure that describes the properties of a number. In this case, the number is a year, and the properties are whether it is divisible by 4, 100 and 400. Let's call any instance of such data structure the shape of a number.

While there are many numbers, there are fewer shapes, so we can define all shapes corresponding to all leap years. There are only two.

(def leap-shapes
  #{{:by-4 true :by-100 true :by-400 true}
    {:by-4 true :by-100 false :by-400 false}})

We now need a function to convert any number to its shape.

(defn- to-shape [year]
  {:by-4 (zero? (mod year 4))
   :by-100 (zero? (mod year 100))
   :by-400 (zero? (mod year 400))})

With the above, we can now take a year number and check if its shape is one of the leap shapes.

(defn leap-year? [year]
  (->> year
       to-shape
       leap-shapes
       some?))

In Clojure, if a value is passed to a set, the set acts like a function checking if the value exists in that set. This is how leap-shapes acts as a predicate when combined with some?.

13th Nov 2024 · Found it useful?