Visualize long division with ASCII art

16

3

Write a program that visualizes long division with ASCII art. Input consists of two integers, a numerator and a denominator, using the input format of your choice.

Examples:

1234 ÷ 56:

     22
   ----
56|1234
   112
   ---
    114
    112
    ---
      2

1002012 ÷ 12:

     83501
   -------
12|1002012
    96
   ---
     42
     36
     --
      60
      60
      --
        12
        12
        --

0 ÷ 35

   0
   -
35|0

Rules:

  • Use of the programming language's division operator is allowed.
  • Use of big integer support is also allowed.
  • For consistency:
    • If the quotient is zero, print a single zero at the end of the diving board.
    • If the remainder is zero, do not print it.
    • Do not print leading zeros on any numbers.
  • Excess newlines at the end and trailing spaces to the right are allowed.
  • Solution with the fewest characters wins.

Limits:

  • 0 <= numerator <= 1072 - 1
  • 1 <= denominator <= 9999999

This implies that the output will never be wider than 80 columns.

Test suite and sample implementation:

You can use long-division.c (gist) to test your program. It is actually a bash script with a C program inside. Tweak it to invoke your program in the test suite. Look at the C code at the bottom to see the reference implementation. Please let me know if there are any problems with the sample program or test suite.

$ ./long-division.c 10 7
   1
  --
7|10
   7
  --
   3
$ ./long-division.c
PASS 1234 ÷ 56
PASS 1002012 ÷ 12
PASS 1 ÷ 1
--- snip ---

Score: 35 / 35
All tests passed!

Edit: By request, I put the test suite input and expected output into text files (gist). Sample usage (bash):

cat input | while read nd; do
    ./program $nd |
        sed 's/\s*$//' | sed -e :a -e '/^\n*$/{$d;N;};/\n$/ba'
done > output

diff -u expected output

The weird sed commands filter out trailing newlines and spaces from the program output.

Joey Adams

Posted 2011-03-14T21:15:29.067

Reputation: 9 929

I discovered a minor flaw in the reference implementation, namely in the case of 123000123000123 ÷ 123. The subtraction lines were spanning blank space, but they should only be spanning the length of the visible digits of the minuend. It's fixed now. – Joey Adams – 2011-03-15T01:22:22.833

2

I think the output is a bit biased towards the English-speaking golfing audience: http://en.wikipedia.org/wiki/Long_division#Notation_in_non-English-speaking_parts_of_the_world

– hallvabo – 2011-03-15T11:23:28.097

Can you just create a file that shows the expected output of all the tests and link to it? – mellamokb – 2011-03-15T14:43:38.830

@mellamokb: Added, thanks! – Joey Adams – 2011-03-15T15:28:18.367

What about accepting? The question is old enough... – Oleh Prypin – 2011-04-06T16:57:27.093

Answers

3

Python 3, 284 257 characters

div.py

n,t=input().split()
d=int(t)
l=lambda x:len(str(x))
s=l(n)
def p(x):print(' '*(l(d)+s-l(x)+1)+str(x))
p(int(n)//d)
p('-'*s)
p(t+'|'+n)
s=z=f=0
while t:
 try:
  while z<d:z=z*10+int(n[s]);s+=1
 except:t=0
 if z*f:p(z)
 if t:f=1;t=z//d*d;p(t);p('-'*l(z));z-=t

Usage: python3 div.py
Input: from keyboard

test.py

import sys
sys.stdin=open('input'); sys.stdout=open('output','w')
for line in open('input'): exec(open('div.py').read())

output matches expected

Versions:
 1. 284
 2. 257: s,z,f=0,0,0s=z=f=0; z and fz*f; better looping; removed a few newlines.

Oleh Prypin

Posted 2011-03-14T21:15:29.067

Reputation: 706

2

you may try ideone for python3 and input - http://ideone.com/clone/ZZyzu

– YOU – 2011-04-04T04:28:29.723

3

JavaScript (400 394 418)

function d(n,d){t=parseInt;p=function(v){return(s+v).substring(v.length)};a=function(v,c){return v.replace(/\d/g,c)};w='\n';q=b=o=c=e='';s=a(d,' ')+' ';f=true;i=-1;z='0';while(++i<n.length){s+=' ';if(t(c+=n[i])>=t(d)){q+=r=Math.floor(t(c)/t(d));o+=(!f?p(c)+w:e)+p(''+r*t(d))+w+p(a(c,'-'))+w;c=t(c)%t(d);f=false}else if(!f){q+=z;}c=(c==0)?e:e+c}return p(!q?z:q)+w+p(a(n,'-'))+w+d+'|'+n+w+o+(q?p(c):e)}

NOTE: As tempting as it looks to shave off a few chars by replacing c=(c==0)? with c=!c?, it is not usable because it causes floating point-related bugs.

http://jsfiddle.net/nLzYW/9/

Sample Execution:

document.writeln("<pre>");
document.writeln(d("1234","56"));
document.writeln();
document.writeln(d("1002012","12"));
document.writeln();
document.writeln(d("0","35"));
document.writeln();
document.writeln(d("123000123000123","123"));
document.writeln("</pre>");

Edit 1: Minor bug fixes, numerous code optimizations.

Edit 2: Fix bug with 1/7 generating extra output.

mellamokb

Posted 2011-03-14T21:15:29.067

Reputation: 5 544

The test script revealed one problem. d(1,7) (and similar tests) repeat the denominator rather than printing nothing. This is wrong because this number should be the quotient digit times the denominator, which is zero. – Joey Adams – 2011-03-15T15:32:17.833

All tests pass now. – Joey Adams – 2011-04-04T19:47:39.357

3

Haskell, 320 characters

l=length
(®)=replicate
p!v=p&show v
p&s=(p-l s)®' '++s
0§_=[];_§l=l
d[m,n]=l c!(read m`div`e):l c&(l m®'-'):c:drop 1(g 0(map(toInteger.fromEnum)m)$1+l n)where
 e=read n;c=n++'|':m
 g r(d:z)p=i§[o!k,o!(i*e),o&(l(show k)®'-')]++g j z o where k=r*10+d-48;(i,j)=k`divMod`e;o=1+p
 g r[]p=r§[p!r]
main=interact$unlines.d.words

Passes all tests. While is this pretty golf'd -- I think there is still yet more to be done here...


  • Edit: (344 -> 339) delay read calls, which reduces need to call show, enough that abbreviating show as s isn't worth it.
  • Edit: (339 -> 320) rewrote string field formatting functions

MtnViewMark

Posted 2011-03-14T21:15:29.067

Reputation: 4 779

Neat! I did a Haskell solution with 344 characters, but didn't post it. Also, I didn't know you could use Unicode symbols for operators (without -XUnicodeSyntax). – Joey Adams – 2011-04-05T17:00:35.933

1

Javascript: (372)

function g(a){for(var c="",e=0;e<a;e++)c=" "+c;return c}function i(a,c){for(var e=a+"/"+c+"\\",j=(""+c).split(""),k="",d=0,b=0;b<j.length;b++){d*=10;d+=parseInt(j[b],10);var f=d>9?b-1:b,h=0;h=Math.floor(d/a);d%=a;f=g(f+a.toString().split("").length);f+=h*a+"\n"+g(b+a.toString().split("").length)+"--\n"+g(b+a.toString().split("").length)+d+"\n";k+=f;e+=h}return e+"\n"+k}

Invoke by using i(divider,number). Codegolfed JS: http://jsfiddle.net/puckipedia/EP464/ Ungolfed (dutch) JS: http://jsfiddle.net/puckipedia/M82VM/

Returns the long division (in dutch format as i learned it):

5/25\05
 0
 --
 2
 25
  --
  0

Testcase:

document.write("<pre>"+i(5,25)+"</pre>");
document.write("<pre>"+i(7,65669726752476)+"</pre>");

puckipedia

Posted 2011-03-14T21:15:29.067

Reputation: 199

Hey, this isn't the same as required! – Oleh Prypin – 2011-04-03T13:53:51.877

@BlaXpirit I know, i learned it that way. – puckipedia – 2011-04-03T16:57:34.917

Interesting. Though as @BlaXpirit says, it doesn't follow the spec. The spec is intended to be a fair standard of comparison for determining efficiency of code-golfed code, so you can't arbitrarily change the spec even if you don't agree with the output format :) – mellamokb – 2011-04-04T16:40:43.903