Sum of digits in a string - python

if i just read my sum_digits function here, it makes sense in my head but it seems to be producing wrong results. Any tip?
def is_a_digit(s):
''' (str) -> bool
Precondition: len(s) == 1
Return True iff s is a string containing a single digit character (between
'0' and '9' inclusive).
>>> is_a_digit('7')
True
>>> is_a_digit('b')
False
'''
return '0' <= s and s <= '9'
def sum_digits(digit):
b = 0
for a in digit:
if is_a_digit(a) == True:
b = int(a)
b += 1
return b
For the function sum_digits, if i input sum_digits('hihello153john'), it should produce 9

Notice that you can easily solve this problem using built-in functions. This is a more idiomatic and efficient solution:
def sum_digits(digit):
return sum(int(x) for x in digit if x.isdigit())
print(sum_digits('hihello153john'))
=> 9
In particular, be aware that the is_a_digit() method already exists for string types, it's called isdigit().
And the whole loop in the sum_digits() function can be expressed more concisely using a generator expression as a parameter for the sum() built-in function, as shown above.

You're resetting the value of b on each iteration, if a is a digit.
Perhaps you want:
b += int(a)
Instead of:
b = int(a)
b += 1

Another way of using built in functions, is using the reduce function:
>>> numeric = lambda x: int(x) if x.isdigit() else 0
>>> reduce(lambda x, y: x + numeric(y), 'hihello153john', 0)
9

One liner
sum_digits = lambda x: sum(int(y) for y in x if y.isdigit())

I would like to propose a different solution using regx that covers two scenarios:
1.
Input = 'abcd45def05'
Output = 45 + 05 = 50
import re
print(sum(int(x) for x in re.findall(r'[0-9]+', my_str)))
Notice the '+' for one or more occurrences
2.
Input = 'abcd45def05'
Output = 4 + 5 + 0 + 5 = 14
import re
print(sum(int(x) for x in re.findall(r'[0-9]', my_str)))

Another way of doing it:
def digit_sum(n):
new_n = str(n)
sum = 0
for i in new_n:
sum += int(i)
return sum

An equivalent for your code, using list comprehensions:
def sum_digits(your_string):
return sum(int(x) for x in your_string if '0' <= x <= '9')
It will run faster then a "for" version, and saves a lot of code.

Just a variation to #oscar's answer, if we need the sum to be single digit,
def sum_digits(digit):
s = sum(int(x) for x in str(digit) if x.isdigit())
if len(str(s)) > 1:
return sum_digits(s)
else:
return s

#if string =he15ll15oo10
#sum of number =15+15+10=40
def sum_of_all_Number(s):
num = 0
sum = 0
for i in s:
if i.isdigit():
num = num * 10 + int(i)
else:
sum = sum + num
num = 0
return sum+num
#if string =he15ll15oo10
#sum of digit=1+5+1+5+1+0=13
def sum_of_Digit(s):
sum = 0
for i in s:
if i.isdigit():
sum= sum + int(i)
return sum
s = input("Enter any String ")
print("Sum of Number =", sum_of_all_Number(s))
print("Sum Of Digit =", sum_of_Digit(s))

simply turn the input to integer by int(a) ---> using a.isdigit to make sure the input not None ('') ,
if the input none make it 0 and return sum of the inputs in a string simply
def sum_str(a, b):
a = int(a) if a.isdigit() else 0
b = int(b) if b.isdigit() else 0
return f'{a+b}'

Related

Extracting number from alphanumeric string and adding them

Given string str containing alphanumeric characters. The task is to calculate the sum of all the numbers present in the string.
Example 1:
Input:
str = 1abc23
Output: 24
Explanation: 1 and 23 are numbers in the
a string which is added to get the sum as
24.
Example 2:
Input:
str = geeks4geeks
Output: 4
Explanation: 4 is the only number, so the
the sum is 4.
I broke down the problem into smaller parts, for first I just want to extract the numbers.
s = "a12bc3d"
number = ""
for i in range(0, len(s)):
if s[i].isdigit():
n=0
number = number + s[i]
while s[i].isdigit():
n = n+1
if s[i + n].isdigit():
number = number + s[i+n] + " "
else:
break
i = i + n + 1
else:
continue
print(number)
my output from the above code is 12 23 but it should be 12 3, as the for loop is starting from the initial point making 2 coming twice, I have tried to move the for loop forward by updating i = i + n + 1 but it's not working out like that.
It will be great if someone gives me a direction, any help is really appreciated.
A slightly simpler approach with regex:
import re
numbers_sum = sum(int(match) for match in re.findall(r'(\d+)', s))
Use itertools.groupby to break the string into groups of digits and not-digits; then convert the digit groups to int and sum them:
>>> from itertools import groupby
>>> def sum_numbers(s: str) -> int:
... return sum(int(''.join(g)) for d, g in groupby(s, str.isdigit) if d)
...
>>> sum_numbers("1abc23")
24
>>> sum_numbers("geeks4geeks")
4
you can use regex.
import re
s='a12bc3d'
sections = re.split('(\d+)',s)
numeric_sections = [int(x) for x in sections if x.isdigit()]
sum_ = sum(numeric_sections)
print(sum_)
I appreciate the solutions with regex and group-by. And I got the solution using logic as well.
`s = "4a7312cfh86"
slist = [i for i in s]
nlist = []
for i in range(len(slist)):
if slist[i].isdigit() and (i != (len(slist) - 1)):
if not slist[i + 1].isdigit():
nlist.append(slist[i])
else:
slist[i + 1] = slist[i] + slist[i + 1]
elif slist[i].isdigit() and (i == (len(slist) - 1)):
nlist.append(slist[i])
def addingElement(arr):
if len(arr) == 0:
return 0
return addingElement(arr[1:]) + int(arr[0])
print(addingElement(nlist))
Output - 7402

How to take an int, split it to digits, do some arithmetics and then append it to new int

Task:
Given an integer as input, Add code to take the individual digits and increase by 1.
For example, if the digit is 5, then it becomes 6. Please note that if the digit is 9 it becomes 0.
More examples
input: 2342 output: 3453
input: 9999 output: 0
input: 835193 output: 946204
I wrote this function but I know for sure this isn't way to write this code and I'm looking for some tips to write it in a more concise, efficient way. Please advise.
def new_num (num):
newnum = []
for i in range (0,len(str(num))):
upper = num%10
print(upper)
num = int(num/10)
print(num)
if upper == 9:
upper = 0
newnum.append(upper)
else:
upper+=1
newnum.append(upper)
strings = [str(newnum) for newnum in newnum]
a_string = "".join(strings)
an_integer = str(a_string)
new_int = int(an_integer[::-1])
return(new_int)
You could do this:-
n = '2349'
nn = ''
for i in n:
nn += '0' if i == '9' else str(int(i) + 1)
print(nn)
one of many possible improvements... replace the if/else with:
upper = (upper+1)%10
newnum.append(upper)
x= input('no = ')
x= '' + x
ans=[]
for i in x :
if int(i) == 9 :
ans.append(str(0))
else:
ans.append(str(int(i)+1))
ans=''.join(ans)
if int(ans) == 0:
ans = 0
print(ans.strip('0'))
This is the most basic code I can write, it can also be shortened to few lines
testInputs = [2342, 9999, 835193, 9]
def new_num (num):
return int("".join([str((int(d) + 1) % 10) for d in str(num)]))
result = [new_num(test) for test in testInputs]
print(result)
# [3453, 0, 946204, 0]
convert the num to string
convert the digit by using (int(d) + 1) % 10
join back the digits
parse the string as int
def newnum(x):
lis = list(str(x))
new_list = [int(i)+1 if int(i)<9 else 0 for i in lis]
new_list = map(str,new_list)
return int(''.join(new_list))
Take the number and convert to list of strings
Iterate through the list. Convert each element to int and add 1. The condition of digit 9 is included to produce 0 instead of 10
Map it back to strings and use join.
Return the output as int.

Find the first two nonzero digits of float number in Python?

I want to get the first two nonzero digits of a float number using math library.
for example for
x = 1.27
the answer would be
12
and for
x = 0.025
the answer would be
25
I could find the first and second nonzero number:
a = str(x)
o1 = int(a.replace('0', '')[1])
o2 = int(a.replace('0', '')[2])
and then I can concat them but I get
string index out of range
error for big numbers.
Here's one approach:
from itertools import islice
def first_n_nonzero_digits(l, n):
return ''.join(islice((i for i in str(l) if i not in {'0', '.'}), n))
first_n_nonzero_digits(1.27, 2)
# '12'
first_n_nonzero_digits(0.025, 2)
# '25'
Here's one without any imports and using sorted:
def first_n_nonzero_digits_v2(l, n):
return ''.join(sorted(str(x), key=lambda x: x in {'0', '.'}))[:2]
first_n_nonzero_digits_v2(1.27, 2)
# '12'
first_n_nonzero_digits_v2(0.025, 2)
# '25'
Here is a simple solution:
str(x).replace(".","").replace("0", "")[:2]
Try this:
def nonzeroDigits(f,n=2):
counter = 1
s = str(f).replace(".","")
for ndx,i in enumerate(s):
if i == "0":
counter = 1
continue
if counter >= n:
return s[ndx - n + 1: ndx + 1]
counter += 1
raise ValueError("Doesn't have non-zero consecutive Digits")
I have tired to make it as simple as possible without using any third-party library.
print(nonzeroDigits(1.27))
# print(nonzeroDigits(1.02)) # Raise ValueError Exception
print(nonzeroDigits(0.025))
Returns:
12
25

Find the numbers in string and Sum them using list comprehension [sum only 1-9] [duplicate]

if i just read my sum_digits function here, it makes sense in my head but it seems to be producing wrong results. Any tip?
def is_a_digit(s):
''' (str) -> bool
Precondition: len(s) == 1
Return True iff s is a string containing a single digit character (between
'0' and '9' inclusive).
>>> is_a_digit('7')
True
>>> is_a_digit('b')
False
'''
return '0' <= s and s <= '9'
def sum_digits(digit):
b = 0
for a in digit:
if is_a_digit(a) == True:
b = int(a)
b += 1
return b
For the function sum_digits, if i input sum_digits('hihello153john'), it should produce 9
Notice that you can easily solve this problem using built-in functions. This is a more idiomatic and efficient solution:
def sum_digits(digit):
return sum(int(x) for x in digit if x.isdigit())
print(sum_digits('hihello153john'))
=> 9
In particular, be aware that the is_a_digit() method already exists for string types, it's called isdigit().
And the whole loop in the sum_digits() function can be expressed more concisely using a generator expression as a parameter for the sum() built-in function, as shown above.
You're resetting the value of b on each iteration, if a is a digit.
Perhaps you want:
b += int(a)
Instead of:
b = int(a)
b += 1
Another way of using built in functions, is using the reduce function:
>>> numeric = lambda x: int(x) if x.isdigit() else 0
>>> reduce(lambda x, y: x + numeric(y), 'hihello153john', 0)
9
One liner
sum_digits = lambda x: sum(int(y) for y in x if y.isdigit())
I would like to propose a different solution using regx that covers two scenarios:
1.
Input = 'abcd45def05'
Output = 45 + 05 = 50
import re
print(sum(int(x) for x in re.findall(r'[0-9]+', my_str)))
Notice the '+' for one or more occurrences
2.
Input = 'abcd45def05'
Output = 4 + 5 + 0 + 5 = 14
import re
print(sum(int(x) for x in re.findall(r'[0-9]', my_str)))
Another way of doing it:
def digit_sum(n):
new_n = str(n)
sum = 0
for i in new_n:
sum += int(i)
return sum
An equivalent for your code, using list comprehensions:
def sum_digits(your_string):
return sum(int(x) for x in your_string if '0' <= x <= '9')
It will run faster then a "for" version, and saves a lot of code.
Just a variation to #oscar's answer, if we need the sum to be single digit,
def sum_digits(digit):
s = sum(int(x) for x in str(digit) if x.isdigit())
if len(str(s)) > 1:
return sum_digits(s)
else:
return s
#if string =he15ll15oo10
#sum of number =15+15+10=40
def sum_of_all_Number(s):
num = 0
sum = 0
for i in s:
if i.isdigit():
num = num * 10 + int(i)
else:
sum = sum + num
num = 0
return sum+num
#if string =he15ll15oo10
#sum of digit=1+5+1+5+1+0=13
def sum_of_Digit(s):
sum = 0
for i in s:
if i.isdigit():
sum= sum + int(i)
return sum
s = input("Enter any String ")
print("Sum of Number =", sum_of_all_Number(s))
print("Sum Of Digit =", sum_of_Digit(s))
simply turn the input to integer by int(a) ---> using a.isdigit to make sure the input not None ('') ,
if the input none make it 0 and return sum of the inputs in a string simply
def sum_str(a, b):
a = int(a) if a.isdigit() else 0
b = int(b) if b.isdigit() else 0
return f'{a+b}'

Joining elements in a list without the join command

I need to join the elements in a list without using the join command, so if for example I have the list:
[12,4,15,11]
The output should be:
1241511
Here is my code so far:
def lists(list1):
answer = 0
h = len(list1)
while list1 != []:
answer = answer + list1[0] * 10 ** h
h = h - 1
list1.pop(0)
print(answer)
But, in the end, the answer ends up being 125610 which is clearly wrong.
I think the logic is OK, but I can't find the problem?
If you just want to print the number rather than return an actual int:
>>> a = [12,4,15,11]
>>> print(*a, sep='')
1241511
You could just convert each element to a string, add them, and then convert back to an int:
def lists(list1):
answer=''
for number in list1:
answer+=str(number)
print(int(answer))
lists([12,4,15,11])
>>>
1241511
s = ""
for x in map(str, x):
s += x
print(s)
1241511
There can be few more options like
Option1
>>> lst=[12,4,15,11]
>>> str(lst).translate(None, '[,] ')
'1241511'
Option 2
>>> join = lambda e: str(e[0]) + join(e[1:]) if e else ""
>>> join(lst)
'1241511'
Option 3
>>> ("{}"*len(lst)).format(*lst)
'1241511'
Option 4
>>> reduce(lambda a,b:a+b,map(str,lst))
'1241511'
a numeric solution, using your code
import math
def numdig(n):
#only positive numbers
if n > 0:
return int(math.log10(n))+1
else:
return 1
def lists(list1):
answer = 0
h = 0
while list1 != []:
answer = answer * 10 ** h + list1[0]
list1.pop(0)
if list1 != []:
h = numdig(list1[0])
print(answer)
lists([12,4,15,11])
You may try map and reduce with lambda like this:
def without_join(alist):
try:
return int(reduce(lambda a,b: a + b, map(str, alist)))
except ValueError, error:
print error
return None
print without_join([12,4,15,11])
Here's an entirely numerical solution, playing off of your notion of messing with powers of 10. You were on the right track, but your implementation assumed all values were 1 digit long.
import math
def lists(list1):
b = 0
foo = 0
for item in reversed(list1):
b += item*(10**foo)
foo += int(math.floor(math.log10(item))) + 1
return b
a = [12, 4, 15, 11]
print lists(a)
This returns 1241511, as requested.
All I'm doing here is looping through the list in reverse order and keeping track of how many digits to the left I need to shift each value. This allows integers with an arbitrary number of digits.
list_name_of_program = [a,b,c,d,e,f]
program = ""
for pro in list_name_of_program:
program += str(pro)
program += "," # you can use seprator a space " " or different
print(program[:-1])
Output:
'a,b,c,d,e,f'

Categories