I'm an amateur learner and would like to have more ideas on these.
This is what I want,
paper_doll('Hello') --> 'HHHeeellllllooo'
Here is my code and it doesn't work, but I have no ideas why.
def paper_doll(text):
for i in range(0,len(text)-1):
return ''.join(text[i]*3)
paper_doll('Hello')
The result became 'HHH'.
Understood the following would work,
def paper_doll(text):
result = ''
for char in text:
result += char * 3
return result
But why .join doesn't work in this case?
def paper_doll(text):
ret=[]
for i in text:
ret.append(i*3)
return ''.join(ret)
Should work. This returns each 3 letter iteration, joined together.
First, your code does not work because the return statement exits from the function on the first iteration loop, so it triples only the first letter, and that's all:
def paper_doll(text):
for i in range(0,len(text)-1): # on 1st iteration: i = 0
return ''.join(text[i]*3) # on 1st iteration: text[i] equals 'H' ==> 'HHH' is returned
Secondly, here is a solution using comprehension, which is well adapted in your case to iterate over each character of a string:
def paper_doll(text):
return ''.join(i*3 for i in text)
print(paper_doll('Hello')) # HHHeeellllllooo
Your initial problem was the return in your iteration. This short circuits the rest of the loop... as noted in other answers.
python can iterate through a string for you. Another answer using list comprehension:
def paper_doll(text):
return ''.join([char*3 for char in text])
Add to a string during the loop, return the result:
def paper_doll(text):
s = ''
for i in range(0,len(text)):
s += ''.join(text[i]*3)
return s
print(paper_doll('Hello'))
Output:
HHHeeellllllooo
(I also removed the -1 in range so you get three "o"s)
Related
I'm trying to write a function to return the longest common prefix from a series of strings. Using a debugger, saw that my function reaches the longest common prefix correctly, but then when it reaches the statement to return, it begins reverting to earlier stages of the algorithm.
For test case strs = ["flower","flow","flight"]
The output variable holds the following values:-
f > fl > f
instead of returning fl.
Any help would be appreciated, because I don't really know how to Google for this one. Thank you.
class Solution(object):
def longestCommonPrefix(self, strs, output = ''):
#return true if all chars in string are the same
def same(s):
return s == len(s) * s[0]
#return new list of strings with first char removed from each string
def slicer(list_, list_2 = []):
for string in list_:
string1 = string[1:]
list_2.append(string1)
return list_2
#return string containing first char from each string
def puller(list_):
s = ''
for string in list_:
s += string[0]
return s
#pull first character from each string
s = puller(strs)
#if they are the same
#add one char to output
#run again on sliced list
if same(s):
output += s[0]
self.longestCommonPrefix(slicer(strs), output)
return output
This can be handled with os.path.commonprefix.
>>> import os
>>> strs = ["flower","flow","flight"]
>>> os.path.commonprefix(strs)
'fl'
It doesn't "revert". longestCommonPrefix potentially calls itself - what you're seeing is simply the call-stack unwinding, and flow of execution is returning to the calling code (the line that invoked the call to longestCommonPrefix from which you are returning).
That being said, there's really no need to implement a recursive solution in the first place. I would suggest something like:
def get_common_prefix(strings):
def get_next_prefix_char():
for chars in zip(*strings):
if len(set(chars)) != 1:
break
yield chars[0]
return "".join(get_next_prefix_char())
print(get_common_prefix(["hello", "hey"]))
You are looking at the behavior...the final result...of recursive calls to your method. However, the recursive calls don't do anything to affect the result of the initial execution of the method. If we look at the few lines that matter at the end of your method:
if same(s):
output += s[0]
self.longestCommonPrefix(slicer(strs), output)
return output
The problem here is that since output is immutable, its value won't be changed by calling longestCommonPrefix recursively. So from the standpoint of the outermost call to longestCommonPrefix, the result it will return is determined only by if same(s) is true or false. If it is true it will return s[0], otherwise it will return ''.
The easiest way to fix this behavior and have your recursive call affect the result of the prior call to the method would be to have its return value become the value of output, like this:
if same(s):
output += s[0]
output = self.longestCommonPrefix(slicer(strs), output)
return output
This is a common code pattern when using recursion. Just this change does seem to give you the result you expect! I haven't analyzed your whole algorithm, so I don't know if it becomes "correct" with just this change.
Can you try this? I
class Solution(object):
def longestCommonPrefix(self, strs, output = ''):
#return true if all chars in string are the same
def same(s):
return s == len(s) * s[0]
#return new list of strings with first char removed from each string
def slicer(list_, list_2 = []):
for string in list_:
string1 = string[1:]
list_2.append(string1)
return list_2
#return string containing first char from each string
def puller(list_):
s = ''
for string in list_:
s += string[0]
return s
#pull first character from each string
s = puller(strs)
# Can you Try this revision?
# I think the problem is that your new version of output is being lost when the fourth called function returns to the third and the third returns to the second, etc...
# You need to calculate a new output value before you call recursively, that is true, but you also need a way to 'store' that output when that recursively called function 'returns'. Right now it disappears, I believe.
if same(s):
output += s[0]
output = self.longestCommonPrefix(slicer(strs), output)
return output
I'm learning data and algorithm, here is the question I met
Question:Write a short recursive Python function that takes a character string s and
outputs its reverse. For example, the reverse of pots&pans would be
snap&stop .
a="pots&pans"
b=a.split("&")
c=[]
c=list(b)
def reverse(data,leng,leng2,index,count):
rev=(leng-1)-count
if count<leng/2:
temp=data[index][count]
data[index][count]=data[index][rev]
data[index][rev]=temp
if index==leng2:
print(data[index-1]+"&"+data[index])
return reverse(data,leng,leng2,index+1,count)
reverse(c,4,2,0,0)
I got an error here
TypeError: 'str' object does not support item assignment
My initial thought is that str is immutable. So it is better to store it in an list and do the operations. However, it met some problem when I trying to assign str to a list. Any solution to this?
Try this:
a="pots&pans"
b=a.split("&")
def reverse(word):
if not word:
return ""
return reverse(word[1:]) + word[0]
result = reverse(b[1]) + "&" + reverse(b[0])
print(result)
If you want one recursion to also reverse all the words position:
a="pots&pans&hello&hi"
b=a.split("&")
def reverse(lis):
if not lis:
return ""
if type(lis) == list and len(lis) == 1:
return reverse(lis[0])
if type(lis) == str:
return reverse(lis[1:]) + lis[0]
if type(lis) == list:
return reverse(lis[1:]) + "&" + reverse(lis[0])
print(reverse(b))
One recursive approach would be to append the first character to the reverse of the rest of the string:
def rev(s): return rev(s[1:])+s[0] if s else ""
output:
rev("pots&pans")
'snap&stop'
You could also do this without indexing using parameter unpacking:
def rev(first,*rest): return rev(*rest)+first if rest else first
rev(*"pots&pans")
'snap&stop'
Try this:
a="pots&pans"
def reverse(a_string):
`letter_list = list(a_string)`
`letter_list.reverse()`
`return(''.join(letter_list))`
print(reverse(a))
While I tried to execute the following code, I faced some problem in loop iterations and couldn't figure out what's the problem might be.
def string_splosion(s):
"""Takes a non-empty string s like "Code" and
returns a string like "CCoCodCode"
"""
for i in range(len(s)):
return s[i] * (i+1)
print(string_splosion('Code'))
you leave the function after the first return.
I think this would be the right solution
def string_splosion(s):
result = ''
for i in range(len(s)):
result += s[:i]
result += s
return result
if you have return inside in a loop the loop is raning only for one time.
def string_splosion(s):
"""Takes a non-empty string s like "Code" and
returns a string like "CCoCodCode"
"""
a='' ## empty String
for i in range(len(s)):
a += s[0:i] +s[i] ## this is beter way to do this "CCoCodCode"
return a ## out of the "for" loop
print(string_splosion('Code'))
Try something like:
def string_splosion(s):
return ''.join(s[:i+1] for i in range(len(s)))
print(string_splosion('Code'))
I am a beginning in Python.
I have a function that checks if it is a vowel.
def vowel(x):
if(x=='a' or x=='e' or x=='i' or x=='o' or x=='u'):
return True;
else:
return False;
And a function that tries to convert the string to a robber's language by using the vowel function above. (The algorithm for conversion is to double every consonant and place an "o" in between).
def robber(text):
s=""
for i,c in enumerate(text):
if vowel(c)==False:
s=s.join([c,'o',c])
return s;
When I try to run it by passing robber("asdf") into the function, I get a blank line and "Process finished with exit code 0"
I suspect that there might be multiple errors, but the program is syntactically correct. Could you help me with this?
You should append to s instead of assigning and also appending the c in case it is no vowel:
def robber(text):
s=""
for i,c in enumerate(text):
if vowel(c)==False:
s += ''.join([c,'o',c])
else:
s += c
return s
Furthermore some additional remarks:
it is more Pythonic to use not instead of == False;
you do not need to use enumerate(..) since i is never used;
you do not need to return True and return False if the test succeeds/fails, simply return the condition; and
you can rewrite both the vowel(..) and robber(..) function more elegantly.
So putting it together:
def vowel(x):
return x.lower() in ('a','e','i','o','u')
and:
def robber(text):
return ''.join([c if vowel(c) else ''.join((c,'o',c)) for c in text])
If you want to avoid all those append/overwrite errors (and get a much better performance/avoid string concatenation), better start writing those using list comprehension:
text = "asdf"
new_text = "".join([c if c in "aeiou" else "{0}o{0}".format(c) for c in text])
print(new_text)
result:
asosdodfof
the new text is a joined list (creates a string) of a list comprehension built using a ternary expression: leave the letter alone if vowel, else create the pattern.
Firstly, your problem
On the line s=s.join([c,'o',c]), you are actually replacing the contents of s every time. I think what you do want to do is to append it to s, so I would use s += "".join([c, 'o', c])
Also the use of join is wrong - the string before the join comes between every two elements in the given list, not before the first.
So, as I said, the correct form to do that should be:
s += "".join([c, 'o', c])
Disclaimer : Not tested.
Code readability
As you stated that you are a beginner, let me give you some tips about your coding style (Python's coding style is very unique).
1
Instead of doing x=='a' or x=='e' or x=='i' or x=='o' or x=='u', you do:
`if x in 'aeiou':`
Much more understandable and reads better.
2
Doing:
if ...:
return True
else
Return False
Is very clumsy. Try:
return ...
And in your case:
return x in 'aeiuo'
The condition is already a boolean value (True or False) - no need to reevaluate it ;)
The question is :
Given a string, return a string where for every char in the original, there are two chars.
This is my attempt:
def double_char(str):
n = 0
for x in range(0, len(str)):
return 2*str[n]
n = n+1
When I run it, it only returns 2 versions of the first letter and doesn't loop properly. So for double_char(Hello) it just returns HH.
What is going wrong? Thanks in advance for any help, sorry for the really beginner question.
The return is causing your function to return in the first iteration so it just returns 2 of the first letter.
What you may have intended to write was something like
def double_char(s):
n = 0
r = ''
for x in range(0, len(s)):
r += 2*s[n]
n = n+1
return r
Building a string incrementally that is just 2 of each character.
A neater refactor of that function (without duplicating the other answer by using a comprehension) is
def double_char(s):
r = ''
for c in s:
r += 2*c
return r
You also should not use str as a variable name. It is a built in type and you are hiding that by defining a variable called str.
return returns control to the caller once reached, thus exiting your for loop prematurely.
Here's a simpler way to do that with str.join:
def double_char(s):
return ''.join(i*2 for i in s)
>>> s = 'Hello'
>>> double_char(s)
'HHeelllloo'
Do not use str as name to avoid shadowing the builtin str function.
Here is a different way to solving the question.
def double_char(str):
new_str = ""
for i in range(len(str)):
new_str += (str[i]*2)
return new_str
double_char('Hello')
'HHeelllloo'
def double_char(str):
string = ''
for i in range(len(str)):
string += str[i] * 2
i += 1
return string