Skip to content

Instantly share code, notes, and snippets.

@hindol
Created January 1, 2020 07:26
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hindol/f918b382b94dd1f5d98306195f231128 to your computer and use it in GitHub Desktop.
Save hindol/f918b382b94dd1f5d98306195f231128 to your computer and use it in GitHub Desktop.
(ns com.github.hindol.euler
(:require
[clojure.test :refer [is]]
[clojure.tools.trace :refer [trace-ns untrace-ns]])
(:gen-class))
(set! *unchecked-math* true)
(set! *warn-on-reflection* true)
(defn pentagonal-seq
[]
(let [xf (comp
(mapcat (juxt identity -))
(map #(/ (* % (dec (* 3 %))) 2)))] ;; k (3k - 1) / 2
(sequence xf (iterate inc 1))))
(def cached-pentagonal-seq
(pentagonal-seq))
;; https://projecteuler.net/problem=78
;;
;; *
;;
;; **
;; * *
;;
;; ***
;; ** *
;; * * *
;;
;; ****
;; *** *
;; ** **
;; ** * *
(def count-partitions
"Given n coins, how many distinct partitions are possible?"
(memoize
(fn
[n]
{:pre [(is (not (neg? n)))]
:post [(is (not (neg? %)))]}
(cond
(neg? n) 0
(zero? n) 1
:else (let [xf (comp
(take-while #(<= % n))
(map #(count-partitions (- n %))))
terms (sequence xf cached-pentagonal-seq)
signs (cycle [+1 +1 -1 -1])]
(reduce +' (map * signs terms)))))))
(defn -main
[& _]
(let [n 6
xf (comp
(map count-partitions)
(take-while #(pos? (rem % 1000000))))]
(+ n (count (sequence xf (iterate inc n))))))
(time (-main))
@didibus
Copy link

didibus commented Jan 3, 2020

For posterity, here it is with the transducer:
Takes 4.2s on my machine.

(set! *unchecked-math* true)

(def ^:const modulo
  1000000)

(def ^:const limit
  100000)

(defn solve []
  (loop [n 1 partitions (vector-of :long 1)]
    (if (<= n limit)
      (let [sum (unchecked-long
                  (loop [sum 0 i 0 offsets (sequence (comp (mapcat (juxt identity -))
                                                           (map (fn [^long %] (quot (* % (dec (* 3 %))) 2))))
                                                     (iterate inc 1))]
                    (let [offset (unchecked-long (first offsets))]
                      (if (< n offset)
                        sum
                        (if (< (rem i 4) 2)
                          (recur (rem (+ sum (unchecked-long (nth partitions (- n offset)))) modulo) (inc i) (rest offsets))
                          (recur (rem (- sum (unchecked-long (nth partitions (- n offset)))) modulo) (inc i) (rest offsets)))))))
            sum (if (neg? sum) (+ sum modulo) sum)]
        (if (zero? sum)
          (count partitions)
          (recur (inc n) (conj partitions sum))))
      (count partitions))))

(time (solve))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment