I want to apply a condition inside a resursion only once. My data structure looks as follows
stages = {"stage_1": False, "stage_2":False, "stage_3":False,"state_4": False}
I want to pick any stage randomly from it and change the status to True. But when total number of true stage is 3 I want to randomly change a True stage to False. But only once. Then it should continue to turn stages in to True. When all 4 stages are true. The recursion process stops. How can I do that ? I have tried the following code. but it is not complete.
def process(stages):
all_stages = [stage for stage, status in stages.items() if status == False]
if len(all_stages) !=0:
print(all_stages)
select_ = random.choice(all_stages)
print("\tselected stage: ",select_)
stages[select_] = True
process(stages)
else:
print("Done")
print(stages)
process(stages)
This works without adding that extra condition. I have tried the following one. But that does not work
def process(stages):
all_stages = [stage for stage, status in stages.items() if status == False]
if len(all_stages) !=0:
print(all_stages)
select_ = random.choice(all_stages)
print("\tselected stage: ",select_)
stages[select_] = True
if len(all_stages) == 1:
select_ = random.choice([stage for stage, status in stages.items() if status == True])
stages[select_] = False
process(stages)
else:
print("Done")
print(stages)
process(stages)
CodePudding user response:
As with many recursion problems, adding a state to your function call will help you a lot.
Consider making an inner call to process_internal()
that would get the current state of the recursion, whether it's stage 0 (False -> True), stage 1 (True -> False) or stage 2 (False -> True).
import random
def flip_random_state(stages, relevant_bool_val):
relevant_stages = [stage for stage, status in stages.items() if status == relevant_bool_val]
print(relevant_stages)
selected_stage = random.choice(relevant_stages)
print(f"\tSelected stage: {selected_stage}")
stages[selected_stage] = not stages[selected_stage]
return stages
def count_stages_with_status(stages, input_status):
return len([stage for stage, status in stages.items() if status == input_status])
def process_internal(stages, state):
if state == 2 and count_stages_with_status(stages, True) == 4:
print("Done")
print(stages)
return
if state == 0 or state == 2:
relevant_bool_val = False
else:
relevant_bool_val = True
if state == 1 and count_stages_with_status(stages, False) == 0:
state = 2
if state == 0 and count_stages_with_status(stages, True) == 3:
state = 1
stages = flip_random_state(stages, relevant_bool_val)
process_internal(stages, state)
def process(stages):
return process_internal(stages, 0)
stages = {"stage_1": False, "stage_2": False, "stage_3": False,"state_4": False}
process(stages)
CodePudding user response:
You could add a global variable as a flag to get, wheather you already set one back to False, or add an optional parameter like returnedToFalse=False And set it to true when you eventually set one to false already.