Grade School Multiplication

November 18, 2011

We begin with the function that displays a single multiplication. We find it easiest to plan everything first, calculating the width of the output display in the variable len and the number of lines in the body of the multiplication in the variable lines:

(define (mult x y)
  (let* ((ys (digits y))
         (len (length (digits (* x y))))
         (lines (length (filter positive? ys))))
    (display-right x len)
    (display-right y len)
    (display (repeat len #\-)) (newline)
    (when (< 1 lines)
      (let loop ((ys (reverse ys)) (i 0) (z 1))
        (when (pair? ys)
          (if (zero? (car ys))
              (loop (cdr ys) i (* z 10))
              (begin (display-right (* x (car ys) z) (- len i))
                     (loop (cdr ys) (+ i (ilog10 z) 1) 1)))))
      (display (repeat len #\-)) (newline))
    (display-right (* x y) len)))

We used several utility functions that aren’t shown here, though all are at digits, which returns a list of the digits in a number, is from the Standard Prelude; repeat returns a string consisting of n repetitions of the character c; display-right displays a number n right-justified in a string of width len, and appends a newline; and ilog10 returns the number of digits in the input number n, minus one.

Function problem-a takes a filename and outputs the requested multiplications:

(define (problem-a filename)
  (with-input-from-file filename
    (lambda ()
      (let loop ((x (read)) (y (read)) (i 1))
        (when (and (positive? x) (positive? y))
          (display "Problem ") (display i) (newline)
          (mult x y)
          (loop (read) (read) (+ i 1)))))))

To solve the problem, say problem-a


Pages: 1 2

6 Responses to “Grade School Multiplication”

  1. DGel said

    My quickly hacked together version in Python. Would love to see more elegant versions, but right now can’t think of one.

    import sys
    def expand_string(a, n):
        diff = n - len(a)
        if diff > 0:
            a = ' ' * diff + a
        return a
    def pprint_mult(i, j, counter):
        print "Problem", counter
        res = int(i) * int(j)
        length = len(str(res))
        separator = '-' * length
        print expand_string(i, length)
        i = int(i)
        print expand_string(j, length)
        print separator
        n_printed = 0
        printstring = ''
        printlen = length
        for pos in range(len(j)):
            if j[len(j) - 1 - pos] == '0':
                printstring += '0'
                print expand_string(str(int(j[len(j) - 1 - pos]) * i) + printstring, printlen)
                n_printed += 1
                printlen = length - pos - 1
                printstring = ''
        if n_printed > 1:
            print separator
            print res
    with open(sys.argv[1], 'r') as dfile:
        counter = 1
        for line in dfile:
            a, b = line.split()
            if a == '0' and b == '0':
            pprint_mult(a, b, counter)
            counter += 1
  2. DGel said

    minor correction: instead of writing my expand_string() function, I could have used something like:

    ('{0: >' + str(printlen) + '}').format(int(j[len(j) - 1 - pos]) * i) + printstring)
  3. DGel said

    sigh… correction on my correction: I should leave the string conversion in :)

  4. ”’
    My python solution
    i1=int(raw_input(‘enter first no’))
    i2=int(raw_input(‘enter second no’))
    print i1,’\n’,i2
    print ‘————‘
    while t!=0:
    if cnt==0 and x!=0:
    print x
    elif x!=0:
    print x*(cnt*10)
    print ‘————‘
    print i1*i2

    i1=int(raw_input('enter first no'))
    i2=int(raw_input('enter second no'))
    print i1,'\n',i2
    print '------------'
    while t!=0:
        if cnt==0 and x!=0:
            print x
        elif x!=0:
            print x*(cnt*10)
    print '------------'
    print i1*i2
  6. A Clojure solution:

    (defn digits [n]
    	(loop [k n acc ()]
    		(if (zero? k) 
    			(recur (quot k 10) (conj acc (rem k 10))))))
    (defn partials [a b]
    	(map #(* % a) (digits b)))
    (defn repeated [n x]
    	(apply str (repeat n x)))
    (defn rpad [len pad n]
    	(str (repeated (- len (count (digits n))) pad) n))
    (defn print-multiplication [a b]
    	(let [r (* a b) rlen (count (digits r)) ps (reverse (partials a b))]
    		(println  (rpad rlen " " a) "x")
    		(println  (rpad rlen " " b))
            (when (not (= 1 (count (filter #(not (zero? %)) ps))))
    		  (println  (repeated rlen "-"))
              (loop [p ps i 0 suffix ""]
                  (when (seq p)
                      (when (not (zero? (first p)))
                          (println (str (rpad (- rlen i) " " (first p)) suffix)))
                          (rest p) 
                          (inc i)
                          (if (zero? (first p)) (str suffix "0") "")))))
    		(println (repeated rlen "-"))
    		(println r)))
    (defn problem-a [filename]
      (let [stream (java.util.Scanner. ( filename))]
            (while (.hasNextInt stream)
              (let [a (.nextInt stream) b (.nextInt stream)]
                (when (and (> a 0) (> b 0))
                  (print-multiplication a b))))))

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: