Manipulating list order - python

I am an artist taking a class on how to manipulate code to make poetry. Python was not supposed to be a prerequisite, but I am not getting it! Please help- we are supposed to make a snowball poem.
Here's the code I have so far:
my_string = "you're going home in a Chelsea ambulance"
counter = 0
new_list = my_string.split()
def make_a_snowball (text):
poem = ' '
for i in text:
poem = poem + "\n" + i
print (poem)
make_a_snowball (new_list)
The result is:
you're
going
home
etc..
I'd like it to look like:
you're
you're going
you're going home
etc...
Any suggestions? Help would be appreciated.

You just need to move the print method inside the loop:
my_string = "you're going home in a Chelsea ambulance"
counter = 0
new_list = my_string.split()
print(new_list)
def make_a_snowball(text):
poem = ' '
for word in text:
poem = poem + ' ' + word
print(poem)
make_a_snowball(new_list)

for i in range(len(new_list)):
print(poem.join(new_list[:i]))

If you want to have your whole poem be stored in one long string, here's how you'd do it:
def make_a_snowball(text):
poem_line = ''
full_poem = ''
for word in text:
poem_line += word + ' '
full_poem += poem_line + '\n'
print(full_poem)
return full_poem
This prints exactly what you want, except all at once rather than line-by-line.

The reason the code is printing each item on a new line is because we are inadvertantly adding a newline character between the terms, when we should be adding a space character.
In the following code, if we replace the \n with a " " and shift the print() function inwards so that it prints every time we loop through the items of the list, then this should work just fine.
my_string = "you're going home in a Chelsea ambulance"
counter = 0
new_list = my_string.split()
def make_a_snowball (text):
poem = ' '
for i in text:
poem = poem + " " + i
print (poem)
make_a_snowball (new_list)
This results in:
you're
you're going
you're going home
you're going home in
you're going home in a
you're going home in a Chelsea
you're going home in a Chelsea ambulance
A couple of additional thoughts.
In your code above, a counter is not necessary.
I like my code to be somewhat self descriptive, so I might replace this:
for i in text:
poem = poem + " " + i
print (poem)
with
for word in text:
poem = poem + " " + word
print (poem)

Related

Beginner question about making a program change based on user input

I'm trying to learn to code and decided to give myself a simple task. It's a madlib game (roses are..., ... is blue, etc..). I want to make the program change '... is blue' to '... are blue' based on use input. So if the use inputs 'my head' the program says 'my head is blue' instead of 'my head are blue.'
I've tried to implement this:
if thing in ['my','your']:
print(thing + " is blue")
else:
print (thing + " are blue")
However the programme only reads 'are' when 'my' or 'your' are written on their own. Is there a way to print something based on whether or not a word is present, not if a certain phrase or word is written?
colour = input ("roses are... ")
thing = input(" ... are blue")
love = input("I love ... ")
print("roses are " + colour)
if thing in ['my','your']:
print(thing + " is blue")
else:
print (thing + " are blue")
print("I love " + love)
You can check if a sub-string is in your list by doing:
if any(word in thing for word in ['my', 'your'])
pretty self explanatory:
it's a for loop that just returns true or false. it basically looks at your variable thing which is storing a string, checks if it's also within your list
So full code:
colour = input ("roses are... ")
thing = input(" ... are blue ")
love = input("I love ... ")
print("roses are " + colour)
if any(word in thing for word in ['my', 'your']):
print(thing + " is blue")
else:
print (thing + " are blue")
print("I love " + love)

Python - Removing paragraph breaks in input

So I have written a program (however ugly) that counts the number of words and the instances of each unique word in a given input.
My problem is that I want to use it for song lyrics, but most lyric sets come with multiple paragraph breaks.
My question is: how can I take a user input of lyrics with paragraph breaks and reduce the input down to a single string?
This is my code so far:
Song = {}
lines = []
while True:
line = input("")
if line:
lines.append(line)
else:
break
string = '\n'.join(lines)
def string_cleaner(string):
string = string.lower()
newString = ''
validLetters = " abcdefghijklmnopqrstuvwxyz"
newString = ''.join([char for char in string if char in validLetters])
return newString
def song_splitter(string):
string = string_cleaner(string)
words = string.split()
for word in words:
if word in Song:
Song[word] += 1
else:
Song[word] = 1
Expected input:
Well, my heart went "boom"
When I crossed that room
And I held her hand in mine
Whoah, we danced through the night
And we held each other tight
And before too long I fell in love with her
Now I'll never dance with another
(Whooh)
Since I saw her standing there
Oh since I saw her standing there
Oh since I saw her standing there
Desired output:
This song has 328 words.
39 of which are unique.
This song is 11% unique words.
('i', 6)
('her', 4)
('standing', 3)
.... etc
The following example code extracts all the words (English alphabet only) from every line and process them (counts the number of words, and retrieve instances of each unique word).
import re
MESSAGE = 'Please input a new line: '
TEST_LINE = '''
Well, my heart went "boom"
When I crossed that room
And I held her hand in mine
Whoah, we danced through the night
And we held each other tight
And before too long I fell in love with her
Now I'll never dance with another
(Whooh)
Since I saw her standing there
Oh since I saw her standing there well well
Oh since I saw her standing there
'''
prog = re.compile(r'\w+')
class UniqueWordCounter():
def __init__(self):
self.data = {}
def add(self, word):
if word:
count = self.data.get(word)
if count:
count += 1
else:
count = 1
self.data[word] = count
# instances of each unique word
set_of_words = UniqueWordCounter()
# counts the number of words
count_of_words = 0
def handle_line(line):
line = line.lower()
words = map(lambda mo: mo.group(0), prog.finditer(line))
for word in words:
global count_of_words
count_of_words += 1
set_of_words.add(word)
def run():
line = input(MESSAGE)
if not line:
line = TEST_LINE
while line:
'''
Loop continues as long as `line` is not empty
'''
handle_line(line)
line = input(MESSAGE)
count_of_unique_words = len(set_of_words.data.keys())
unique_percentage = count_of_unique_words / count_of_words
print('-------------------------')
print('This song has {} words.'.format(count_of_words))
print('{} of which are unique.'.format(count_of_unique_words))
print('This song is {:.2%} unique words.'.format(unique_percentage))
items = sorted(set_of_words.data.items(), key = lambda tup: tup[1], reverse=True)
items = ["('{}', {})".format(k, v) for k, v in items]
print('\n'.join(items[:3]))
print('...')
run()
If you want to handle lyrics in other languages, you should check out this link.

Putting quotation marks inside a string

def add_div(filename, caption):
test = str(filename)
return ('<div><img src=' + test + '><br><p>' + caption + '</p></div>')
def add_body(image_dict, s, order = None):
'''(dict of {str:list of str}, str, list) -> str
If the third parameter is passed, then the filenames
included in the body should only be those in the list and should be added
in the same order as they are listed in the list. '''
new = ''
s = '<html><head></head>'
while order is None:
for (key, value) in image_dict.items():
new += add_div(str(key), str(value[2]))
return (s + '<body><div id="slideshow">' + new + '</body>'+ '</html>')
The output of add_body function is:
how do I get quotation marks around the word images/skater.jpg ?
this is what the file looks like
You have two separate options:
1) Use double quotes
print("Hey that's pretty cool!")
2) Escape the single quotation mark
print('Hey that\'s pretty cool!')
You can include the quotation marks in the string that you are concatenating like this :
def add_div(filename, caption):
test = str(filename)
return ('<div><img src="' + test + '"><br><p>' + caption + '</p></div>')
Use one type of quotation for the string definition and the other for the included quotes:
>>> "bob said: 'hello'"
"bob said: 'hello'"
>>> "I said 'yo bob, how u doing?' in reply"
"I said 'yo bob, how u doing?' in reply"
So to fix your problem, just change the return statement in the first function to:
return ('<div><img src="' + test + '><br><p>'" + caption + '</p></div>')
Note that as a final thing, the parenthesis in the return statement aren't required as return is a not a function or method.
Good answers, but another method is to escape the single or double quotation mark with \
Example:
# this is the same as
# s = "'"
s = '\''
print(s)
#this is the same as
# s = '"'
s = "\""
print(s)

Python,join() function, adding space between words

I need to write a function that takes two strings (text and word) and returns the text with the chosen word replaced with asterisks (the number of asterisks should correspond to the number of letters in the censored word.).
For example:
if text="hey hey hey" and word="hey" the returned text should be:
'*** *** ***'
Here is my code:
def censor(text,word):
text = text.split(" ")
asterisks=[]
text_with_asterisks=[]
for item in text:
if item not in word:
text_with_asterisks.append(item)
else:
asterisks=[]
for letter in word:
asterisks.append("*")
text_with_asterisks.append(' '.join(asterisks))
return (" ".join(text_with_asterisks))
The code works but it returns:
*********
and not
*** *** ***.
Once I use the line:
return ("_".join(text_with_asterisks))
instead I get:
'***_***_***'
I don't understand why the " " is ignored and how can I add a space between the words.
Thanks!
You have an extra space when you join your asterisks:
def censor(text, word):
text = text.split(" ")
asterisks=[]
text_with_asterisks=[]
for item in text:
if item not in word:
text_with_asterisks.append(item)
else:
asterisks=[]
for letter in word:
asterisks.append("*")
text_with_asterisks.append(''.join(asterisks)) #here's the culprit
return (" ".join(text_with_asterisks))
censor("hey hey hey", "hey") outputs what you want ('*** *** ***')
I just pointed out your mistake, but surely there's a more elegant and efficient way to do what you want.
Here is the simplest solution
text.replace(word, "*" * len(word))
Regex method of doing this -
import re
def censor(text,word):
return re.sub(r'\b(?i){0}\b'.format(re.escape(word)),'*' * len(word), text)
Example/Demo -
>>> censor('hey hey they hey','hey')
'*** *** they ***'
>>> censor('hey hey they Hey','hey')
'*** *** they ***'
You have spaces between every * in the word, and additional spaces between the words, so I think, you only want spaces between words:
def censor(text, word):
return ' '.join('*'*len(word) if word==item else item for item in text.split())
Simple solution,
>>> text = "hey hey hey"
>>> "***".join(text.split("hey"))
'*** *** ***'
Or
>>> text = "hey hey they Hey','hey"
>>> " ".join([ '***' if word.lower() == 'hey' else word
... for word in text.replace("'","").replace(","," ").split()])
'*** *** they *** ***'
As text_with_asterisks.append(' '.join(asterisks)) does, each character is joined by " ", and then " ".join(text_with_asterisks) also makes each words joined by " ", thus the output is: * * * * * * * * *, where there is a space between each star.
def censor(text, censor_w):
splitted_text = text.split(" ")
asterics = "*" * len(censor_w)
result = []
for word in splitted_text:
if word == censor:
result.append(asterics)
else:
result.append(word)
return " ".join(result)

string.replace('the','') is leaving white space

I have a string that is the name of an artist that I get from the MP3 ID3 tag
sArtist = "The Beatles"
What I want is to change it to
sArtist = "Beatles, the"
I have running into 2 different problems. My first problem is that I seem to be trading 'The' for ''.
if sArtist.lower().find('the') == 0:
sArtist = sArtist.lower().replace('the','')
sArtist = sArtist + ", the"
My second problem is that since I have to check for both 'The' and 'the' I use sArtist.lower(). However this changes my result from " Beatles, the" to " beatles, the". To solve that problem I just removed the .lower and added a second line of code to explicitly look for both cases.
if sArtist.lower().find('the') == 0:
sArtist = sArtist.replace('the','')
sArtist = sArtist.replace('The','')
sArtist = sArtist + ", the"
So the problem I really need to solve is why am I replacing 'the' with <SPACE> instead of <NULL>. But if somebody has a better way to do this I would be glad for the education :)
Using
sArtist.replace('The','')
is dangerous. What happens if the artist's name is Theodore?
Perhaps use regex instead:
In [11]: import re
In [13]: re.sub(r'^(?i)(a|an|the) (.*)',r'\2, \1','The Beatles')
Out[13]: 'Beatles, The'
One way:
>>> def reformat(artist,beg):
... if artist.startswith(beg):
... artist = artist[len(beg):] + ', ' + beg.strip()
... return artist
...
>>> reformat('The Beatles','The ')
'Beatles, The'
>>> reformat('An Officer and a Gentleman','An ')
'Officer and a Gentleman, An'
>>>

Categories

Resources