(ns test-project-intellij.core
  (:gen-class))

(defn cube [x]
  "Cube a number through triple multiplication"
  (* x x x))

(defn sum3 [[i j]]
   " [i j] -> i^3 + j^3"
  (+ (cube i) (cube j)))

(defn next-pair [[i j]]
  " Generate next [i j] pair of sequence  (producing lower triangle pairs) "
  (if (< j i)
    [i (inc j)]
    [(inc i) 1]))


(def pairs-seq	(iterate next-pair [1 1]))

(defn dict-inc [m pair]
  " Add pair to pair map m, with the key of the map based upon the cubic sum (sum3) and the value appends the pair "
  (update-in m [(sum3 pair)] (fnil #(conj % pair) [])))

(defn enough? [m n-to-generate]
  " Checks if we have enough taxi numbers (i.e. if number in map >= count-needed "
  (->> m                                
       (filter #(if (> (count (second %)) 1) true false))   
       (count)                                              
       (<= n-to-generate)))                                

(defn find-taxi-numbers [n-to-generate]
  " Generates 1st n-to-generate taxi numbers"
  (loop [m {}               
         p pairs-seq        
         num-tried 0        
         check-after 1]     
                            
                            
    (if (and (= num-tried check-after) (enough? m n-to-generate)) 
      (sort-by first (into [] (filter #(> (count (second %)) 1) m)))  
      (if (= num-tried check-after)                                   
        (recur (dict-inc m (first p)) (rest p) (inc num-tried) (* 2 check-after))   
        (recur (dict-inc m (first p)) (rest p) (inc num-tried) check-after)))))     


(def result (find-taxi-numbers 2006))


(defn show-result [n sample]
  " Prints one line of result "
  (print (format "%4d:%10d" n  (first sample)))
  (doseq [q  (second sample)
         :let [[i j] q]]
      (print (format " =%4d^3 +%4d^3" i j)))
  (println))


(doseq [n (range 1 26)
       :let [sample (nth result (dec n))]]
  (show-result n sample))


(doseq [n (range 2000 2007)
       :let [sample (nth result (dec n))]]
  (show-result n sample))

}