Eliminating last element in array - python

So I am working on a small hangman text based game.
The problem I am currently dealing with is calling random words from my text file. Each word has one additional character for a new line (\n).
For instance, running through my function that separates a string's letters into individual elements I get something to the effect of:
from text file: guess
answer = arrange_word(guess)
>>>>> ['g', 'u', 'e', 's', 's', '\n']
however, when joining the array back together the following is shown:
print ''.join(arrange_word)
>>>>> guess
as you can see, it is a bit difficult to guess an element that does not show up.
For clarity here is my function for arrange_word:
def arrange_word(word):
##########
# This collects the mystery word and breaks it into an array of
# individual letters.
##########
word_length = len(word)
break_up = ["" for x in range(word_length)]
for i in range(0, word_length):
break_up[i] = word[i]
return break_up
What I am stuck on is that when trying to guess letters, the \n is impossible to guess. The win condition of my game is based on the guess being identical to the answer word. However the \n keeps that from working because they are of different length.
These answer arrays are of different length as well, since I am just pulling random lines from a text file of ~1000 words. After hours of searching I cannot seem to find out how to drop the last element of an array.

For this line here:
word_length = len(word)
Before you take the length, what you can do is this first:
word = word.strip()
Explanation:
strip removes leading and trailing whitespace.
>>> s = "bob\n"
>>> s
'bob\n'
>>> s.strip()
'bob'
With all this in mind, you don't need the rest of this code anymore:
word_length = len(word)
break_up = ["" for x in range(word_length)]
for i in range(0, word_length):
break_up[i] = word[i]
Applying the strip will give you your word without the whitespace character, then all you want to do after this to have a list of characters, is simply:
>>> s = "bob"
>>> list(s)
['b', 'o', 'b']
So your method can now simply be:
def arrange_word(word):
return list(word.strip())
Demo:
arrange_word("guess")
Output:
['g', 'u', 'e', 's', 's']

All these answers are fine for specifically stripping whitespace characters from a string, but more generally, Python lists implement standard stack/queue operations, and you can make your word into a list just by calling the list() constructor without needing to write your own function:
In [38]: letters = list('guess\n')
letters.pop()
letters
Out[38]: ['g', 'u', 'e', 's', 's']

Use List slicing
arr = [1,2,3,4]
print(arr[:-1:])
Array slicing syntax is [startindex:endindex:offset(2, means each 2 element)] So in your case you could. Which mean start at the begging of the list, to the last element -1 for every 1 element in the list.
return break_up[:-1:]

you can access last element by -1 index like:
guess[-1]
and you can delte it by:
del guess[-1]

Just strip the word:
word = 'guess\n'
word = word.strip() ## 'guess' without new line character, or spaces

Maybe first line of your arrange_word function should be
word = word.strip()
to remove all leading/trailing whitespace characters.

Related

List modification doesn't change list

I'm trying to reverse a string, so I converted the string into a list and was trying to send the last element to the front, 2nd to last element to the 2nd space, etc.
word = input("Enter a word: ")
word = list(word)
count = 0
while count < len(word):
word.insert(count, word.pop())
count = count + 1
print(word)
It just returns the original string in list form, even though I'm saving the last letter and inserting it before popping it off of the string? Does word.pop() not capture the last letter of a string before deleting it or am I overlooking something?
Well the simplest way to do what you are trying is to slice the string in reverse order, this does not even require changing into a list:
word = input("Enter a word: ")
return word[::-1]
Here's an experiment:
>>> word = list('python')
>>> word.insert(0, word[-1])
>>> word
['n', 'p', 'y', 't', 'h', 'o', 'n']
>>> word.remove(word[-1])
>>> word
['p', 'y', 't', 'h', 'o', 'n']
Wait, what?!
>>> help(word.remove)
Help on built-in function remove:
remove(value, /) method of builtins.list instance
Remove first occurrence of value.
Raises ValueError if the value is not present.
Remove first occurrence of value.
So, you inserted word[-1] at the beginning of the list, and then word.remove immediately removes the first occurrence of word[-1], which is now at the beginning of the list, you've just inserted it there!
You're setting the variables inside the while-loop to the same value. Also, use list.pop to remove the element from the list. For example:
word = input("Enter a word: ")
word = list(word)
count = 0
while count < len(word):
word.insert(count, word.pop())
count = count + 1
print(word)
Prints:
Enter a word: book
['k', 'o', 'o', 'b']
Here is the docstring for list.remove:
>>> help(list.remove)
Help on method_descriptor:
remove(self, value, /)
Remove first occurrence of value.
Raises ValueError if the value is not present.
>>>
As you can see, list.remove removes the first occurrence of the given value from the list. All your backwards function does right now is take the last character of the word, add it to the front and then immediately remove it from the front again. You do this once for every character in the word, the net result being no change.

Can this function return an int value by linking the elements of a list?

I am creating a function in order to develop a tiny word game. When I was creating it I got stuck when I tried to write the body. I was looking for information about Python and if I can write a return statement . It seems that it is possible but I didn't find out anything clear about that. This is my body function: This is my current progress: Am I close? or Should I try another method?
def num_words_on_board(board, words):
""" (list of list of str, list of str) -> int
Return how many words appear on board.
>>> num_words_on_board([['A', 'N', 'T', 'T'], ['X', 'S', 'O', 'B']], ['ANT', 'BOX', 'SOB', 'TO'])
3
"""
count = 0
for word_list in board:
if words in ''.join(word_list):
count = count + 1
return count
Your question is lacking in explanation, but I'll answer the best I understood.
I think you are trying to do something like a wordsearch solver, mixed with a scramble puzzle?
Anyways, my recommendation is to make multiple functions for everything you need to solve. For example:
The way I see it, you need to know if the letters in the board can make up each of the words in the words variable. That can be done by one function. If you don't really need the order of the word, just the length, then we can do it like this.
def same (word, letters):
temp = []
for every_letter in word:
if every_letter in letters and every_letter not in temp:
temp.append(every_letter)
return len(temp) >= len(word)
This function takes only one word and a "bunch of letters" (for example a list from board ;) ) as parameters, then the function compares each letter in the word against each letter in the "bunch of letters" and if it finds a match it adds it to a temp variable, at the end of the iterations if the temp variable has at least the same count of letters as the initial `word' then it's safe to say that the word can be built.
*there is a problem with this function. If the original word has repeated letters, for example the word "butter" then this function will not work, but since this is not your case we are good to continue.
For the second part we have to use that function for every word in board so we'll use another function for that:
def num_words_on_board(board, words):
count = 0
for word in words:
for letters in board:
if same(word, letters):
count += 1
print(count) # This is not needed, just here for testing.
return count
And there we go. This function should return the count which is 3. I hope this helps you.
(if anyone wanna correct my code please feel free, it's not optimal by any means. Just thought it would be easy to understand like this, rather than the answer in the duplicate question mentioned by Stefan Pochmann)
:)
I had a previous function can I use it in order to create this new one?.
My previous function is this:
def board_contains_word(board, word):
""" (list of list of str, str) -> bool
Return True if and only if word appears in board.
Precondition: board has at least one row and one column.
>>> board_contains_word([['A', 'N', 'T', 'T'], ['X', 'S', 'O', 'B']], 'ANT')
True
>>> board_contains_word([['A', 'N', 'T', 'T'], ['X', 'S', 'O', 'B']], 'NNT')
False
>>> board_contains_word([['A', 'N', 'T', 'T'], ['X', 'S', 'O', 'B']], 'NTT')
True
"""
for word_list in board:
if word in ''.join(word_list):
return True
return False

Replacing a character from a certain index [duplicate]

This question already has answers here:
Changing one character in a string
(15 answers)
Closed 2 years ago.
How can I replace a character in a string from a certain index? For example, I want to get the middle character from a string, like abc, and if the character is not equal to the character the user specifies, then I want to replace it.
Something like this maybe?
middle = ? # (I don't know how to get the middle of a string)
if str[middle] != char:
str[middle].replace('')
As strings are immutable in Python, just create a new string which includes the value at the desired index.
Assuming you have a string s, perhaps s = "mystring"
You can quickly (and obviously) replace a portion at a desired index by placing it between "slices" of the original.
s = s[:index] + newstring + s[index + 1:]
You can find the middle by dividing your string length by 2 len(s)/2
If you're getting mystery inputs, you should take care to handle indices outside the expected range
def replacer(s, newstring, index, nofail=False):
# raise an error if index is outside of the string
if not nofail and index not in range(len(s)):
raise ValueError("index outside given string")
# if not erroring, but the index is still not in the correct range..
if index < 0: # add it to the beginning
return newstring + s
if index > len(s): # add it to the end
return s + newstring
# insert the new string between "slices" of the original
return s[:index] + newstring + s[index + 1:]
This will work as
replacer("mystring", "12", 4)
'myst12ing'
You can't replace a letter in a string. Convert the string to a list, replace the letter, and convert it back to a string.
>>> s = list("Hello world")
>>> s
['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd']
>>> s[int(len(s) / 2)] = '-'
>>> s
['H', 'e', 'l', 'l', 'o', '-', 'W', 'o', 'r', 'l', 'd']
>>> "".join(s)
'Hello-World'
Strings in Python are immutable meaning you cannot replace parts of them.
You can however create a new string that is modified. Mind that this is not semantically equivalent since other references to the old string will not be updated.
You could for instance write a function:
def replace_str_index(text,index=0,replacement=''):
return '%s%s%s'%(text[:index],replacement,text[index+1:])
And then for instance call it with:
new_string = replace_str_index(old_string,middle)
If you do not feed a replacement, the new string will not contain the character you want to remove, you can feed it a string of arbitrary length.
For instance:
replace_str_index('hello?bye',5)
will return 'hellobye'; and:
replace_str_index('hello?bye',5,'good')
will return 'hellogoodbye'.
# Use slicing to extract those parts of the original string to be kept
s = s[:position] + replacement + s[position+length_of_replaced:]
# Example: replace 'sat' with 'slept'
text = "The cat sat on the mat"
text = text[:8] + "slept" + text[11:]
I/P : The cat sat on the mat
O/P : The cat slept on the mat
You can also Use below method if you have to replace string between specific index
def Replace_Substring_Between_Index(singleLine,stringToReplace='',startPos,endPos):
singleLine = singleLine[:startPos]+stringToReplace+singleLine[endPos:]
return singleLine

Comparing and printing elements in nested loops

The program identifies if one of the elements in the string word is a consonant by looping though the word string, and then for each iteration though the word string, iterating though the consonants list and comparing if the current element in word string equals to the current element of consonant list.
If yes, the current element of the word string is a consonant and the consonant gets printed (not the index of the consonant, but the actual consonant, for e.g. "d".)
The problem is, I get this instead:
1
1
What am I doing wrong? Shouldn't the nested loops work so that the below loop iterates every element for each element in the above loop? That is, each index above makes the below loop iterate though each index?
That's the program:
word = "Hello"
consonants = ['b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'z']
for character in range(len(word)):
for char in range(len(consonants)):
if consonants[char] == word[character]:
consonant = word[character]
print consonant
You are misreading the output. The character is the letter L lowercase, not the number 1.
In other words, your code is working as designed. The captital letter H is not in your consonants list, but the two lowercase letters l in Hello are.
Note that it'd be much more efficient to use a set for consonants here; you'd not have to loop over that whole list and just use in to test for membership. That works with lists too, but is much more efficient with a set. If you lowercase the word value you'd also be able to match the H.
Last but not least, you can loop over the word string directly rather than use range(len(word)) then use the generated index:
word = "Hello"
consonants = set('bcdfghjklmnpqrstvwxz')
for character in word.lower():
if character in consonants:
print character
Demo:
>>> word = "Hello"
>>> consonants = set('bcdfghjklmnpqrstvwxz')
>>> for character in word.lower():
... if character in consonants:
... print character
...
h
l
l

Python: Appending to a list

I'm working on a definition tester (you enter in words, their part of speeches, and synonyms for each, and it tests you on them). Problem I have is with the part that gets the word:
def get_word(): # this is in another function, that's why it is indented
import easygui as eg
word_info = eg.multenterbox(msg = 'Enter in the following information about each word.'
, title = 'Definition Tester'
, fields = ['Word: ', 'Part of Speech: ', 'Synonyms (separated by spaces): ']
, values = []
)
return word_info
for i in range(n):
my_list = get_word()
print my_list # for testing
word, pOS, synonyms = my_list[0], my_list[1], my_list[2]
word = word.capitalize()
synonyms = synonyms.split(', ')
words_list += word
print word # for testing
test_dict[word] = [pOS, synonyms]
print words_list # for testing
However, words_list ends up being the word(s) after the list(word) function is applied to them--- I'm not sure why.
For example: if the only word was 'word', words_list turns out to be ['w', 'o', 'r', 'd']. If there were two words ('dog', 'cat'), words_list turns out to be ['d', 'o', 'g', 'c', 'a', 't'].
Here is my input (into get_word()): Word: 'myword', Part of Speech: 'n', Synonyms: 'synonym, definition'.
This is the output I get:
['myword', 'n', 'synonym, definition']
Myword
['M', 'y', 'w', 'o', 'r', 'd'] # Why does this happen?
This is the only thing wrong with my program... If I could get some input on how to fix this and what is wrong, it would be much appreciated. Thanks!
It's because of this line:
words_list += word
+= on a list is for adding all the elements in another list. As it happens, Python strings also function like lists of characters, so you are adding each character to the list as its own element.
You want this:
words_list.append(word)
which is for adding a single element to the end.
After messing around with it, I figured out the problem myself, so I thought I should put it here for anyone who has something similar:
Instead of doing words_list += word, it should be: words_list.append(word).
Or, which is what I did, you can do: words_list += [word]. Now, word is a list object, so it will add onto the previous list.

Categories

Resources