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 http://programmingpraxis.codepad.org/AMItBoYw: 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 multiply.in.

About these ads

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.

    #!/usr/bin/python
    
    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'
            else:
                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':
                break
            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 ‘————‘
    t=i2
    cnt=0
    x=0
    while t!=0:
    x=(t%10)*i1
    if cnt==0 and x!=0:
    print x
    elif x!=0:
    print x*(cnt*10)
    t=t/10
    cnt+=1
    print ‘————‘
    print i1*i2

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

    (defn digits [n]
    	(loop [k n acc ()]
    		(if (zero? k) 
    			acc 
    			(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)))
                      (recur 
                          (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. (java.io.File. 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:

WordPress.com Logo

You are commenting using your WordPress.com 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 )

Google+ photo

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

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 629 other followers

%d bloggers like this: