Multiplication Table In Emacs Lisp

Xah Lee saw my post about Tim Visher's video on building a multiplication table in Emacs and decided to experiment. Visher's video was in the context of VimGolf where the goal was to build the table in the minimum number of keystrokes. Lee wasn't interested in building the table in the minimum number of keystrokes; he wanted to see how you could do it in various programming languages. He gives solutions in Emacs Lisp, Python, and Perl. That was interesting but then he says

Lisp is a bit verbose for this kinda thing due to the nested syntax.
But you can write it in perl, python, ruby, bash, or any dynamic lang
quickly, and press a button to have emacs call it and insert the
result.

To a Lisper like me this is a challenge that can't go unanswered. Therefore I started to think about how I could code this concisely with Emacs Lisp. My first thought was to use the dotimes macro but that starts with 0, which complicates things. Then I realized that since we only needed to deal with the numbers 1–10, I could just use dolist like this

(dolist (r '(1 2 3 4 5 6 7 8 9 10))
  (dolist (c '(1 2 3 4 5 6 7 8 9 10))
    (insert (format "%2d " (* r c))))
  (insert "\n"))

Now put the point at the beginning of the next line, type 【Ctrl+x Ctrl+e】 and the table is inserted into the buffer.

None of this is of any importance, of course, but it is fun and instructive. My solution can be criticized on the grounds that it's really a Common Lisp solution but it does work in Emacs due to the cl.el package. It's also slightly objectionable to have to list the numbers explicitly but I couldn't think of a better way. Leave a comment if you have a nicer solution.

Update: Added link to Xah Lee's post.

This entry was posted in Programming and tagged , . Bookmark the permalink.

10 Responses to Multiplication Table In Emacs Lisp

  1. jpkotta says:

    You want number-sequence.

    • jcs jcs says:

      Cool. That's exactly what I want. With that, we have

      (dolist (r (number-sequence 1 10))
      (dolist (c (number-sequence 1 10))
      (insert (format "%2d " (* r c))))
      (insert "\n"))

  2. bitti says:

    Isn't loop even more readable and concise?


    (loop for r from 1 to 10 do
    (loop for c from 1 to 10 do
    (insert (format "%5d " (* r c))))
    (insert "\n"))

    PS: The flash captcha is awful! :(

    • jcs jcs says:

      PS: The flash captcha is awful!

      Really? I chose it because it was easier to read and supposedly harder to break. What don't you like about it?
      I hated using a captcha at all but The forum spam was completely out of control.

  3. bitti says:

    Because it makes my chrome (16) browser very sticky, especially when it scrolls into the viewport (even just a part of it). That's makes reading your block a hurdle, not to mention commenting.

    In firefox a .gif is displayed therefore the problem doesn't occur there, but that doesn't help me since I use chrome normally.

    • jcs jcs says:

      Noted. I'll look around for something better but at the time I installed it there didn't appear to be anything better. If you plan on coming back you might want to register. That way you won't see the captcha. Sorry you're having trouble.

  4. Tassilo Horn says:

    Here's my version for those preferring higher-order functions over loops:


    (defun multiplication-table (ns)
    (let ((fstr (concat "%"
    (number-to-string
    (* 2 (length (number-to-string (apply 'max ns)))))
    "d")))
    (mapc (lambda (n)
    (mapc (lambda (r)
    (insert (format fstr (* n r))))
    (cons 1 ns))
    (insert "\n"))
    (cons 1 ns))))

    (multiplication-table (number-sequence 5 15))
    1 5 6 7 8 9 10 11 12 13 14 15
    5 25 30 35 40 45 50 55 60 65 70 75
    6 30 36 42 48 54 60 66 72 78 84 90
    7 35 42 49 56 63 70 77 84 91 98 105
    8 40 48 56 64 72 80 88 96 104 112 120
    9 45 54 63 72 81 90 99 108 117 126 135
    10 50 60 70 80 90 100 110 120 130 140 150
    11 55 66 77 88 99 110 121 132 143 154 165
    12 60 72 84 96 108 120 132 144 156 168 180
    13 65 78 91 104 117 130 143 156 169 182 195
    14 70 84 98 112 126 140 154 168 182 196 210
    15 75 90 105 120 135 150 165 180 195 210 225

    It also adds an argument line and column, which is good if you provide a list as argument that doesn't start with one or one that has decreasing or arbitrary values. And it calculates the column with dynamically.


    (multiplication-table (number-sequence 15 5 -1))
    1 15 14 13 12 11 10 9 8 7 6 5
    15 225 210 195 180 165 150 135 120 105 90 75
    14 210 196 182 168 154 140 126 112 98 84 70
    13 195 182 169 156 143 130 117 104 91 78 65
    12 180 168 156 144 132 120 108 96 84 72 60
    11 165 154 143 132 121 110 99 88 77 66 55
    10 150 140 130 120 110 100 90 80 70 60 50
    9 135 126 117 108 99 90 81 72 63 54 45
    8 120 112 104 96 88 80 72 64 56 48 40
    7 105 98 91 84 77 70 63 56 49 42 35
    6 90 84 78 72 66 60 54 48 42 36 30
    5 75 70 65 60 55 50 45 40 35 30 25

  5. Xah Lee says:

    great post! and excellent comments too! Thanks a lot.

Comments are closed.