Adding tabs (\t) in the appropriate spot to my code - python

I created a code that requires tabs to put in it, but I cannot seem to figure out how to add the tabs appropriately. See below for my code and the doc string for what it should return, and what it returns instead. Maybe I should rethink my whole approach?
def display_game(guesses, clues):
'''(list, list) -> str
Given two lists of single character strings, return a string
that displays the current state of the game
>>>display_game([['Y', 'P', 'G', 'G'], ['O', 'O', 'G', 'G']], [['b', 'b'], ['b','b', 'b', 'b']])
'Guess\tClues\n****************\nY P G G\tb b\nO O G G\tb b b b\n'
'''
display = 'Guess\tClues\n****************\n'
for i in range(len(guesses)):
for letter in guesses[i]:
display += letter + ' '
for letter in clues[i]:
display += letter + ' '
display += '\n'
return display
When I use it (using the doc string example), I get:
display_game([['Y', 'P', 'G', 'G'], ['O', 'O', 'G', 'G']], [['b', 'b'], ['b','b', 'b', 'b']])
'Guess\tClues\n****************\nY P G G b b \nO O G G b b b b \n'
Any attempt to put \t in the code has it turning out wrong (ex: with \t between each string instead of where they should be as per the doc string). Is anyone able to suggest how I may change things around? Thanks!

Your code does not add a tab in between the guess and the clue. You could simply add
display += '\t'
in between the first and second nested for loops, however, you then need to ensure that a trailing space is not added at the end of the first loop.
str.join() is a better way to handle this as it only adds delimiter strings in between the items of a sequence:
>>> ' '.join(['a', 'b', 'c'])
'a b c'
Notice that there is no trailing space character in the above. Applying that to your function:
def display_game(guesses, clues):
display = 'Guess\tClues\n****************\n'
for guess, clue in zip(guesses, clues):
display += '{}\t{}\n'.format(' '.join(guess), ' '.join(clue))
return display
zip() is also used here to pair each guess and clue. Then it's simply a matter of using str.join() on the guess and clue, and building the string with the tab in the required place.
>>> assert(display_game([['Y', 'P', 'G', 'G'], ['O', 'O', 'G', 'G']], [['b', 'b'], ['b','b', 'b', 'b']]) == 'Guess\tClues\n****************\nY P G G\tb b\nO O G G\tb b b b\n')

You can just add it in between the for loops:
for i in range(len(guesses)):
for letter in guesses[i]:
display += letter + ' '
display += '\t' # right here
for letter in clues[i]:
display += letter + ' '
display += '\n'
return display

This worked for me. Just add the tab between those two for loops of guesses and clues.
def display_game(guesses, clues):
display = 'Guess \t Clues \n **************** \n'
for i in range(len(guesses)):
for letter in guesses[i]:
display += letter + ' '
display += '\t'
for letter in clues[i]:
display += letter + ' '
display += '\n'
return display
print(display_game('at', 'yk'))
This gave output:
Guess Clues
****************
a y
t k

Related

why does conditional list.insert() in python add additional items to list [duplicate]

This question already has answers here:
Python: Adding element to list while iterating
(12 answers)
Closed 9 months ago.
h = list('camelCase')
for i in range(len(h)):
if h[i].isupper():
h.insert(i,' ')
print(h) returns: ['c', 'a', 'm', 'e', 'l', ' ', ' ', ' ', ' ', 'C', 'a', 's', 'e']
I expected: ['c', 'a', 'm', 'e', 'l', ' ', 'C', 'a', 's', 'e']
since there's only one uppercase letter "C"
Changing the list you are iterating on isn't always a good idea but if you want to apply it on the same list you can use while loop:
h = list('camelCase')
i = 0
while (i < len(h)):
if h[i].isupper():
h.insert(i,' ')
i += 1
i += 1
You need to copy the original list first.
The reason the space letters are added repeatedly is that " " is added in the list h so "C" is taken continuously until the index i reaches the original length of h.
h = list('camelCase')
a = h.copy()
for i in range(len(h)):
if h[i].isupper():
a.insert(i,' ')
print(a)
Your issue is that you are iterating over the range of the list, and when you find a capital letter, you insert the space in that position, which means that the capital letter will be move to the next position, therefore once you find a capital letter it will simply add a space and check that letter again.
Your h[i] right now would print the following:
`c`, `a`, `m`, `e`, `l`, `C`, `C`, `C`, `C`
My recommendation would be to not modify the original list, but do it in a separate one:
h = list('camelCase')
new_text = ''
for i in range(len(h)):
if h[i].isupper():
new_text += ' '
new_text += h[i]

i want to remove empty string from a list

can someone please tell me why I cant remove the empty string by using following code?
numlist = list()
tim = "s x s f f f"
timo = tim.strip()
for line in timo:
numlist.append(line)
list(filter(None, numlist))
print(numlist)
output: ['s', ' ', 'x', ' ', 's', ' ', 'f', ' ', 'f', ' ', 'f']
desired output: ['s', 'x', 's', 'f', 'f', 'f']
Use split not strip. strip is for removing leading and trailing characters
In [35]: tim = "s x s f f f"
In [36]: tim.split()
Out[36]: ['s', 'x', 's', 'f', 'f', 'f']
You forgot to assign the result of the filtering back to numlist, so it made the new list and discarded it. Just make the line:
numlist = list(filter(None, numlist))
That said, it wouldn't have done what you wanted, because a string of a single space is still truthy. If you want to exclude spaces as truthy, a simple tweak would be:
numlist = list(filter(str.strip, numlist))
Or simplifying further (but with different behavior if the input isn't always single characters with space separation), replace the entirety of your code with just:
tim = "s x s f f f"
numlist = tim.split()
print(numlist)
as no-arg split will split on whitespace, remove leading and trailing whitespace, and return the list of non-whitespace components as a single efficient action.

How do I return a value within a loop within a function?

I have this almost figured it out but there is one thing. Basically I want to return a string without a vowel (a common challenge I guess). This is similar to other challenges on CodeWars I have done, still uncompleted due to this. I have a for loop within a function. I call the function to return value.
For some reason, I'm returning empty or rather "None", yet I get the result I wanted by printing. On the same line and indenting.
This is for a Codewar challenge, so I need to return values instead of , printing, logging (I know). I asked for a friend, hours of researching but nothing could help me.
def disemvowel(string):
#aeiou
vowel = ['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']
aList = list(string) #'' to [...]
for x in aList:
for y in vowel:
if x == y:
#print(x)
aList.remove(x)
print(''.join(aList)) # "Ths wbst s fr lsrs LL!"
return(''.join(aList)) # Nothing shows up here...
I expect the output of "Ths wbst s fr lsrs LL!" by returning but I get None.
https://www.codewars.com/kata/52fba66badcd10859f00097e/train/python
Source ^
To remove vowels from strings, the quickest way would be to use str.replace.
def remove_vowels(msg):
vowels = ['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']
for vowel in vowels:
msg = msg.replace(vowel, '')
return msg
Use a list comprehension:
def remove_vowels(msg):
return ''.join(c for c in msg if c.lower() not in {'a', 'e', 'i', 'o', 'u'})
Examples:
>>> remove_vowels("Lorem ipsum dolor sit amet.")
'Lrm psm dlr st mt.'
>> remove_vowels("This is it")
'Ths s t'
>>> remove_vowels("This website is for losers LOL!")
'Ths wbst s fr lsrs LL!'

Output in lists turns everything into individual strings

I'm trying to insert something into a new list and get an output that says:
vehicle is 7 letters
fl=['vehicle','person']
Textfl=[]
Textfl.extend(str(fl[0])+ "is " +str(len(fl[0]))+ "letters")
print(Textfl)
Ends up returning:
['v', 'e', 'h', 'i', 'c', 'l', 'e', 'i', 's' ' ', '7', 'l', 'e', 't', 't', 'e', 'r', 's']
Wanted output: vehicle is 7 letters
You could use string formatting for a cleaner solution:
For Python 3.6+
s = 'vehicle'
output = f'{s} is {len(s)} letters'
# 'vehicle is 7 letters'
For older versions use:
output = '{} is {} letters'.format(s,len(s))
# 'vehicle is 7 letters'
The problem with your solution is that you are making the result a list, when you're expected output is actually a string. The following would be enough:
str(fl[0]) + " is " + str(len(fl[0]))+ " letters"
# 'vehicle is 7 letters'
fl = ['vehicle', 'person']
Textfl = str()
Textfl = fl[0]+ " is " + str(len(fl[0])) + " letters"
print(Textfl)
Try to use the Textfl object as string.
If you want a list in output containing an element vehicle is 7 letters then you can do something like this:
fl=['vehicle','person']
Textfl=[]
Textfl.append(str(fl[0])+" "+"is " +str(len(fl[0]))+" "+"letters")
print(Textfl)
output
['vehicle is 7 letters']

Can it be done with recursion?

im trying to make my program run as i want it to, but i have some trouble with that, hope someone can help with that.
I wrote a program that takes a list of chars and assembles them to create words. Word ends when there is a " " in list. So it looks like that:
inp = ['r','e', 'e', 'l', ' ', 'y', 'e', 'l', 'l', 'o', 'w', ' ', 'g', 'e', 'l',' ', 'p','e','e','k']
outp = ['reel', 'yellow', 'gel', 'peek']
The code looks like this:
def mer(inp, outp=[]):
tail = 0
for item in inp:
if item == (" "):
inp[:tail] = ["".join(inp[:tail])]
outp.append(inp.pop(0))
inp.remove(item)
if ((" ") in inp) == False:
inp[:] = ["".join(inp[:])]
outp.append(inp.pop(0))
tail +=1
And now to get the output (in the case with the input like on top) i need to call mer two times. Is there a way to make it run untill the input list is empty, or maybe use a recursion?
It's just a programming exercise, so it can be probably all done better, but for now thats all i need.
You can use join and split:
>>> ''.join(inp).split()
['reel', 'yellow', 'gel', 'peek']
# recursion
from itertools import takewhile
def fun(x):
if not x:
return
y = list(takewhile(lambda i:i!=' ', x))
yield ''.join(y)
for z in fun(x[len(y)+1:]):
yield z
list(fun(['r','e', 'e', 'l', ' ', 'y', 'e', 'l', 'l', 'o', 'w', ' ', 'g', 'e', 'l',' ', 'p','e','e','k']))
I know you asked for a method using recursion, but the most pythonic method in this case is to join the characters together, then split them.
outp = "".join(input).split(" ")
And now to get the output (in the case with the input like on top) i need to call mer two times.
The problem with your algorithm is that you are modifying the list while you iterate over it. This is a naughty and unsafe thing to be doing.
After "reel" is put into outp, inp is ['y', 'e', 'l', 'l', 'o', 'w', ' ', 'g', 'e', 'l',' ', 'p','e','e','k']. But the next character that will be examined by the loop is - at least in the CPython implementation - not the 'y' of 'yellow', but the 'w'. This is because the iteration internally stores an index (which happens to be in sync with the tail variable that you update manually) and uses that to grab elements. The listiterator created behind the scenes to implement the for-loop is utterly unaware of changes to the list that it's iterating over, and thus can't adjust to keep the "same position" (and who knows what you really mean by that, anyway?).
You can see this for yourself if you add a couple of "trace" print statements to the code to show the state of the variables at various points.
Anyway, since the iterator is at the 'w' at this point, it will find the space next and extract 'yellow' just fine; but next it will move to the 'k' of "peek", missing the space after 'gel', and it won't run any of the code in your second if-case, either, because the space between 'gel' and 'peek' is still in the buffer (you didn't really think clearly enough about the real end condition).
If you really, really want to do everything the hard way instead of just writing ''.join(inp).split(' '), you could fix the problem by tracking a beginning-of-word and end-of-word index, slicing out sublists, joining them and putting the resulting words into the output, and leaving the input alone. While we're at it:
functions should use the return value to return data; passing in an outp parameter is silly - let's just return a list of words.
We can use the built-in enumerate function to get indices that match up with the list elements as we iterate.
I have no idea what "mer" means.
You use way too many parentheses, and comparing to boolean literals (True and False) is poor style.
So, the corrected code using the original algorithm:
def words_from(chars):
begin = 0 # index of beginning of current word
result = [] # where we store the output
for i, char in enumerate(chars):
if char == ' ':
result.append(''.join(chars[begin:i]))
begin = i + 1
# At the end, make one more word from the chars after the last space.
result.append(''.join(chars[begin:]))
return result
You should definitely use join and split for this, but since the question specifically asks for a recursive solution, here is an answer that uses one.
This is meant as an exercise in recursion only, this code should not be used.
def join_split(inp, outp=None):
if not inp:
return outp
if inp[0] == ' ':
return join_split(inp[1:], (outp or ['']) + [''])
if outp is None:
return join_split(inp[1:], [inp[0]])
outp[-1] += inp[0]
return join_split(inp[1:], outp)
>>> join_split(['r','e', 'e', 'l', ' ', 'y', 'e', 'l', 'l', 'o', 'w', ' ', 'g', 'e', 'l',' ', 'p','e','e','k'])
['reel', 'yellow', 'gel', 'peek']

Categories

Resources