;; Problem 66  : 2011/11/29
;; "Elapsed time: 67.348225 msecs"

;; treat all num as
;; (sqrt X)+M
;; -----------
;;      N

(defn int-floor [x]
  (Math/round (Math/floor x)))

(defn inverse-rationalize [X M N]
  (let [new-N (/ (- X (* M M)) N)
	new-M (- M)]
    [new-M new-N]))
  
(defn make-proper [X M N]
  (let [nume (+ (Math/sqrt X) M)
	a (int-floor (/ nume N))
	new-M (- M (* a N))]
    [a new-M]))
	
(defn get-cf-list-loop
  "Get continued fraction parms of Sqrt X"
  ([X] (get-cf-list-loop X 0 1 nil))
  ([X M N top]
     (let [[a prop-M] (make-proper X M N)
	   [new-M new-N] (inverse-rationalize X prop-M N)]
       (lazy-seq
	(cons a
	      (if (= [new-M new-N] top)
		nil
		(get-cf-list-loop X
				  new-M
				  new-N
				  (if (empty? top)
				    [new-M new-N]
				    top))))))))

(defn calc-cf-partial-fraction [cf-list]
  (reduce #(+ (/ 1 %1) %2)
	  (drop 1 (reverse cf-list))))

(defn check-norm [X Y D]
  (= 1 (- (* X X) (* Y Y D))))

(defn my-numerator [n]
  (if (integer? n)
    n
    (numerator (rationalize n))))

(defn my-denominator [n]
  (if (integer? n)
    1
    (denominator (rationalize n))))

(defn solv-pell-eq [n]
  (let [fraction (calc-cf-partial-fraction (get-cf-list-loop n))
	num (my-numerator fraction)
	den (my-denominator fraction)]
    (if (check-norm num den n)
      [num den n]
      [(+ (* num num) (* den den  n)) (* 2 den num) n])))

(defn square? [n]
  (let [rt (Math/round (Math/sqrt n))]
    (= n (* rt rt))))

(defn pe-66 [limit]
  (reduce #(if (> (first %1) (first %2)) %1 %2)
	  (map solv-pell-eq
	       (filter (complement square?) (range 10 (inc limit))))))