4clojure 150 - Palindromic Numbers
A palindromic number is a number that is the same when written forwards or backwards (e.g., 3
, 99
, 14341
).
Write a function which takes an integer n
, as its only argument, and returns an increasing lazy sequence of all palindromic numbers that are not less than n
.
The most simple solution will exceed the time limit!
From jafingerhut
:
Note that all palindromic numbers are either of the form:
(concat x (reverse x))
for some sequence of one or more digits x
, so the palindromic number has an even number of digits.
or:
(concat x [ d ] (reverse x))
for some sequence of digits x
(perhaps empty) and some digit d
, so the palindromic number has an odd number of digits. To generate the palindromic numbers in increasing order, we just need to make the sequence x
(for even-length)
or (concat x [d]) (for odd-length)
represent incrementing decimal numbers.
Function next-pal returns the smallest palindromic number that is greater than or equal to its argument.
(ns live.test
(:require [cljs.test :refer-macros [deftest is run-tests]]))
(defn pals [s]
(let [p #(js/parseInt (apply str % ((if %2 next seq) (reverse (str %)))))
d #(count (str %))
o #(odd? (d %))
b #(js/parseInt (subs (str %) 0 (quot (+ 1 (d %)) 2)))
i #(let [x (b %)
o (o %)
y (+ 1 x)]
(cond
(= (d x) (d y)) (p y o)
o (p (/ y 10) nil)
1 (p y 1)))]
(filter #(>= % s) (iterate i (p (b s) (o s))))))
(deftest pals-test
(is (= (take 26 (pals 0))
[0 1 2 3 4 5 6 7 8 9
11 22 33 44 55 66 77 88 99
101 111 121 131 141 151 161]))
(is (= (take 16 (pals 162))
[171 181 191 202
212 222 232 242
252 262 272 282
292 303 313 323]))
(is (= (take 6 (pals 1234550000))
[1234554321 1234664321 1234774321
1234884321 1234994321 1235005321]))
(is (= (first (pals (* 111111111 111111111)))
(* 111111111 111111111)))
(is (= (set (take 199 (pals 0)))
(set (map #(first (pals %)) (range 0 10000)))))
(is (= true
(apply < (take 6666 (pals 9999999)))))
(is (= (nth (pals 0) 10101)
9102019)))
(run-tests)