aboutsummaryrefslogtreecommitdiff
path: root/racket/leetcode/lc-9-palindromic-number.rkt
blob: 1fccbefd34974c895e3b20a03e4f081bb6db703e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#lang racket
(define/contract (is-palindrome x)
  (-> exact-integer? boolean?)
  ; get the easy cases out of the way first
  ; negative numbers are not palindromes, single-digit numbers are
  (cond [(x . < . 0) #false]
        [(x . < . 10) #true]
        [else
         ; order-of-magnitude returns the scientific notation exponent
         ; so add 1 to get the number of digits
         (define digits
           (add1 (order-of-magnitude x)))
         ; figure out how many digits we need to trim to find the mirrored halves
         ; if there are an even number of digits 2n, we will remove n of them from the right
         ; if there are an odd number of digits 2n+1, we will remove n+1 of them from the right
         (define half-digits
           (cond [(even? digits) (/ digits 2)]
                 [else (/ (add1 digits) 2)]))
         ; divide x by a power of 10 to get the digits to match
         (define front-half
           (quotient x (expt 10 half-digits)))
         ; reverse the back half with repeated divisions by 10
         (define back-half-reversed
           (for/fold ([reversed 0]
                      [remaining (remainder x (expt 10 half-digits))]
                      ; build up the sum of the digits in reversed and return it at the end
                      #:result reversed)
                     ; if we have an odd number of digits, we don't need to match the middle one
                     ([n (in-range (if (even? digits)
                                       half-digits
                                       (sub1 half-digits)))])
             ; shift all the accumulated digits in the mirror to the left one place
             ; and add the next one to the right,
             ; then chop the right-most digit off the original
             (values (+ (* 10 reversed) (remainder remaining 10))
                     (quotient remaining 10))))
         ; finally, check to see if the mirrored right is equal to the original left
         (= front-half back-half-reversed)]))