How to keep a value from resetting in a loop? - loops

I have been trying to set up a health system for my school project but the value keeps resetting regardless of the fact that monster_health is outside of the loop, my friends and I can't seem to fix this.
Code:
monster_health = 100
while monster_health > 0:
playeraction = input('Placeholder beast wants to fight you!!\n1) Basic Attack')
print(monster_health)
if playeraction == 1:
monster_health = monster_health-7
continue
if monster_health <= 0:
print('You killed the monster!! Gain nothing, this is a test you barbarian')
break
Output:
Placeholder beast wants to fight you!!
1) Basic Attack
100 #should print 97 but fails to

replace
if playeraction == 1:
with
if playeraction == "1":
or:
if int(playeraction) == 1:
Because your input is string format and not an integer and 1 != "1".

From your code, you are printing the monster health before updating it, so it will be "100" (the initial value) the first time.
while monster_health > 0:
playeraction = input('Placeholder beast wants to fight you!!\n1) Basic Attack')
print(monster_health) # at this time, it is still 100

Related

i'm trying to make higher_lower game that let the user to guess between to celebrities i don't know what's the problem in my programme

i think the problem is in loop i don't know the program is just stopped after the first round but it's only giving one result and the rest is jut
keep repeating the same print statement and it's not giving a new random celebrity plus the score is always 1 or 0 #i don't know where the bug is but the
a=random.choice(data)
b=random.choice(data)
value1=a["follower_count"]
value2=b["follower_count"]
nameA=a["name"]
nameB=b["name"]
descriptionA=a["description"]
descriptionB=b["description"]
countryA=a["country"]
countryB=b["country"]
score=0
def compare_1(a,b):
game_continue=True
while game_continue:
a=b
b=random.choice(data)
while a == b:
b=random.choice(data)
print(f"compare A: {nameA},a {descriptionA}, from {countryA}")
print(vs)
print(f"compare B: {nameB},a {descriptionB}, from {countryB}")
answer_comp()
#clear()
#print(logo)
else:
game_continue=False
print(f"soory you loose : {score}")
def answer_comp():
global score
answer=input("who has more followers A or B ").lower()
global value1
global value2
if answer=="a" and value1>value2:
score+=1
print(f"correct,move to the next one your score is:{score}")
return a
elif answer=="b" and value1<value2:
score+=1
print(f"correct,move to the next one your score is:{score}")
return b
elif answer=="a" and value1<value2:
print(f"faulse,you loose your score is :{score}")
elif answer=="b"and value1>value2:
print(f"faulse,you loose your score is :{score}")
compare_1(a,b)

Ruby Array Elements

I am trying to create password Generate in ruby. At the moment all is working just got stuck at the final piece of generating the password.
I asked user if he/she would like the password to include numbers, lowercase or uppercase.
If YES, user will enter 1 and 0 for NO.
I used the code below to generate password if everything is 1. Meaning user want to include numbers, lowercase and uppercase.
if numbers == 1 && lowercase == 1 && uppercase == 1
passGen = [(0..9).to_a + ('A'..'Z').to_a + ('a'..'z').to_a].flatten.sample(10)
end
p passGen
This works 90% of the time. 10% of the time the generated password will not include say any numbers. But everything else present. I am not sure if this is because of the size or length of Array from which the password is sampled.
Anyway lets go to the main problem below
Here is the problem, I am struggling to write the code to generate password if one or more of input is 0. That's if user don't want to include numbers. Or no numbers and uppercase etc . As I can't predict what user may want or not want. I need help on this please.
Thank you.
You will need to make your input array more dynamic:
passGen = []
passGen += (0..9).to_a if numbers == 1
passGen += ('A'..'Z').to_a if uppercase == 1
passGen += ('a'..'z').to_a if lowercase == 1
passGen.sample(10).join
Now, to tackle your other issue with missing characters - this is caused as you are simply taking 10 random characters from an array. So it can just take, for example, all digits.
To tackle this you need to get one character from each generator first and then generate the remaining characters randomly and shuffle the result:
def generators(numbers:, lowercase:, uppercase:)
[
(0..9 if numbers),
('A'..'Z' if uppercase),
('a'..'z' if lowercase)
].compact.map(&:to_a)
end
def generate_password(generators:, length:, min_per_generator: 1)
chars = generators.flat_map {|g| Array.new(min_per_generator) { g.sample }}
chars += Array.new(length - chars.length) { generators.sample.sample }
chars.shuffle.join
end
gens = generators(numbers: numbers == 1, uppercase == 1, lowercase: lowercase == 1)
Array.new(10) { generate_password(generators: gens, length: 10) }
The code doesn't know it needs to include a digit/letter from every group. The sample takes random signs and since you a basically sampling 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz there is a possibility that all the signs will not be digits.
The easiest way to fix it is to check if a sign from every group is in the "password" and then replace a random sign with a sign from group that is not present.
If I were to program this I would do it like that
def random_from_range(range)
range.to_a.sample.to_s
end
def passGen(numbers, lowercase, uppercase)
result = ''
possibleSigns = []
if numbers == 1
range = (0..9)
result += random_from_range(range)
possibleSigns += range.to_a
end
if lowercase == 1
range = ('A'..'Z')
result += random_from_range(range)
possibleSigns += range.to_a
end
if uppercase == 1
range = ('a'..'z')
result += random_from_range(range)
possibleSigns += range.to_a
end
desired_lenth = 10
while result.length < desired_lenth
result += possibleSigns.sample.to_s
end
result
end
puts passGen(1,1,1)
By saying (0..9).to_a + ('A'..'Z').to_a + ('a'..'z').to_a, you're creating an Array of 10 + 26 + 26 = 62 elements, and then you pick only 10 elements out of it.
At your place I'd wrap password generation around an until block:
def generate_password_with_digits_and_caps
[(0..9).to_a + ('A'..'Z').to_a + ('a'..'z').to_a].flatten.sample(10).join
end
passGen = ''
until passGen.match(/[A-Z]/) && passGen.match(/[a-z]/) && passGen.match(/\d/)
passGen = generate_password_with_digits_and_caps
end
This could also work (closer to your snipppet):
if numbers == 1 && lowercase == 1 && uppercase == 1
passGen = ''
until passGen.match(/[A-Z]/) && passGen.match(/[a-z]/) && passGen.match(/\d/)
passGen = [(0..9).to_a + ('A'..'Z').to_a + ('a'..'z').to_a].flatten.sample(10).join
end
end
Start with something simple and stupid:
passGen = (('0'..'9').to_a.sample(1)+ ('A'..'Z').to_a.sample(1)+('a'..'z').to_a.sample(8).shuffle).join
Technically speaking, this already fulfills your requirement. From the viewpoint of aesthetics and security, the disadvantage here is that the number of upper case characters is always 8. A more elegant solution would be to find three non-zero integers which add up to 10, and can be used as the arguments for the sample call. Also, if no numbers are requested, you simply pass 0 as argument to sample.
Since this exceeds the scope of your question, and I don't even know whether you want to go so far, I don't elaborate on this here further.

Why is my code returning all records when I am trying to subset inside for loop - R?

for (i in 1:length(data$name)){
if (!is.na(data$years[i]) >= 34 & !is.na(data$gender[i]) == "male" & !is.na(data$classification[i]) == "mid"){
print(data$name)
}
}
There's a few problems in your code. I am assuming this is a class exercise or similar, so I'll add a bit extra detail to illustrate where you've missed a step.
First of all you loop works fine, but your if condition is not completely correct.
!is.na(data$years[i]) >= 34
All of your conditions look (somewhat) like this. The idea is obvious, you want to "check that data$years[i] is not null, and above 34". But in R (and most languages) you have to check these seperately.
!is.na(data$years[i]) && data$years[i] >= 34
Similar for the rest of your conditions.
Next your print statement is printing out everything, because this is what you're asking it to:
print(data$name)
is "ignorant" of anything else you've done up till now. It seems you want to print the specific record, eg:
print(data$name[i])
And this is the way to go about it.
Now R has a thing called "vectorization", so we could wrap this entire loop up in one go:
data$name[!is.na(data$years) & !is.na(data$gender) & !is.na(data$classification) & data$year > 34 & data$gender == "male" & data$classification == "mid"]
But I am assuming that is not part of your current exercise. Note the slight (but important) difference that for vectorized (eg. more than 1) condition I use single & but for single conditions I use 2 &&. The latter is optimized to be "lazy" for single inputs (thus faster).
Perhaps you can try subset + complete.cases like below
subset(
data,
years >= 34 & gender == "male" & classification == "mid" & complete.cases(data[c("years", "gender", "classification")])
)$name

Skip one iteration and adding conditions Python (Basic Question)

I have been reading a text file a object and create a list with the contents.
textfile:
Activity Time Location
Football 8-9 Pitch
Basketball 9-10 Gym
Lunch 11-12 Home
Read 13-14 Library
Swim 14-15 Pool
openTime = 6
closeTime = 15
come = int(input('When do you want to come?'))
leave = int(input('When do you want to leave?'))
# endtime_of_activity and startTimeofactivity is equal to the startingtime
# of each activity and the end time of each activity in the textfile
# (taken from a list that I have been splitting).
for i in range(len(my_list)):
item = my_list[i]
if (i == 1):
continue
if closeTime <= come <= endtime_of_activity and startTimeofactivity < leave <= closeTime:
print(item.activities)
My question: As you can read in the textfile there are some activities appering on different times. For example football between 8 and 9. With the code I want to be able to skip the second element (basketball) as the code is doing, however, I want the if statement under "continue" to work. If i type that im coming 8 and leaving at 12 I want all the activities (excluding the second one) to show. This works for me when I'm doing a regular for-loop without skiping the second activity, like when im just writing: for i in my_list, then adding on the condition, but when Im doing the code above it shows me all the activites (except basketball) independeltly of when I chose to come and leave. What have I missed? How could I write the code better?
If you want to skip a certain activity, simply test if the activitiy to be printed is the same and skip it if it is:
with open("f.txt","w") as f:
f.write(("Activity Time Location\nFootball 8-9 "
"Pitch\nBasketball 9-10 Gym\nLunch 11-12"
" Home\nRead 13-14 Library\nSwim 14-15"))
data = []
with open("f.txt") as f:
for line in f:
act, time, what = (line.strip().split(" ") + ["","",""])[:3]
if data:
try:
time=list(map(int, time.split("-")))
except ValueError:
continue # invalid time: skip row
data.append([act,time,what])
header,*data = data
openTime = 6
closeTime = 15
come = 9
leave = 12
skip=set(["Basketball"])
fmt = "{:<15}"*len(header)
print(fmt.format(*header))
for act,(start,stop),what in data:
if act in skip:
continue
if start >= come and stop <= leave and openTime <= come and closeTime >= leave:
print(fmt.format(act, f"{start}-{stop}", what))
Output:
Activity Time Location
Football 8-9 Pitch
Lunch 11-12 Home

Create Loop So Whole Task Repeats

import sgenrand
# program greeting
print("The purpose of this exercise is to enter a number of coin values")
print("that add up to a displayed target value.\n")
print("Enter coins values as 1-penny, 5-nickel, 10-dime,and 25-quarter.")
print("Hit return after the last entered coin value.")
print("--------------------")
#print("Enter coins that add up to 81 cents, one per line.")
total = 0
#prompt the user to start entering coin values that add up to 81
while True:
final_coin= sgenrand.randint(1,99)
print ("Enter coins that add up to", final_coin, "cents, on per line")
user_input = int(input("Enter first coin: "))
if user_input != 1 and user_input!=5 and user_input!=10 and user_input!=25:
print("invalid input")
total = total + user_input
while total != final_coin:
user_input = int(input("Enter next coin:"))
total = total + user_input
if user_input == input(" "):
break
if total > final_coin:
print("Sorry - total amount exceeds", (final_coin))
if total < final_coin:
print("Sorry - you only entered",(total))
if total== final_coin:
print("correct")
goagain= input("Try again (y/n)?:")
if goagain == "y":
if goagain == "n":
print("Thanks for playing ... goodbye!" )
I've been trying to create this loop, so it can repeat the whole program at the end when the user accepts/ if he accepts to do it again at the end.
I know you have to have a while statement around your whole program, but with my while true statement at the top, it only repeats the first part of my program and not the whole thing.
Well one thing you should be careful of is that you do not set the
total = 0
at the start of each loop. So when the user plays the game again. He will continue using his previous total. You should move total = 0 to the start of the loop
while True:
total = 0
Additionally, you need to deindent you first
while True
statement as it does not align properly with the rest of your code.
Finally, you need to allow the user to exit the while loop after he selects No for trying again.
if goagain == "n":
print("Thanks for playing ... goodbye!" )
break
This can be done by applying a break statement.

Resources