Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (defmacro palinfun (name parameters &body body)
- `(defun ,name (sequence ,@parameters)
- (let* ((len (length sequence)) (anti-midlen (antibelt sequence (floor len 2))) (midlen (floor len 2)) (midsequence (/ len 2)))
- (declare (ignorable midlen anti-midlen midsequence))
- ,@body)))
- (palinfun lrbelt (belt)
- ;;Returns 0 (left) 1 (right) or 2 (mid) for position of belt in sequence
- (when (> belt (1- len)) (return-from lrbelt nil))
- (when (and (oddp len) (= belt midlen)) (return-from lrbelt 2))
- (when (and (evenp len) (= belt midlen) (return-from lrbelt 1)))
- (when (< belt midsequence) (return-from lrbelt 0))
- (when (> belt midsequence) (return-from lrbelt 1)))
- (palinfun antibelt (belt)
- ;;;Returns the corresponding belt across the midline of sequence
- (let ((zblen (- len 1)))
- (- zblen belt)))
- (palinfun belt (elt)
- ;;;A balanced version of elt
- (when (> elt (- len 1)) (return-from belt nil))
- (cons (elt sequence elt) (elt (reverse sequence) elt)))
- (palinfun bset (belt newval)
- ;;;Outputs a copy of sequence with belt and antibelt set to newval
- (let ((leftbelt (if (zerop (lrbelt sequence belt)) (values 1) (values nil)))
- (midbelt (if (= (lrbelt sequence belt) 2) (values 1) (values nil))) (antibelt (antibelt sequence belt)))
- (when (> belt (1- len)) (return-from bset nil))
- (let ((rightbelt (if (and (not leftbelt) (not midbelt)) (values 1) (values nil))))
- (cond (midbelt
- (concatenate 'string (subseq sequence 0 belt) newval (subseq sequence (1+ belt) len)))
- (leftbelt
- (concatenate 'string (subseq sequence 0 belt) newval (subseq sequence (1+ belt) antibelt) newval (subseq sequence (1+ antibelt) len)))
- (rightbelt
- (concatenate 'string (subseq sequence 0 antibelt) newval (subseq sequence (1+ antibelt) belt) newval (subseq sequence (1+ belt) len)))))))
- (palinfun palindromep ()
- ;;;Palindrome predicate
- (loop for n from 0 upto anti-midlen do
- (let ((belt (belt sequence n)))
- (let ((left (car belt)) (right (cdr belt)))
- (when (not (equal left right)) (return-from palindromep nil))))
- finally (return-from palindromep 1)))
- (palinfun palindrominc ()
- ;;;Increments palindrome to next palindrome
- (when (not (equal 9 (parse-integer (string (elt sequence anti-midlen))))) (return-from palindrominc (bset sequence anti-midlen (write-to-string (1+ (parse-integer (string (elt sequence anti-midlen))))))))
- (loop for belt from (1- anti-midlen) downto 0 do
- (when (not (equal 9 (parse-integer (string (elt sequence belt))))) (return-from palindrominc (bset sequence belt (write-to-string (1+ (parse-integer (string (elt sequence belt))))))))
- finally (return-from palindrominc (write-to-string (1+ (expt 10 len))))))
- (palinfun right-balance ()
- ;;;Balance right digits with left digits
- (loop for belt from (1- len) downto midlen with newsequence = sequence do
- (when (< (parse-integer (string (elt newsequence belt))) (parse-integer (string (elt newsequence (antibelt newsequence belt)))))
- (setf newsequence (bset newsequence belt (string (elt newsequence (antibelt newsequence belt))))))
- finally (return newsequence)))
- (palinfun next-palindrome ()
- ;;;Balance left digits with right digits
- (loop for belt from anti-midlen downto 0 with newsequence = sequence do
- (when (< (parse-integer (string (elt newsequence belt))) (parse-integer (string (elt newsequence (antibelt newsequence belt)))))
- (setf newsequence (bset newsequence belt (string (elt newsequence (antibelt newsequence belt))))))
- finally (return newsequence)))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement