Https://www.codecademy.com/courses/learn-python/lessons/practice-makes-perfect/exercises/digitsum

I wanted to post this in python faq, but when I tried searching for it under the topics when creating this post it didn’t come up, and when I went to the python faq forum I couldn’t click on the topic button (it was greyed out). When I tried to reply to an already made post it had been locked my a moderator, so am having to create a new post in order to ask my question.

Anyway the question I have is related to the lesson: https://www.codecademy.com/courses/learn-python/lessons/practice-makes-perfect/exercises/digitsum.

The question I want to ask is why does it not accept an answer just by using the sum format? Like so:

def digit_sum(n):
 return sum(n)
print digit_sum([1,2,3,4])

As it still prints out 10 as the correct answer, it’s just the argument is entered as a list of arguments, rather then one argument, which then has to be turned into a string then concatenated together and then turned into an int, or the other way round. Even if the argument isn’t entered as a list when calling the function: print digit_sum(1234) an error is generated saying: int object is not iterable, I don’t know why this happens? Is it because python sees the argument as one object, and therefore cannot add it up, because it has nothing to add up?

The sum function is not what we’re expected to use. If I recall this exercise, we are handing in an integer. Integers cannot be iterated.

The idea of this exercise is that you are summing the digits of a single number. So if you had the number one hundred and twelve (112), it would sum the 3 digits to get 4. When you enter it as a list, you aren’t entering a single number, but a list of numbers, hence it is not meeting the goal of the lesson. That is also why sum doesn’t work, because you cannot sum a single digit.

Also just to add, but think of it from a user perspective (even if it seems silly). If you were to hand a user this function, what would be more intuitive to them: giving a single number of which the digits should be summed, or splitting that number into a list of digits first? Your way is technically a valid way of summing those digits, but it’s not a complete solution to the problem “sum the digits of a given number” since that number needs to be changed before input.

Broadly speaking, all the lessons in codecademy require you to do what they ask of you, even if there are other ways to get the same answer. The idea is that you actually see all the different ways of doing things, and work up to the correct way.

sum might return an answer that matches, but if you are being asked to add the numbers together yourself, then you have not passed the test requirements for that lesson until you do that.

Why can’t integers be iterated?

I understand what you’re saying, but if you asked the computer to add 112, it would see that as one individual number so would give the answer 224, as oppose to just 4 because it’s one individual number, but the exercise is asking me to add the individual digits of a complete number, which would somehow require me to break it up into individual numbers, then add them together, this is the only solution I can currently think of, where the computer can take a number argument (as an array of lists), then add them together, otherwise the result I end up with is the number + number, ie if the number was 1234, the output would be (1234 + 1234) 2468 as oppose to (1+2+3+4) 10. This is achieved by doing the following:

def digit_sum(n):
   n += n
   return n      
print digit_sum(1234)

You can alternatively do n *= 2 which would get the same result (2468).

There are two ways (essentially) of doing this…

  1. cast to string and iterate the characters; cast character to int and add
  2. reduce the number by successive modulo by ten, add, then floor divide by 10.
    s = 0
    for x in str(n):
        s += int(x)
    return s

OR

    s = 0
    while n > 0:
        s += n % 10
        n //= 10
    return s

I don’t understand why you can’t iterate over an int, and also I feel like this exercise is very illogical as adding single digits of a number completely goes against the principles of the unit structure numbers have, ie tens, hundreds etc. Why with the first solution do you have introduce a second variable (in your example it’s s), why does it not work if you use set the argument to 0 ie n = 0? I really have no idea how the floor division method works, to me on the surface it works the same as a normal division, ie if I do 10 // 2 I get 5. How does adding the remainder from dividing by 10 on to a variable, and then floor dividing it, get the right result? Same with the first answer why does a secondary variable have to be added to the function?

Because an int represents a single value, in and of itself. It is not enumerable because it is a number. Numbers are not a sequence of digits, but a magnitude or quantity.

Strings are iterable because they are a sequence of characters. Lists are iterable because they are a sequence of values. Same goes for tuples and sets.

>>> list(256)
Traceback (most recent call last):
  File "<pyshell#29>", line 1, in <module>
    list(256)
TypeError: 'int' object is not iterable
>>> list('256')
['2', '5', '6']

That makes sense, but I still don’t understand how floor division will get the result of adding a set of numbers together.

Do you mean here,

    s = 0
    while n > 0:
        s += n % 10
        n //= 10
    return s

The addition is done with the remainder of division by 10, the last digit. We still have to complete the division to arrive at the remaining digits. Since we are working with an integer, floor division returns an integer.

To see how this works, insert a print statement:

def digit_sum(n):
    s = 0
    while n > 0:
        print (n, n % 10)
        s += n % 10
        n //= 10
    return s

>>> digit_sum(12345)
12345 5
1234 4
123 3
12 2
1 1
15

I now understand why you’re using the modulo function, but surely once you’ve used % on the whole sequence from 1 -5 why do you need to then floor divide on n, is it so the number represented by n changes from 1234.5, to 1234?

Correct. We need to keep n as an integer.

Does modulo not also round up or down in the same way floor division does? For example:

x = 4
x //= 3.
print x

x = 4
x %= 3.
print x

In both examples (where the first uses floor division and the second modulo), the answer is 1.0, but when I divide by 10 I get two different answers, but neither is the answer I expect to see (0.4) ie:

x = 4
x = x % 10.
print x

x = 4
x = x // 10.
print x

In the first example I get 4.0 as the output, but in the second example I get 0.0, why do the two different methods, provide me with two different outputs and why does neither method return an output of 0.4?

Floor division is not rounding, but truncating.

 123 // 10  =>  12

Note the effect adding a decimal point:

 123 // 10.  =>  12.0

We don’t want to introduce a float into the solution, so don’t add the dot.

For all practical purposes don’t think, ‘modulo’, think, ‘remainder’

 4 / 10  =>  quotient, 0; remainder, 4

so,

4 % 10  =>  4  (remainder)

Not to be confused with floor division which focuses on the quotient:

4 // 10  =>  0  (quotient)

So where modulo is meant to give me the number plus the remainder, why is it when I do:

print 4 % 3

I get 1, surely it should also print the remainder as well, so the expected output should be 1.3?

4 / 3  =>  1.333...

Now multiply .333... by 4 and you get, 1 (almost). The remainder is what we get when we do integer division (no decimal fraction).

 3 )  4  |  1  <-  quotient
    - 3
    ____
      1        <-  remainder