# Dissecting an interview question: math is hard (part 2)

[Updated: This post is now public – commenting on submissions takes a lot of time to do right!]

Thank you for your submission! As promised, here’s the second half of the post – the actual dissection of the problem.

So first, let’s talk through the basic algorithm for addition:

1. Put one number on top, the other number on the bottom (traditionally, the number with more digits goes on top, but this is visual sugar, not a requirement)
2. There’s a third row used for the “carry”
3. Moving right to left, for each column:
• Add the numbers in the column
• Put the result%10 into the answer
• If the result >= 10, put a one into the “carry” row for the next column to the left
4. Once you are past the last column on the left (including the carry), you’re done!
`1234 + 567 = ?`
```1234
567
----```
```  1
1234
567
----
1```
``` 11
1234
567
----
01```
``` 11
1234
567
----
801```
``` 11
1234
567
----
1801```

OK, that’s a little pedantic, but it makes the point. So, how do you get your code to do that? First, as always, let’s start out with a stub.

```String add(String a, String b) {
}```

Next, we need to make sure we’re handling the carry correctly. Although conceptually there’s a third row, all we need to know is whether we had a carry from the last column.

```String add(String a, String b) {
}```

Let’s set up a variable for an answer, move right to left, add the contents of each column with the carry and put it into the answer.

```String add(String a, String b) {
for (every column, right to left) {
int temp = a + b + (carry ? 1 : 0);
carry = temp >= 10;
}
}```

Note that I’m pre-pending the sum to the answer – we’ll come back to this later.

Lastly, we have to specify what happens if there’s a carry at the very end (e.g., if you add “6” and “4”).

```String add(String a, String b) {
for (every column, right to left) {
int temp = a + b + (carry ? 1 : 0);
carry = temp >= 10;
}
if (carry) {
}
}```

OK, so here are the outlines of an answer. It’s ugly, and there are a lot of details that need to get worked out, but the basic algorithm is there.

Before we go any further, and because it hurts my eyes, let’s handle the carry a little more elegantly. It makes intuitive sense to treat it as a boolean, but it’s faster, simpler, and more maintainable to replace it with an int, and to make the carry just like the other numbers in the column:

```String add(String a, String b) {
for (every column, right to left) {
int temp = a + b + carry;
carry = temp / 10;
}
if (carry > 0) {
}
}```

The next problem we have is to actually get the numbers from the columns. Let’s assume we have a method `atoi()` to convert chars ‘0’ – ‘9’ to ints 0 – 9.

```String add(String a, String b) {
for (int i = each column index, from right to left) {
int a_value = atoi(a.charAt(i));
int b_value = atoi(b.charAt(i));
int temp = a_value + b_value + carry;
carry = temp / 10;
}
if (carry > 0) {
}
}```

Well, this isn’t quite right. The two numbers might have a different number of digits, so 1) using the same index won’t necessarily give us numbers from the same column, and 2) we could run out of digits in one `String` before the other. What we want is to be counting from the end of the `Strings`.

```String add(String a, String b) {
for (int i = 0; i < a.length() || i < b.length(); i++) {
int a_value = atoi(a.charAt(a.length() - i - 1));
int b_value = atoi(b.charAt(b.length() - i - 1));
int temp = a_value + b_value + carry;
carry = temp / 10;
}
if (carry > 0) {
}
}```

Let’s also make sure we aren’t running off the front of the `Strings`:

```String add(String a, String b) {
for (int i = 0; i < a.length() || i < b.length(); i++) {
int a_value = i >= a.length() ? 0 : atoi(a.charAt(a.length() - i - 1));
int b_value = i >= b.length() ? 0 : atoi(b.charAt(b.length() - i - 1));
int temp = a_value + b_value + carry;
carry = temp / 10;
}
if (carry > 0) {
}
}```

We seem to be using `a.length()` and `b.length()` a lot. Let’s tidy that up.

```String add(String a, String b) {
int alen = a.length();
int blen = b.length();
for (int i = 0; i < alen || i < blen; i++) {
int a_value = i >= alen ? 0 : atoi(a.charAt(alen - i - 1));
int b_value = i >= blen ? 0 : atoi(b.charAt(blen - i - 1));
int temp = a_value + b_value + carry;
carry = temp / 10;
}
if (carry > 0) {
}
}```

Lastly, that special case at the end of the method is bothering me a little. We don’t really have to change it, but let’s just get rid of it to make the code a little cleaner (if slightly less performant).

```String add(String a, String b) {
int alen = a.length();
int blen = b.length();
for (int i = 0; i < alen || i < blen || carry > 0; i++) {
int a_value = i >= alen ? 0 : atoi(a.charAt(alen - i - 1));
int b_value = i >= blen ? 0 : atoi(b.charAt(blen - i - 1));
int temp = a_value + b_value + carry;
carry = temp / 10;
}
}```

Voila! We’re done, right? No, not yet. First, let’s talk about `atoi()`. This is an area where people tend to completely blank. Some try to do the following:

```int atoi(char ch) {
return Integer.valueOf(ch);
}```

This is nonsensical, of course – they’re trying to treat `ch` as a `String`. Others will explicitly convert the char into a `String`, then use `Integer.valueOf()` – which works, I guess, but is pretty ugly. It’s great to see a candidate who understands that chars are fundamentally numbers, and can do this:

```int atoi(char ch) {
return ch - '0';
}```

Honestly, I used to care a lot more about this, but along with expecting coders to know key ASCII values, powers of two, and bit math, I’ve pretty much thrown up my hands and accepted that these are lost skills. Still, if you know how to do this, you’ll bring a smile to your interviewer’s face.

So what do you think the big-O time is for the code above? Most people will look at it and answer “O(n)”. Unfortunately, the answer is actually O(n2). Can you see why? As described in this post, concatenating `Strings` in a loop is a common but costly mistake. Not only is it O(n2) time, it also allocates O(n2) bytes of memory – most of this is immediately garbage collected, but that puts additional pressure on GC, and can have disastrous results. Luckily, avoiding this is straightforward – just use a `StringBuilder`.

```String add(String a, String b) {
int alen = a.length();
int blen = b.length();
for (int i = 0; i < alen || i < blen || carry > 0; i++) {
int a_value = i >= alen ? 0 : (a.charAt(alen - i - 1) - '0');
int b_value = i >= blen ? 0 : (b.charAt(blen - i - 1) - '0');
int temp = a_value + b_value + carry;
carry = temp / 10;
}
}```

Hmm, well, that won’t work – we’re appending to the `StringBuilder`, not prepending, so our answer is going to come out reversed. Luckily, it’s easy to reverse a `StringBuilder` object:

```String add(String a, String b) {
int alen = a.length();
int blen = b.length();
for (int i = 0; i < alen || i < blen || carry > 0; i++) {
int a_value = i >= alen ? 0 : (a.charAt(alen - i - 1) - '0');
int b_value = i >= blen ? 0 : (b.charAt(blen - i - 1) - '0');
int temp = a_value + b_value + carry;
carry = temp / 10;
}
}```

If you’re feeling plucky, you can do an in-place reversal of `answer` using `charAt()` and `setCharAt()`, but you get the idea. The only thing left is to set the `StringBuilder` capacity up-front, so as to avoid having to resize and copy it as it grows past the bounds of its buffer.

```String add(String a, String b) {
int alen = a.length();
int blen = b.length();
int max_answer_len = (alen > blen ? alen : blen) + 1;
for (int i = 0; i < alen || i < blen || carry > 0; i++) {
int a_value = i >= alen ? 0 : (a.charAt(alen - i - 1) - '0');
int b_value = i >= blen ? 0 : (b.charAt(blen - i - 1) - '0');
int temp = a_value + b_value + carry;
carry = temp / 10;
}
}```

As you can see, there are a lot of places to make mistakes. Not knowing how to convert chars to ints. Not reversing the `String`, or forgetting to handle the case where there’s a carry at the end of the loop. Terrible big-O time. Messing up the column indexing. Logical errors. Off-by-one errors. Not handling `Strings` of different sizes.

Being able to translate an algorithm into code is the defining characteristic of a software engineer, and this is a straightforward algorithm that everyone knows (well, there was that one candidate who tried to convince me that he didn’t add often). If your code had problems, then now is the time to practice – especially if you’re about to start interviewing. Try adding a list of numbers. Try it with decimals, or negative numbers. Try multiplication (division is no fun – I’d recommend against it, unless you like pain). The nice thing about arithmetic is that it’s incredibly easy to test, so you can do these types of exercises on your own and still be confident that your solution works.

Anyway, thanks for taking part in the challenge – I hope you enjoyed it!

## 4 thoughts on “Dissecting an interview question: math is hard (part 2)”

1. Frank J Kelly says:

I think you should trim() your Strings just in case :-)

• Dan says:

Normally, you should do a lot of data validation. But I specifically ask candidates to assume that the input is valid, so we can focus on the part of the problem I care most about. :)

2. Michael Burjack (@MichaelBurjack) says:

I liked your shortcut of using modulo to snag the ‘ones’ digit; I kick myself for not thinking about that, especially given I’m doing a bunch of modulo-based programming at the moment! Much more concise than the alternative.

My original Perl one-liner solution had the nasty bug of losing a leading carry semaphore, so ‘6’ + ‘4’ = ‘0’ as per the caution in your post. Of course, I noticed this after I tweeted.

I’ve updated my nasty Perl one-liner version to:

%> perl -E’@a=split//,shift;@b=split//,shift;while(@a+@b+\$d){\$d+=pop(@a)+pop(@b);\$s=(\$d%10).\$s;\$d=int\$d/10}say\$s’ 987 654
1641

Even shorter, leaving lots of extra room in a tweet now!

3. David Parmenter says:

Yep, last modulo operation to get the carry is excellent. I could not find that in ‘simulated exam conditions’ that I self-imposed.

Dan, I’m sure you’re busy, but can you say anything about the solutions you looked at and that you’ve seen in your day job?