Skip to content

Instantly share code, notes, and snippets.

@xuchunyang
Created April 1, 2015 13:47
Show Gist options
  • Save xuchunyang/7fd6ebf0ad0c47ed8795 to your computer and use it in GitHub Desktop.
Save xuchunyang/7fd6ebf0ad0c47ed8795 to your computer and use it in GitHub Desktop.
elisp-pcase-note.el
;;; elisp-pcase-note.el --- Learning Notes for Pattern Matching implemented in Emacs Lisp
;; URL: http://www.emacswiki.org/emacs/PatternMatching
;; Created: Wed Apr 1 20:57:16 CST 2015
;;; Find the reciprocal of a number
(defun recip (n)
(pcase n
(`0 (error "Can't divide by zero"))
(n (/ 1.0 n))))
;;; Find the absoulte value of a number
(defun abs2 (x)
(pcase x
((pred (< 0)) x)
((pred (= 0)) 0)
((pred (> 0)) (- x))))
;;; Find the head (`car') of a list
(defun car2 (list)
(pcase list
(`(,l . ,ll) l)))
(car2 '(1 2 3)) ;=> 1
;;; Find the tail (`cdr') of a list
(defun cdr2 (list)
(pcase list
(`(,l . ,ll) ll)))
(cdr2 '(1 2 3)) ;=> (2 3)
;;; Find the 2th element of a list
(defun 2nd (list)
(pcase list
(`(,l ,l2 . ,_) l2)))
(2nd '(1 2 3)) ;=> 2
;;; Find the 3rd element of a list
(defun 3rd (list)
(pcase list
(`(,l ,l2 ,l3 . ,_) l3)))
(3rd '(1 2 3 4)) ;=> 3
;;; Find the last element of a list
(defun thelast (list)
(pcase list
(`(,l . nil) l)
(_ (thelast (cdr list)))))
(thelast '(1 2 3)) ;=> 3
;;; sum(1, n)
(defun sum-to (n)
(pcase n
('1 1)
(n (+ n (sum-to (1- n))))))
(sum-to 1) ; => 1
(sum-to 3) ; => 6
(mapcar 'sum-to (number-sequence 1 10)) ;; => (1 3 6 10 15 21 28 36 45 55)
;;; Fibonacci number
(defun fib (n)
(pcase n
('0 1)
('1 1)
(n (+ (fib (- n 1)) (fib (- n 2))))))
(mapcar 'fib (number-sequence 0 7)) ;; => (1 1 2 3 5 8 13 21)
;;; GCD
(defun gcd (x y)
(pcase (list x y)
(`(,x 0) x)
(`(,x ,y) (gcd y (% x y)))))
(gcd 12 8) ;; => 4
(defun pow (x n)
(pcase `(,x ,n)
(`(,x 0) 1)
(`(,x ,n)
(* x (pow x (1- n))))))
(pow 2 10) ;; => 1024
(defun ackermann (m n)
(pcase (list m n)
(`(0 ,n) (1+ n))
(`(,m 0) (ackermann (1- m) 1))
(`(,m ,n) (ackermann (1- m)
(ackermann m (1- n))))))
(ackermann 0 0) ;; => 1
(defun int-to-words (n)
"List of English groupings for number N."
(let* ((pow10 (pcase (if (zerop n) 1 (floor (log10 (abs n))))
(`1 1)
(`2 2)
(`3 3)
(n (- n (% n 3)))))
(base10 (expt 10.0 pow10)))
(pcase n
(`nil (error))
((pred (> 0)) (cons "negative" (int-to-words (- n))))
(`0 '("zero"))
(`1 '("one"))
(`2 '("two"))
(`3 '("three"))
(`4 '("four"))
(`5 '("five"))
(`6 '("six"))
(`7 '("seven"))
(`8 '("eight"))
(`9 '("nine"))
(`10 '("ten"))
(`11 '("eleven"))
(`12 '("twelve"))
(`13 '("thirteen"))
(`14 '("fourteen"))
(`15 '("fifteen"))
(`16 '("sixteen"))
(`17 '("seventeen"))
(`18 '("eighteen"))
(`19 '("nineteen"))
(`20 '("twenty"))
(`30 '("thirty"))
(`40 '("forty"))
(`50 '("fifty"))
(`60 '("sixty"))
(`70 '("seventy"))
(`80 '("eighty"))
(`90 '("ninety"))
;; Less than 100
((pred (> 100))
(list (mapconcat 'identity
(cons (car (int-to-words (- n (% n 10))))
(int-to-words (% n 10))) "-")))
;; Equal to a base ten
((pred (= base10)) (pcase pow10
(`2 '("hundred"))
(`3 '("thousand"))
(`6 '("million"))
(`9 '("billion"))
(`12 '("trillion"))
(`15 '("quadrillion"))
(`18 '("quintillion"))
(`21 '("sextillion"))
(`24 '("septillion"))
(`27 '("octillion"))
(`30 '("nonillion"))
(`33 '("decillion"))
(`36 '("undecillion"))
(`39 '("duodecillion"))
(`42 '("tredecillion"))
(`45 '("quattuordecillion"))
(`48 '("quindecillion"))
(`51 '("sexdecillion"))
(`54 '("septendecillion"))
(`57 '("octodecillion"))
(`60 '("novemdecillion"))
(`63 '("vigintillion"))
(_ (signal 'domain-error (list n)))))
;; Greater than a base ten
((pred (< base10))
(cons (mapconcat 'identity
(append (int-to-words (floor (/ n base10)))
(int-to-words base10))
(if (< (/ n base10) 20) "-" " "))
(if (zerop (mod n base10))
nil
(int-to-words (if (< n most-positive-fixnum)
(% (floor n) (floor base10))
(mod n base10)))))))))
(int-to-words 333) ;; => ("three-hundred" "thirty-three")
;;; elisp-pcase-note.el ends here
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment