Sum of Digits in a specific way in Python - python

I'm looking for a code that runs, i.e:
int(input) = 2565
Printed Output should be like:
2 + 5 + 6 + 5 = 18 = 1 + 8 = 9
I wrote the code that gives final answer "9". But I couldn't managed to write it with every digit separated "+" sign. Assuming that I need to use while loop but how can I write the code so it will be like the output above?

You can use something like this:
def sum_of_digits(s):
if s < 10:
return s
return sum_of_digits(sum(int(c) for c in str(s)))
> sum_of_digits(2565)
9
It recursively checks if the numerical value is less than 10. If it does, it returns this value. If not, it adds the digits, then recursively calls itself on the result.
Edit
To print out the steps as it goes along, you could do something like this:
def sum_of_digits(s):
if s < 10:
print(s)
return s
print(' + '.join(c for c in str(s)) + ' = ')
return sum_of_digits(sum(int(c) for c in str(s)))

First, initiate an empty string output_str.
With a while loop which contniues when our integer is > 9:
[s for s in str(x)] would create a list of the digits (as strings) of our integer. It's called a list comprehension, is very useful, and my advice is to read a bit about it.
With " + ".join() we create a string with " + " between the
digits. Add this string at the end of output_str.
Add " = " to the end of output_str.
Calculate the sum of the digits (we cannot use sum(lst_of_digits) because it's a list of strings. sum([int(s) for s in lst_of_digits]) converts the string list into an inter list, which can be summed using sum()). Store the sum into x.
Add the new x + " = " to output_string.
At the end of the string, we have a redundant " = " (because the last (5) was not needed), let's just remove the last 3 chars (=) from it.
x = 2565
output_str = ""
while x > 9:
lst_of_digits = [s for s in str(x)]
output_str += " + ".join(lst_of_digits)
output_str += " = "
x = sum([int(s) for s in lst_of_digits])
output_str += f"{x} = "
output_str = output_str[:-3]
outputs:
output_str = '2 + 5 + 6 + 5 = 18 = 1 + 8 = 9'

You can play around with the end keyword argument of the print function which is the last character/string that print will put after all of its arguments are, well, printed, by default is "\n" but it can be change to your desire.
And the .join method from string which put the given string between the given list/iterable of strings to get the desire result:
>>> " + ".join("123")
'1 + 2 + 3'
>>>
Mixing it all together:
def sum_digit(n):
s = sum(map(int,str(n)))
print(" + ".join(str(n)),"=",s, end="")
if s<10:
print()
return s
else:
print(" = ",end="")
return sum_digit(s)
Here we first get the sum of the digit on s, and print it as desire, with end="" print will not go to the next line which is necessary for the recursive step, then we check if done, and in that case print a new empty line if not we print an additional = to tie it for the next recursive step
>>> sum_digit(2565)
2 + 5 + 6 + 5 = 18 = 1 + 8 = 9
9
>>>
This can be easily be modify to just return the accumulated string by adding an extra argument or to be iterative but I leave those as exercise for the reader :)

I am a noob but this should do what you want.
Cheers,
Guglielmo
import math
import sys
def sumdigits(number):
digits = []
for i in range( int(math.log10(number)) + 1):
digits.append(int(number%10))
number = number/10
digits.reverse()
string = ''
thesum = 0
for i,x in enumerate(digits):
string += str(x)
thesum += x
if i != len(digits)-1: string += ' + '
else: string += ' = '
if thesum > 10:
return string,thesum,int(math.log10(number))+1
else:
return string,thesum,0
def main():
number = float(sys.argv[1])
finalstring = ''
string,thesum,order = sumdigits(number)
finalstring += string
finalstring += str(thesum)
while order > 0:
finalstring += ' = '
string,thesum,order = sumdigits(thesum)
finalstring += string
finalstring += str(thesum)
print 'myinput = ',int(number)
print 'Output = ',finalstring
if __name__ == "__main__":
main()

Related

How to join list elements into strings?

I have a list here where I only need to input 10 letters or strings. I am having a problem separating the list.
print ("Please input letter: \n")
num_string = []
num = 10
for i in range (0,num):
element = str(input(str(i + 1) + ". "))
num_string.append(element)
string = ' '.join([str(item) for item in num_string])
print (string)
In my code, for example, I inputted a b c d e f g h i j since it is only 10 inputs. Instead of having an output like a b c d e f g h i j because I used the join method, I want to have a NewLine for every list. So I want it to be like
a
b
c
d
e
f
g
h
i
j
You are almost there just instead of joining a whitespace, join a newline, also you don't need to convert each element to string because each element is a string already because input always returns a string (in Python3) (so this is redundant: str(input()), it is the exact same as: input()):
string = '\n'.join(num_string)
Complete example (removed the redundant str):
print("Please input letter: \n")
num_string = []
num = 10
# the 0 isn't necessary either but
# I guess for clarification it can stay
for i in range(0, num):
element = input(str(i + 1) + ". ")
num_string.append(element)
string = '\n'.join(num_string)
print(string)
Alternatively you can use this (instead of the last two lines in the above code example):
print(*num_string, sep='\n')
And if you really want to shorten the code (it can be as short as 3 lines):
print("Please input letter: \n")
num = 10
print('\n'.join(input(f'{i + 1}. ') for i in range(num)))
print ("Please input letter: \n")
num_string = []
num = 10
for i in range (0,num):
element = str(input(str(i + 1) + ". "))
num_string.append(element)
string = '\n' .join([str(item) for item in num_string])
print (string)
Use '\n' , it is like a breakline in your output

Adding blank spaces to a list of strings at a specific position

I am trying to process a list of strings in order to get all my strings with 8 characters. If a string has less than 8 characters I fill as many blank spaces as needed to get an 8 character long string before the last 4 characters. I wrote the following function and tried to apply it to a list of strings, but got a list with None values.
def lengthstring(string):
if len(string) == 5:
new_string = string[0] + " " + string[1:5]
elif len(string) == 6:
new_string = string[0:2] + " " + string[2:6]
elif len(string) == 7:
new_string = string[0:3] + " " + string[3:7]
else:
new_string = string
lp = ['7C246', '7B8451', 'NDKW0745', '5B06833']
labels_with_eight_characters = [lengthstring(string) for string in lp]
Thank you!
Just in case you need a more concise version of the code:
def lengthstring(string):
return (
string if len(string) >= 8
else string[:-4] + ' ' * (8 - len(string)) + string[-4:])
labels_with_eight_characters = list(map(lengthstring, lp))
print(labels_with_eight_characters)
This prints:
['7 C246', '7B 8451', 'NDKW0745', '5B0 6833']
This is because you did not return values in your lengthstring function. After new_string = string, add return new_string and your code should run fine.
a little easier would be to use rjust...
for loc in lp:
print(loc.rjust(8, ' '))

Object of type NoneType has no length error

I have written the following function to add the elements of a list to a string.
import random
import string
def printmatches (word,x):
y = len(word)
z = [" "] *y
i = 0
while i<y:
if word[i] == x:
z[i] = x
else:
z[i] = " "
i+=1
return (z)
def append(string,chars): ##append list to a string
q = 0
while q < len(string):
if string[q] == " " and chars[q] != " ":
string[q] = chars[q]
q+=1
x = random.randint(0,55899)
def convertlist(x):
q = " "
a = 0
while (a < len(x)):
q+=x[a]
a+=1
return (q)
try:
f = open('words.txt', 'r')
s = " "
s = f.readline()
L = s.split()
word = L[x]
f.close()
except IOError:
print('file not found')
q=0
print word
print (printmatches('ereesvox','o') == [" "] * 8)
current = [" "] * len(word)
c = 0
char = " "
while char != word and q < 3 and c <35:
char = raw_input (" ")
c+=1
##current.append(printmatches(word,char))
append(current, printmatches(word,char))
str = (append(current, printmatches(word,char)))
if (convertlist(str) == word):
print 'Congratulations, you have won'
if printmatches(word,char) == [" "]*len(word):
print "You have ", (2-q), " guesses left"
q+=1
if (q == 3):
print "Game over"
print ' '.join(current)
x is meant to be a list but when I execute the code its type is interpreted as Nonetype, and I get the error message because I am trying to access elements within x and compare its length. How can I fix this problem?
def append(string,chars): ##append list to a string
q = 0
while q < len(string):
if string[q] == " " and chars[q] != " ":
string[q] = chars[q]
q+=1
This does not explicitly return a value, so it implicitly returns None.
(The name string is also a very poor choice here: first off, you expect to be passed a list rather than a string (since as you presumably learned earlier, you cannot modify a string like this), and second it hides the imported string module. But then again, your code does not use the string module, so you shouldn't import it in the first place.)
str = (append(current, printmatches(word,char)))
Now str is None, because it is the result of an append call.
if (convertlist(str) == word):
Now we attempt to convertlist with None, which of course does not work since we wanted a list to be passed in...
def convertlist(x):
q = " "
a = 0
while (a < len(x)):
q+=x[a]
a+=1
return (q)
... and thus here len is invalid applied to None.
The natural way to get information out of a function is to return that information. Create a new string in append, and return it; then you can use the result the way you're trying to use it. As a bonus, since you are creating a new object, you can actually pass in a string again.
Except, I have no idea why this function is called append, since despite the comment, it doesn't seem intended to do any such thing....
Put a check before you perform any operation with x to see the x is not None or any other type than list.
Something like below,
def convertlist(x):
q = " "
a = 0
if isinstance(x, list):
while (a < len(x)):
q+=x[a]
a+=1
return (q)

Python does not accept some numeric inputs

With this code, all I am trying to do is insert a dash between odd numbers and an asterisk between even ones. It does not work correctly with every input. It works with, e.g. 46879, but returns None with 468799, or does not insert * between 4 and 6 with 4546793. Why is it doing that? Thanks
def DashInsertII(num):
num_str = str(num)
flag_even=False
flag_odd=False
new_str = ''
for i in num_str:
n = int(i)
if n % 2 == 0:
flag_even = True
else:
flag_even = False
if n % 2 != 0:
flag_odd = True
else:
flag_odd = False
new_str = new_str + i
ind = num_str.index(i)
if ind < len(num_str) - 1:
m = int(num_str[ind+1])
if flag_even:
if m % 2 == 0:
new_str = new_str + '*'
else:
if m % 2 != 0:
new_str = new_str + '-'
else:
return new_str
print DashInsertII(raw_input())
Your function definition is one of the most overbuilt functions I've seen in a while; the following should do what yours was trying to do, sans the complexity.
def DashInsertII(num):
num_str = str(num)
new_str = ''
for i in num_str:
n = int(i)
if n % 2 == 0:
new_str += i + '*'
else:
new_str += i + '-'
return new_str
print DashInsertII(raw_input())
EDIT: I just re-read the question and saw that I misinterpreted what you want, which is to insert a - between two odd numbers and a * between two even numbers. For that, the best solution I can come up with uses regular expressions.
Second Edit: As per alvits's request, I'm including an explanation of the regex in this.
import re
def DashInsertII(num):
num_str = str(num)
# r'([02468])([02468])' performs capturing matches on two even numbers
# that are next to each other
# r'\1*\2' is a string consisting of the first match ([02468]) followed
# by an asterisk ('*') and the second match ([02468])
# example input: 48 [A representation of what happens inside re.sub()]
# r'([02468])([02468])' <- 48 = r'( \1 : 4 )( \2 : 8 )'
# r'\1*\2' <- {\1 : 4, \2 : 8} = r'4*8'
num_str = re.sub(r'([02468])([02468])',r'\1*\2',num_str)
# This statement is much like the previous, but it matches on odd pairs
# of numbers
num_str = re.sub(r'([13579])([13579])',r'\1-\2',num_str)
return num_str
print DashInsertII(raw_input())
If this is still not what you actually want, please comment on this to let me know.
RevanProdigalKnight's answer is almost right but fails when 3 or more even/odd numbers come together.
The right way to do this with regex would be to use positive lookahead (use ?=).
def insert_right_way(num):
#your code here
num_str = str(num)
num_str = re.sub(r'([13579])(?=[13579])', r'\1-', num_str)
num_str = re.sub(r'([02468])(?=[02468])', r'\1*', num_str)
return num_str
def DashInsertII(num):
num_str = str(num)
num_str = re.sub(r'([02468])([02468])',r'\1*\2',num_str)
num_str = re.sub(r'([13579])([13579])',r'\1-\2',num_str)
return num_str
print insert_right_way(234467776667888)
print DashInsertII(234467776667888)
This would output:
234*4*67-7-76*6*678*8*8 ( what is desired)
234*467-776*6678*88 ( not what we wanted)
If I understand your problem - for 11223344 you need 1-12*23-34*4
def DashInsertII(num):
prev_even = ( int(num[0])%2 == 0 )
result = num[0]
for i in num[1:]:
curr_even = (int(i)%2 == 0)
if prev_even and curr_even:
result += '*'
elif not prev_even and not curr_even:
result += '-'
result += i
prev_even = curr_even
return result
print DashInsertII(raw_input())

Python Convert String Literal to Float

I am working through the book "Introduction to Computation and Programming Using Python" by Dr. Guttag. I am working on the finger exercises for Chapter 3. I am stuck. It is section 3.2, page 25. The exercise is: Let s be a string that contains a sequence of decimal numbers separated by commas, e.g., s = '1.23,2.4,3.123'. Write a program that prints the sume of the numbers in s.
The previous example was:
total = 0
for c in '123456789':
total += int(c)
print total.
I've tried and tried but keep getting various errors. Here's my latest attempt.
total = 0
s = '1.23,2.4,3.123'
print s
float(s)
for c in s:
total += c
print c
print total
print 'The total should be ', 1.23+2.4+3.123
I get ValueError: invalid literal for float(): 1.23,2.4,3.123.
Floating point values cannot have a comma. You are passing 1.23,2.4,3.123 as it is to float function, which is not valid. First split the string based on comma,
s = "1.23,2.4,3.123"
print s.split(",") # ['1.23', '2.4', '3.123']
Then convert each and and every element of that list to float and add them together to get the result. To feel the power of Python, this particular problem can be solved in the following ways.
You can find the total, like this
s = "1.23,2.4,3.123"
total = sum(map(float, s.split(",")))
If the number of elements is going to be too large, you can use a generator expression, like this
total = sum(float(item) for item in s.split(","))
All these versions will produce the same result as
total, s = 0, "1.23,2.4,3.123"
for current_number in s.split(","):
total += float(current_number)
Since you are starting with Python, you could try this simple approach:
Use the split(c) function, where c is a delimiter. With this you will have a list numbers (in the code below). Then you can iterate over each element of that list, casting each number to a float (because elements of numbers are strings) and sum them:
numbers = s.split(',')
sum = 0
for e in numbers:
sum += float(e)
print sum
Output:
6.753
From the book Introduction to Computation and Programming using Python at page 25.
"Let s be a string that contains a sequence of decimal numbers separated by commas, e.g., s
= '1.23,2.4,3.123'. Write a program that prints the sum of the numbers in s."
If we use only what has been taught so far, then this code is one approach:
tmp = ''
num = 0
print('Enter a string of decimal numbers separated by comma:')
s = input('Enter the string: ')
for ch in s:
if ch != ',':
tmp = tmp + ch
elif ch == ',':
num = num + float(tmp)
tmp = ''
# Also include last float number in sum and show result
print('The sum of all numbers is:', num + float(tmp))
total = 0
s = '1.23,2.4,3.123'
for c in s.split(','):
total = total + float(c)
print(total)
Works Like A Charm
Only used what i have learned yet
s = raw_input('Enter a string that contains a sequence of decimal ' +
'numbers separated by commas, e.g. 1.23,2.4,3.123: ')
s = "," + s+ ","
total =0
for i in range(0,len(s)):
if s[i] == ",":
for j in range(1,(len(s)-i)):
if s[i+j] == ","
total = total + float(s[(i+1):(i+j)])
break
print total
This is what I came up with:
s = raw_input('Enter a sequence of decimal numbers separated by commas: ')
aux = ''
total = 0
for c in s:
aux = aux + c
if c == ',':
total = total + float(aux[0:len(aux)-1])
aux = ''
total = total + float(aux) ##Uses last value stored in aux
print 'The sum of the numbers entered is ', total
I think they've revised this textbook since this question was asked (and some of the other's have answered.) I have the second edition of the text and the split example is not on page 25. There's nothing prior to this lesson that shows you how to use split.
I wound up finding a different way of doing it using regular expressions. Here's my code:
# Intro to Python
# Chapter 3.2
# Finger Exercises
# Write a program that totals a sequence of decimal numbers
import re
total = 0 # initialize the running total
for s in re.findall(r'\d+\.\d+','1.23, 2.2, 5.4, 11.32, 18.1,22.1,19.0'):
total = total + float(s)
print(total)
I've never considered myself dense when it comes to learning new things, but I'm having a hard time with (most of) the finger exercises in this book so far.
s = input('Enter a sequence of decimal numbers separated by commas: ')
x = ''
sum = 0.0
for c in s:
if c != ',':
x = x + c
else:
sum = sum + float(x)
x = ''
sum = sum + float(x)
print(sum)
This is using just the ideas already covered in the book at this point. Basically it goes through each character in the original string, s, using string addition to add each one to the next to build a new string, x, until it encounters a comma, at which point it changes what it has as x to a float and adds it to the sum variable, which started at zero. It then resets x back to an empty string and repeats until all the characters in s have been covered
Here's a solution without using split:
s='1.23,2.4,3.123,5.45343'
pos=[0]
total=0
for i in range(0,len(s)):
if s[i]==',':
pos.append(len(s[0:i]))
pos.append(len(s))
for j in range(len(pos)-1):
if j==0:
num=float(s[pos[j]:pos[j+1]])
total=total+num
else:
num=float(s[pos[j]+1:pos[j+1]])
total=total+num
print total
My way works:
s = '1.23, 211.3'
total = 0
for x in s:
for i in x:
if i != ',' and i != ' ' and i != '.':
total = total + int(i)
print total
My answer is here:
s = '1.23,2.4,3.123'
sum = 0
is_int_part = True
n = 0
for c in s:
if c == '.':
is_int_part = False
elif c == ',':
if is_int_part == True:
total += sum
else:
total += sum/10.0**n
sum = 0
is_int_part = True
n = 0
else:
sum *= 10
sum += int(c)
if is_int_part == False:
n += 1
if is_int_part == True:
total += sum
else:
total += sum/10.0**n
print total
I have managed to answer the question with the knowledge gained up until 3.2 the section for loop
s = '1.0, 1.1, 1.2'
print 'List of decimal number'
print s
total = 0.0
for c in s:
if c == ',':
total += float(s[0:(s.index(','))])
d = int(s.index(','))+1
s = s[(d+1) : len(s)]
s = float(s)
total += s
print '1.0 + 1.1 + 1.2 = ', total
This is the answer to the question i feel that the split function is not good for beginner like you and me.
Considering the fact that you might not yet be exposed to more complex functions, simply try these out.
total = 0
for c in "1.23","2.4",3.123":
total += float(c)
print total
My answer:
s = '2.1,2.0'
countI = 0
countF = 0
totalS = 0
for num in s:
if num == ',' or (countF + 1 == len(s)):
totalS += float(s[countI:countF])
if countF < len(s):
countI = countF + 1
countF += 1
print(totalS) # 4.1
This only works if the numbers are floats
Here is my answer. It is similar to the one by user5716300 above, but since I am also a beginner I explicitly created a separate variable s1 for the split string:
s = "1.23,2.4,3.123"
s1 = s.split(",") #this creates a list of strings
count = 0.0
for i in s1:
count = count + float(i)
print(count)
If we are just sticking with the content for that chapter, I came up with this: (though using that sum method mentioned by theFourthEye is also pretty slick):
s = '1.23,3.4,4.5'
result = s.split(',')
result = list(map(float, result))
n = 0
add = 0
for a in result:
add = add + result[n]
n = n + 1
print(add)
I just wanna to post my answer because I am reading this book now.
s = '1.23,2.4,3.123'
ans = 0.0
i = 0
j = 0
for c in s:
if c == ',':
ans += float(s[i:j])
i = j + 1
j += 1
ans += float(s[i:j])
print(str(ans))
Using knowledge from the book:
s = '4.58,2.399,3.1456,7.655,9.343'
total = 0
index = 0
for string in s:
index += 1
if string == ',':
temp = float(s[:index-1])
s = s[index:]
index = 0
total += temp
temp = 0
print(total)
Here I used string slicing, and by slicing the original string every time our 'string' variable is equal to ','. Also using an index variable to keep track of the number that is before the comma. After slicing the string, the number that gets input into tmp is cleared with the comma in front of it, the string becoming another string without that number.
Because of this, the index variable needs to be reset every time this happens.
Here's mine using the exact string in the question and only what has been taught so far.
total = 0
temp_num = ''
for char in '1.23,2.4,3.123':
if char == ',':
total += float(temp_num)
temp_num = ''
else:
temp_num += char
total += float(temp_num) #to catch the last number that has no comma after it
print(total)
I know this isn't covered in the book up to this point but I happened to learn the use of the eval() function on my own prior to getting to this question and used it to solve.
total = 0
s = "1.23,2.4,3.123"
x = eval(s)
y = sum(x)
print(y)
I think this is the easiest way to answer the question. It uses the split command, which is not introduced in the book at this moment but a very useful command.
s = input('Insert string of decimals, e,g, 1.4,5.55,12.651:')
sList = s.split(',') #create a list of these values
print(sList) #to check if list is correctly created
total = 0 #for creating the variable
for each in sList:
total = total + float(each)
print(total)
total =0
s = {1.23,2.4,3.123}
for c in s:
total = total+float(c)
print(total)

Categories