Substituting all letters from a string with a single character - python-3.x

I am doing an hangman game in python and I'm stuck in the part where I have a random generated word and I'm trying to hide the word by replacing all characters with dashes like this:
generated word -> 'abcd'
hide word -> _ _ _ _
I have done the following:
string = 'luis'
print (string.replace ((string[i]) for i in range (0, len (string)), '_'))
And it gives me the following error:
^
SyntaxError: Generator expression must be parenthesized
Please give me some types

You could try a very simple approach, like this:
word = "luis"
print("_" * len(word))
Output would be:
>>> word = "luis"
>>> print("_" * len(word))
____
>>> word = "hi"
>>> print("_" * len(word))
__

The simplest is:
string = "luis"
"_" * len(string)
# '____'
If you want spaces inbetween:
" ".join("_" * len(string))
# '_ _ _ _'
However, since you will need to show guessed chars later on, you are better off starting with a generator in the first place:
" ".join("_" for char in string)
# '_ _ _ _'
So that you can easily insert guessed characters:
guessed = set("eis")
" ".join(char if char in guessed else "_" for char in string)
# '_ _ i s'

Related

Simplify multiple functions into one in Python

I am wondering how it is possible to combine the following functions into one. The functions remove the entire word if "_" respectively "/" occur in a text.
I have tried the following, and the code fulfils it purpose. It his however cumbersome and I am wondering how to simplify it.
text = "This is _a default/ text"
def filter_string1(string):
a = []
for i in string.split():
if "_" not in i:
a.append(i)
return ' '.join(a)
def filter_string2(string):
a = []
for i in string.split():
if "/" not in i:
a.append(i)
return ' '.join(a)
text_no_underscore = filter_string1(text)
text_no_underscore_no_slash = filter_string2(text_no_underscore)
print(text_no_underscore_no_slash)
The output is (as desired):
"This is text"
You can combine the if conditions.
text = "This is _a default/ text"
def filter(string):
a = []
for i in string.split():
if "_" not in i and "/" not in i:
a.append(i)
return ' '.join(a)
print(filter(text))
There is a function called re.sub in python's re module which will let you accomplish this quickly.
def remove_words(text):
import re
return re.sub(
pattern=r'\s_[\s\S^\/]*\/', # regular expression used to match the parts to remove
repl='', # replace matched parts with empty string
string=text # use `text` as input
)
Explaining the regular expression \s_[\s\S^\/]*\/ (by deconstructing its parts):
\s_ match whitespace character followed by underscore
[\s\S^\/]* match any character sequence not containing a forward slash (sequence may be length 0)
\/ match the forward slash
Testing the function:
text = "This is _a default/ text"
text_no_underscore_no_slash = remove_words(text)
print('Result:', text_no_underscore_no_slash)
# Result: This is text
text = "This is _a longer/ _and also custom/ text"
text_no_underscore_no_slash = remove_words(text)
print('Result:', text_no_underscore_no_slash)
# Result: This is text
By the way, your original code has a bug, I think.
text = "This is _a longer/ _and also custom/ text"
text_no_underscore = filter_string1(text)
text_no_underscore_no_slash = filter_string2(text_no_underscore)
print(text_no_underscore_no_slash == 'This is text')
# False

Hangman program: incorrect use of global variable in loop

I'm writing a program to play the game hangman, and I don't think I'm using my global variable correctly.
Once the first iteration of the program concludes after a correct guess, any successive iteration with a correct guess prints the word and all of its past values.
How can I only print the most current value of word? This chunk of code is within a while loop where each iteration gets user input. Thanks!
Code:
word=''
#lettersGuessed is a list of string values of letters guessed
def getGuessedWord(secretWord, lettersGuessed):
global word
for letter in secretWord:
if letter not in lettersGuessed:
word=word+' _'
elif letter in lettersGuessed:
word=word+' '+letter
return print(word)
The Output:
#first iteration if 'a' was guessed:
a _ _ _ _
#second iteration if 'l' was guessed:
a _ _ _ _ a _ _ l _
#third iteration if 'e' was guessed:
a _ _ _ _ a _ _ l _ a _ _ l e
#Assuming the above, for the third iteration I want:
a _ _ l e
Note: This is only a short section of my code, but I don't feel like the other chunks are relevant.
The main problem you are facing is that you are appending your global variable every time you call your function. However, I think you don't need to use a global variable, in general this is a very bad practice, you can simply use the following code considering what you are explaining in your question:
def getGuessedWord(secretWord, lettersGuessed):
return ' '.join(letter if letter in lettersGuessed else '_'
for letter in secretWord)
I also think that it is better if you use a python comprehension to make your code faster.
every time you are calling the function getGuessedWord you are adding to `word, You can not use a global:
secretWord = "myword"
def getGuessedWord(secretWord, lettersGuessed):
word = ""
for letter in secretWord:
if letter not in lettersGuessed:
word=word+' _'
elif letter in lettersGuessed:
word=word+' '+letter
return print(word)
getGuessedWord(secretWord,"")
getGuessedWord(secretWord,"m")
getGuessedWord(secretWord,"mwd")
Or you can solve this by setting word at a constant length, (not as nice and harder to follow) e.g: word='_ '*len(secretWord), then instead of adding to it, replace the letter word=word[:2*i]+letter +word[2*i+1:]
Example here:
secretWord = "myword"
word='_ '*len(secretWord)
def getGuessedWord(secretWord, lettersGuessed):
global word
for i, letter in enumerate(secretWord):
if letter in lettersGuessed:
word=word[:2*i]+letter +word[2*i+1:]
return print(word)
getGuessedWord(secretWord,"")
getGuessedWord(secretWord,"m")
getGuessedWord(secretWord,"w")
getGuessedWord(secretWord,"d")

Print on one line in python Window

I'm not sure how to get multiple outputs from a for loop to print on the same line in a window. I'm using the built in Window function from uagame with python3.x. Here's what the code looks like:
for char in a_word:
if char in user_guess:
window.draw_string(char+" ",x, y)
else:
window.draw_string('_ ',x, y)
y = y + font_height
This keeps displaying as:
_
_
_
_
And I want it to print as
_ _ _ _
Any idea how to get each character or _ to display on one line? This is for a WordPuzzle/Hangman type game.
Use this as a example, and hopefully you will implement the same to your code.
for i in range(1,10):
print(i,end=",")
print()
The output looks like
1,2,3,4,5,6,7,8,9,
Define a empty list and append your characters then print all at once
a=[]
for char in a_word:
if char in user_guess:
a.append(char)
else:
a.append(char)
print(a,end=",")
y = y + font_height

Python zip() function not working

I'm new to Stack Overflow and Python.
I am trying to build a word by replacing items in a list by index and when I run this code only the first instance is replace.
word = "DRIPPING"
letter = "P"
checkList = [" _ "] * len(word)
letterLocation=[3,4]
for (index, replacement) in zip(letterLocation, letter):
checkList[index] = replacement
print(checkList)
Returns [' _ ', ' _ ', ' _ ', 'P', ' _ ', ' _ ', ' _ ', ' _ ']
Any help will be very welcome.
zip takes two or more iterables, and generates tuples that contain an element from each iterable until one of the iterables is exhausted.
Since letter contains only one character, zip will thus emit only a single tuple:
>>> list(zip(checkList,letter))
[(' _ ', 'P')]
You do not need zip here, you can simply iterate over the checkList, and assign letter to all these indices:
for index in letterLocation: # look ma, no zip
checkList[index] = letter

Trimming strings in Scala

How do I trim the starting and ending character of a string in Scala
For inputs such as ",hello" or "hello,", I need the output as "hello".
Is there is any built-in method to do this in Scala?
Try
val str = " foo "
str.trim
and have a look at the documentation. If you need to get rid of the , character, too, you could try something like:
str.stripPrefix(",").stripSuffix(",").trim
Another way to clean up the front-end of the string would be
val ignoreable = ", \t\r\n"
str.dropWhile(c => ignorable.indexOf(c) >= 0)
which would also take care of strings like ",,, ,,hello"
And for good measure, here's a tiny function, which does it all in one sweep from left to right through the string:
def stripAll(s: String, bad: String): String = {
#scala.annotation.tailrec def start(n: Int): String =
if (n == s.length) ""
else if (bad.indexOf(s.charAt(n)) < 0) end(n, s.length)
else start(1 + n)
#scala.annotation.tailrec def end(a: Int, n: Int): String =
if (n <= a) s.substring(a, n)
else if (bad.indexOf(s.charAt(n - 1)) < 0) s.substring(a, n)
else end(a, n - 1)
start(0)
}
Use like
stripAll(stringToCleanUp, charactersToRemove)
e.g.,
stripAll(" , , , hello , ,,,, ", " ,") => "hello"
To trim the start and ending character in a string, use a mix of drop and dropRight:
scala> " hello,".drop(1).dropRight(1)
res4: String = hello
The drop call removes the first character, dropRight removes the last. Note that this isn't "smart" like trim is. If you don't have any extra character at the start of "hello,", you will trim it to "ello". If you need something more complicated, regex replacement is probably the answer.
If you want to trim only commas and might have more than one on either end, you could do this:
str.dropWhile(_ == ',').reverse.dropWhile(_ == ',').reverse
The use of reverse here is because there is no dropRightWhile.
If you're looking at a single possible comma, stripPrefix and stripSuffix are the way to go, as indicated by Dirk.
Given you only want to trim off invalid characters from the prefix and the suffix of a given string (not scan through the entire string), here's a tiny trimPrefixSuffixChars function to quickly perform the desired effect:
def trimPrefixSuffixChars(
string: String
, invalidCharsFunction: (Char) => Boolean = (c) => c == ' '
): String =
if (string.nonEmpty)
string
.dropWhile(char => invalidCharsFunction(char)) //trim prefix
.reverse
.dropWhile(char => invalidCharsFunction(char)) //trim suffix
.reverse
else
string
This function provides a default for the invalidCharsFunction defining only the space (" ") character as invalid. Here's what the conversion would look like for the following input strings:
trimPrefixSuffixChars(" Tx ") //returns "Tx"
trimPrefixSuffixChars(" . Tx . ") //returns ". Tx ."
trimPrefixSuffixChars(" T x ") //returns "T x"
trimPrefixSuffixChars(" . T x . ") //returns ". T x ."
If you have you would prefer to specify your own invalidCharsFunction function, then pass it in the call like so:
trimPrefixSuffixChars(",Tx. ", (c) => !c.isLetterOrDigit) //returns "Tx"
trimPrefixSuffixChars(" ! Tx # ", (c) => !c.isLetterOrDigit) //returns "Tx"
trimPrefixSuffixChars(",T x. ", (c) => !c.isLetterOrDigit) //returns "T x"
trimPrefixSuffixChars(" ! T x # ", (c) => !c.isLetterOrDigit) //returns "T x"
This attempts to simplify a number of the example solutions provided in other answers.
Someone requested a regex-version, which would be something like this:
val result = " , ,, hello, ,,".replaceAll("""[,\s]+(|.*[^,\s])[,\s]+""", "'$1'")
Result is: result: String = hello
The drawback with regexes (not just in this case, but always), is that it is quite hard to read for someone who is not already intimately familiar with the syntax. The code is nice and concise, though.
Another tailrec function:
def trim(s: String, char: Char): String = {
if (s.stripSuffix(char.toString).stripPrefix(char.toString) == s)
{
s
} else
{
trim(s.stripSuffix(char.toString).stripPrefix(char.toString), char)
}
}
scala> trim(",hello",',')
res12: String = hello
scala> trim(",hello,,,,",',')
res13: String = hello

Resources