I am trying to write a recursive method as follows, but I am getting SyntaxError: invalid syntax, I wonder what I am doing wrong
Given a non-negative integer num, repeatedly add all its digits until
the result has only one digit.
For example:
Given num = 38, the process is like: 3 + 8 = 11, 1 + 1 = 2. Since 2
has only one digit, return it.
class Solution(object):
def addDigits(self, num):
"""
:type num: int
:rtype: int
"""
return self.addDigits(x=sum(i for i in str(num)) if x%9<10:
Note:
I am learning recursion in python, therefore rather than knowing how to solve problem, I would love to learn what I am doing wrong in my implementation.
Updated to match the new question description:
def add_digits(x):
return (x - 1) % 9 + 1 if x else 0
If you apply the brute force version of this solution (the one you were originally attempting) then you will see the output is actually the sequence listed here: https://oeis.org/A010888.
Once we know that this is a repeating sequence we can look for patterns in the sequence, and in this case we realize that the function in this answer provides a guaranteed solution in O(1) time and space.
You can actually see the relationship to n % 9 by seeing this sequence here: https://oeis.org/A010878
Related
So I answered one of the questions on Coding Bat that asked to return half of a string n number of times by defining a variable that takes half the length of the original string and using that variable in slicing the string.
Coding bat accepted the result, but when I try to recreate the problem on Jupyter Notebook it only accepts "integers or None or index method".
What am I doing wrong?
Im a beginner in Python and just want to make sure that I'm learning the correct format.
def first_half(str):
newword = len(str) / 2
return '{}'.format(str[:newword])
for first_half('Milkshakes') I expect to get 'Milk'.
However, the error im getting is:
TypeError: slice indices must be integers or None or have an __index__ method
This is because len(str) / 2 gives you a float value 5.0 and you cannot use a float as a argument to string slice, convert the argument to an int by doing int(len(str) / 2), which gives you 5, and it should work. Note that the above only holds true for Python 3 the original code you have still works for Python 2 where you don't need the float to int conversion
Also str is a python builtin, so it's bad practice to use it as a variable.
In addition, you want the first half of Milkshakes is Milks, and not Milk
def first_half(s):
#Parse float to int
newword = int(len(s) / 2)
return '{}'.format(s[:newword])
print(first_half('Milkshakes'))
#Milks
To make a generic solution, as some of the commentors have suggested, you can use integer division //, which works for both Python 2 and Python 3
def first_half(s):
#Integer division
newword = len(s) // 2
return '{}'.format(s[:newword])
print(first_half('Milkshakes'))
My assignment is:
"Write a function sumOfDigits that has one parameter of type string. The function should return the
sum of the digits in the string. Do not treat multiple digit string as one number – “2014” should be
treated as 4 different digits of 2, 0, 1, 4. The function should return 17 for the string “Today’s date
is 09/01/2014”. You can assume the parameter is a string. No need to do any type validation."
Here's what I've got so far (with appropriate indentation):
def sumOfDigits (string1: str):
summation=0
for i in string1:
summation=summation + int (i)
return (summation)
print (sumOfDigits ('543tf'))
I get the following error:
"Traceback (most recent call last):
File "C:\Users\Andrew\Desktop\lab3.py", line 45, in <module>
print (sumOfDigits ('543tf'))
File "C:\Users\Andrew\Desktop\lab3.py", line 42, in sumOfDigits
summation=summation + int (i)
ValueError: invalid literal for int() with base 10: 't'"
How do I solve this? Is it doing this because of the difficulties associated with adding an int and string/char?
The problem is that int(x) fails unless x is a digit. The solution is to sum only the digits. For this purpose, python has the string method isdigit. For example:
>>> s = '543tf'
>>> sum(int(x) for x in s if x.isdigit())
12
And:
>>> s = "Today’s date is 09/01/2014"
>>> sum(int(x) for x in s if x.isdigit())
17
Python3
Unicode has added a large number of characters and python classifies some of them as digits even if int does not accept them. One such example is superscript 3: ³. To deal with this, python3 has introduced isdecimal and made it more discriminating than isdigit. Thus, in python3, one can use:
>>> s = "Today’s date is 09/01/2014 See footnote³"
>>> sum(int(x) for x in s if x.isdecimal())
17
You can do type-checking like what the other people have mentioned, or just pass the exception in the following manner (with minimal modification to your code so it is easy to see how it works):
def sumOfDigits (string1):
summation=0
for i in string1:
try:
summation = summation + int(i)
except:
pass
return (summation)
This is one of the philosophies of Python that says that you assume that the input is correct and only catch the exceptions and handle them separately. You might even want to explicitely check for the ValueError rather than catching all exceptions. Bit the details depend upon you.
You can't cast a char to an int and expect it to return 0 if it's not an int and its numerical value otherwise. You need to split up the string, check if the characters represent integers, and add those up. Like this:
def sumdigits(mystring):
summation = 0
for letter in list(mystring):
if letter.isdigit():
summation += int(letter)
return summation
This will do the trick:
sum(int(d) for d in '09/01/2014' if d.isdigit())
but I don't recommend handing it in without being able to explain how it works :-)
You could also try figuring out how
sum(map(int,filter(str.isdigit,'09/01/2014')))
works.
Your attempt is not failing 'because of difficulties of adding ints to char' (at least not directly), it's actually failing before that: when you try to convert something that doesn't look remotely like a number ('t') into an int. Which is what the error message is trying to tell you (right at the very bottom: 'ValueError etc.'). How do you solve it? You remove the stuff that can't be converted to int before attempting the conversion. The two code samples I gave you contain hints suggesting two different ways you might do it.
There are many ways to skin this cat.
One is to use a regex to find the single digits:
>>> import re
>>> re.findall(r'(\d)', '543tf')
['5', '4', '3']
Put that inside of map and convert to ints:
>>> map(int, re.findall(r'(\d)', '543tf'))
[5, 4, 3]
Put that into sum to sum the list:
>>> sum(map(int, re.findall(r'(\d)', '543tf')))
12
Say I have a string = '123' but I want to convert it into 123 without using the int() function. How would I go upon doing this using recursion?
The idea I have so far is to put the string into an array as such ['1','2','3'] and then convert them based on ASCII representations.
for i in string:
myArr.append (ord(i) - ord('0'))
So now I'd have a list looking like [1,2,3]. What should I do next to recursively get 123?
I have an idea of using the place values and add them together (ie. 100 + 20 + 3 = 123), but I don't know how to do this. Any ideas would be helpful !
I guess this is an academic exercise, because it's a rather contrived thing to ask. Here's how, assuming that s represents an integer number greater than or equal to zero:
def strToInt(s, acc):
if not s:
return acc
return strToInt(s[1:], 10 * acc + ord(s[0]) - 48)
Or even shorter:
def strToInt(s, acc):
return strToInt(s[1:], 10 * acc + ord(s[0]) - 48) if s else acc
The trick is to accumulate the result of the conversion in an extra parameter, this has the nice side effect of yielding a tail-recursive solution (not that it matters much in Python, but still…). Also notice how we use ord() to get the numeric value of a character representing a digit, and by simply subtracting 48 we get to the actual digit's value. Test it, it works as expected:
strToInt('123', 0) # the accumulator always starts in zero
=> 123
This wouldn't be recursive (I don't think you understand what that means), but:
for char in string:
array.append(ord(char) - ord('0'))
array.reverse()
num = 0
for index, val in enumerate(array):
num += val * (10 ** index)
EDIT: Ah, I see this is for an exercise. Yeah, it's a ridiculous problem to solve via recursion, but one of the other answers does it.
Another possibility:
def strToInt(s):
if s:
return (ord(s[-1]) - ord('0')) + 10 * strToInt(s[:-1])
else:
return 0
The first thing that comes to mind is the famous C method atoi().
Python had a similar method, also called atoi(), but it was deprecated, with the instruction to use int().
Therefore, despite your comment, I would recommend using int(). Python documentation encourages you to use it, so do so without fear.
int() documentation for Python 2.7
int() documentation for Python 3.3
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I'm taking an introductory Python course and we have an assignment that asks us to simulate the way the floating point numbers are stored.
Basically, we have to demonstrate 5 digits of Mantissa. For example, you input 123 and it must come out as 12300. If you input 12345678 it must come out as 12345. How can this be done? Is there a function for that or is it just a formmating issue? Keep in mind, this is an introductory course and we're not allowed to use any external libraries.
You can use Python's string formatting functionality:
'{:<05d}'.format(number)[:5]
Some examples:
>>> '{:<05d}'.format(123)[:5]
'12300'
>>> '{:<05d}'.format(12345678)[:5]
'12345'
Some clarification:
< says: align the number on the left.
0 says: use 0 as padding character.
5 says: set the width to at least five.
d says: it's a decimal.
As the number can be longer than five digits we take only the first five characters by doing [:5]. This is called slice notation and it allows you to take a slice of a string.
So, let's try taking the problem, and writing the rough framework of what we have to do. Notice that whenever I run into a problem that isn't immediately obvious, I push it into its own function, which I can deal with later:
string = str(number)
if len(string) > 5:
string = truncate_string(string)
elif len(string) < 5:
string = pad_string_with_zeros(string)
So, let's try implementing truncate_string and pad_string_with_zeros.
A string is basically a list of characters. How would we get the first 5 elements of a list? Through list slicing. Therefore, we can implement truncate_string like so:
def truncate_string(string):
return string[:5]
How do we pad strings with zeros? Well, if you consult the Python documentation, you could use the ljust function:
>>> '11'.ljust(5, '0')
'11000'
>>> '12345678'.ljust(5, '0')
'12345'
Therefore, our function could be:
def pad_string_with_zeros(string):
return string.ljust(5, '0')
Alternatively, we could have used a while loop:
def pad_string_with_zeros(string):
while len(string) < 5:
string += '0'
...although that'll be more inefficient.
If we move all our functions into the main code, then we might get something like this:
string = str(number)
if len(string) > 5:
string = string[:5]
elif len(string) < 5:
string = string.ljust(5, '0')
As it turns out, list slicing will not throw errors, even if you pass in too small or too large strings. For example, '12'[:5] will result in the string '12'.
Therefore, we don't need to even check for the size of the string, and can compact it down to the following lines:
string = str(number)
string = string[:5].ljust(5, '0')
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Convert an integer to binary without using the built-in bin function
This function receives as a parameter a number in base 10 and should return a list representing the same value expressed in binary as a list of bits, where the first element in the list is the most significant (leftmost) bit.
convert_10_to_2(11) should return [1, 0, 1, 1]
I cannot use the binary function or outside functions, so it has to be done in a more complicated way.
b = ''
while num > 0:
b = str(num % 2) + b
num >>= 1
return (b)
Okay I got my code finally up, okay I get '1011', but I need [1,0,1,1], I can't really use any functions such as bin(x) or binary_list. That has been what's taking this question so long.
You can initialize a list, then iterate through the string using a for loop and append the value to the list every iteration, like such.
binary_string = convert_10_to_2(11)
binary_list = []
for character in binary_string:
binary_list.append(int(character))
bin(X), x is the integer the function returns a binary string
MORE # python build in functions
This will work for both Python 2.x and 3.x:
list(map(int, '{:b}'.format(11)))
Replace 11 with other number, if you wish. Remove enclosing list call, if you do not need support for Python 3.x. Enclose it in function, if you really find it necessary.