23
\$\begingroup\$

Everyone knows how to add numbers by hand, right?––Well, I hope so, but for anyone who needs a quick reminder:

To add 17282 and 1342, you proceed as follows:

  1. place the larger (value wise, not number of digits) number above the smaller number and match up the digits

    17282
     1342
    
  2. draw the plus sign (+) to the left of the equation on the second row. The plus sign must be flush with the left side.

     17282
    + 1342
    
  3. draw a line of dashes (-) with one dash in each column of the digits of the first line

     17282
    + 1342
     -----
    
  4. evaluate the expression and write the digits above each column if you need to 'carry' them

       1
     17282
    + 1342
     -----
     18624
    

Your output is what you get after applying step #4. You may have trailing whitespace, but there may not be any leading zeroes.

You must write a program or a function that prints or returns the output.

The input can be taken as either two separate inputs or an array with two items; the type of the inputs can be either string or integer.

This is code golf so shortest code in bytes wins!

Edit:

The largest number you could expect to receive as output/the sum is the largest integer that your system will display without exponents (thanks to Adám).

More examples:

Input: 
1596, 8404
Output:
1111
 8404
+1596
 ----
10000

Input:
1776, 76
Output:
  11
 1776
+  76
 ----
 1852

Input:
123, 456
Output:
 456
+123
 ---
 579
\$\endgroup\$
10
  • \$\begingroup\$ What are the bounds on the input? \$\endgroup\$
    – dj0wns
    Jul 28, 2016 at 20:21
  • \$\begingroup\$ I think it should be the largest integer that you system will display in non-exponential format. CC: @dj0wns \$\endgroup\$
    – Adám
    Jul 28, 2016 at 20:35
  • \$\begingroup\$ I have edited the question to include Adám's suggestion respecting the upper bound on the input. \$\endgroup\$
    – Daniel
    Jul 28, 2016 at 20:41
  • 2
    \$\begingroup\$ May we have an empty row at the start of the output if there is nothing to carry? I would argue yes, since on paper you have to have space free at the start of the process above the sum since you don't know if there will be carries or not. \$\endgroup\$
    – orlp
    Jul 28, 2016 at 21:11
  • 1
    \$\begingroup\$ @orlp, sure, optionally \$\endgroup\$
    – Daniel
    Jul 28, 2016 at 21:14

4 Answers 4

4
\$\begingroup\$

Dyalog APL, 90 bytes

{⌽↑(⊂⌽s),⍨↓⌽(' + ',⍨' 1'⊃⍨l<⍴s),'-'⍪⍨w⍪⍨' 1'[10|(⍎¨(-l←⍴⍉w)↑s←⍕+/⍵)-(+/0 10⊤⍎)¨⊂[0]w←⍕⍪⍵]}

Takes list of two numbers as argument. Needs ⎕IO←0 which is default on many systems.

      f←{⌽↑(⊂⌽s),⍨↓⌽(' + ',⍨' 1'⊃⍨l<⍴s),'-'⍪⍨w⍪⍨' 1'[10|(⍎¨(-l←≢⍉w)↑s←⍕+/⍵)-(+/0 10⊤⍎)¨⊂[0]w←⍕⍪⍵]}
      f¨(17282 1342)(1596 8404)(1776 76)(123 456)
┌──────┬─────┬─────┬────┐
│   1  │1111 │  11 │    │
│ 17282│ 1596│ 1776│ 123│
│+ 1342│+8404│+  76│+456│
│ -----│ ----│ ----│ ---│
│ 18624│10000│ 1852│ 579│
└──────┴─────┴─────┴────┘

TryAPL online! Note that ⎕IO has been set and has been emulated with e as is banned from TryAPL for security reasons.

Ungolfed and explained

{ An anonymous function

w ← ⍕ ⍪⍵ w gets the textified vertical arrangement of the argument (the numbers to be added)

l ← ≢ ⍉w s gets the count of rows in the transposed w (i.e. the number of columns in w)

s ← ⍕ +/⍵ s gets the textified sum of the argument

' 1'[... index into the string " 1", so zeros give spaces, and ones give character 1s.

⊂[0] w enclose down, gets list of pairs of corresponding digits in the numbers

(+/ 0 10 ⊤ ⍎)¨ for each pair; make into digit(s), then sum

(⍎¨ (-l) ↑ s)- chop left-most digit of grand total to the width of the longest input, then make each character into separate number and subtract the column sums (if the sum does not add up to the total, the discrepancies are due to carrys, so this gives us each column's carry)

10| division remainder when divided by 10

] [end of indexing]

w⍪⍨ stack the input numbers below

'-'⍪⍨ stack a minus below each column

(' + ',⍨' 1'⊃⍨l<⍴s), prepend a space to the 2nd line, a plus to the 3nd, a space to the 4rd, and a one or space to the 1st – depending on if the sum is wider than the widest input (meaning we need a carry high over the plus )

mirror right-left (so left-justification will be to the right)

make table into list of lines (so that differing line lengths are allowed

(⊂⌽s),⍨ append the sum

combine list of lines into table (padding the right with spaces as needed)

mirror back to normal

} [end of function]`

\$\endgroup\$
0
4
\$\begingroup\$

Python 2.7, 201 192 161 155 167 164 182 bytes:

(Saved 2 bytes (192->190) thanks to TheBikingViking)

def Q(T,Y):O,D=sorted([T,Y]);E=len(`D`);print'%s\n %s\n+%*s\n %s\n %d'%(''.join([' ',i[0]][len(i)>1]for i in[`sum(map(int,u))`for u in zip(`D`,'%0*d'%(E,O))]),D,E,O,'-'*E,sum([T,Y]))

A named function that takes input in any order while outputting the correct answer in order of magnitude from top to bottom.

Try it Online! (Ideone)


Alternatively, if allowed to take input in order of magnitude (i.e. bigger number first, then smallest), then here is a much smaller solution which also uses a named function at 164 bytes:

def Q(T,Y):E=len(`T`);print'%s\n %d\n+%*d\n %s\n %d'%(''.join([' ',i[0]][len(i)>1]for i in[`sum(map(int,u))`for u in zip(`T`,`Y`.zfill(E))]),T,E,Y,'-'*E,sum([T,Y]))

Try this Version Online! (Ideone)

\$\endgroup\$
5
  • \$\begingroup\$ join takes any iterable, including a generator statement, so you can drop the outer pair of [, ] within the call. \$\endgroup\$ Jul 28, 2016 at 21:23
  • \$\begingroup\$ @TheBikingViking Thanks! :) \$\endgroup\$
    – R. Kap
    Jul 28, 2016 at 21:26
  • \$\begingroup\$ You can also change E=max('T','Y',key=L) to E='max(T,Y)'. (I've used ' instead of backticks). \$\endgroup\$ Jul 28, 2016 at 21:31
  • \$\begingroup\$ @TheBikingViking Yeah, I was just doing that. \$\endgroup\$
    – R. Kap
    Jul 28, 2016 at 21:32
  • \$\begingroup\$ Converting to a function with def(T,Y,L=len): saves a few. \$\endgroup\$ Jul 28, 2016 at 21:48
2
\$\begingroup\$

Ruby, 192 191 bytes

Returns a multiline string. Input is an array with two strings.

Try it online!

->o{x,y=o.sort_by!(&:to_i).map{|e|e.reverse.chars}
a,b=o.map &:to_i
k=' '
y.zip(x).map{|z|i,j=z.map &:to_i
k=i+j+k.to_i<10?' ':1}.reverse*''+"
 %s
+%#{s=y.size}s
 %s
%#{s+1}s"%[b,a,?-*s,a+b]}
\$\endgroup\$
0
\$\begingroup\$

C (ansi), 392 384 Bytes

Saved 8 thanks to Value Ink (392->384)

Code:

char c[9],d[9],p[99]=" %s\n%0s\n+%0s\n %s\n%0i",*t,*b;k,r;main(a,i,m,n)char**i;{m=strlen(i[1]);n=strlen(i[2]);m==n?(strcmp(i[1],i[2])<0?t=i[2],b=i[1]:(t=i[1],b=i[2])):m<n?t=i[2],b=i[1]:(t=i[1],b=i[2]);n>m?:(n^=m,m=n^m,n=n^m);p[18]=p[5]=1+(p[10]=48+n);while(k<n)d[k]=45,a=(n-++k>=0)*(t[n-k]-48)+(m-k>=0)*(b[m-k]-48),r+=a*pow(10,k-1),c[n-k-1]=32+(a+c[n-k]%2>9)*17;printf(p,c,t,b,d,r);}

With Spacing:

char c[9],d[9], p[99] = " %s\n%0s\n+%0s\n %s\n%0i", *t,*b;
k,r;
main(a,i,m,n)char**i;{
    m=strlen(i[1]);     //get length of num 1
    n=strlen(i[2]);     //get length of num 2
                        //Set the larger number to the top pointer
    m==n?(strcmp(i[1],i[2])<0?t=i[2],b=i[1]:(t=i[1],b=i[2])):m<n?t=i[2],b=i[1]:(t=i[1],b=i[2]);
    n>m?:(n^=m,m=n^m,n=n^m); //set n to the longer length
    p[18]=p[5]=1+(p[10]=48+n); //set the buffers in the printf string

    while(k<n)     //for every number
        d[k]=45,   //add a dash
        a=(n-++k>=0)*(t[n-k]-48)+(m-k>=0)*(b[m-k]-48), //do the addition
        r+=a*pow(10.,(float)k-1), //add to result
        c[n-k-1]=32+(a+c[n-k]%2>9)*17;  //set 1 if carry or a space otherwise

    printf(p,c,t,b,d,r);    //print to stdio
}

Usage:

Compile Params:

gcc -O3 -ansi -lm -o add add.c

Input:

./add 2834 97829

Output:

  11 1
  97829
 + 2834
  -----
 100663

Notes:

Only works on numbers up to 8 in length - formatting is hard or I'm really bad at it

I feel like my approach was suboptimal

\$\endgroup\$
3
  • 1
    \$\begingroup\$ C lets you skip #include<stdio.h> like that? That's pretty cool. Intuitively, I don't think you need to cast (float)k-1 in your pow function because it should coerce to float anyways? But I'm unsure, maybe that's just C++. \$\endgroup\$
    – Value Ink
    Jul 28, 2016 at 23:28
  • \$\begingroup\$ @Value Ink, whether or not you can get away without includes is compiler specific behavior. In gcc I have only found one header I needed to include and that was openmp.h. You are correct on removing float, weird - I distinctly remember that not being the case \$\endgroup\$
    – dj0wns
    Jul 28, 2016 at 23:35
  • 1
    \$\begingroup\$ @ValueInk The header files are only needed for the prototypes of the functions. By default C compilers will assume the types of the parameters you give a function that hasn't been declared already are correct and always assume the return type is int. In the case of printf this fits perfectly, and the linker will find the function in the standard libraries with that signature after it has been compiled. \$\endgroup\$
    – Lemon Drop
    Jul 28, 2016 at 23:47

Not the answer you're looking for? Browse other questions tagged or ask your own question.