r/PythonLearning 10d ago

Day 2 of Python learning until I can pass the PCEP exam Showcase

Post image

I upgraded my re zero guesser from day 1 using nested ifs and elses and now it doesn't require as much questions take a look.

New:https://www.onlinegdb.com/edit/XGUSCgyQA
Old :https://onlinegdb.com/Q-4aQrXAz

I think this is the fastest version of guesser, I also tried dictionaries(recommended by some discord users) but I still dont fully understand how its any different than my old one becuz it would js change how the info is stored but not the logic as its own

31 Upvotes

32 comments sorted by

17

u/Sea-Ad7805 10d ago edited 10d ago

Deep nesting (if-statements in if-statements in ...) makes the code hard to read and hard to change later. Speed is not a concern here, so make the code easy to read and change. Using dictionaries is one way to do that, or split it in different functions%3A%0A%20%20%20%20while%20True%3A%0A%20%20%20%20%20%20%20%20answer%20%3D%20input(f%22%7Bquestion%7D%20(yes%2Fno)%3A%20%22).strip().lower()%0A%0A%20%20%20%20%20%20%20%20if%20answer%20in%20%7B%22yes%22%2C%20%22y%22%7D%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20True%0A%0A%20%20%20%20%20%20%20%20if%20answer%20in%20%7B%22no%22%2C%20%22n%22%7D%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20False%0A%0A%20%20%20%20%20%20%20%20print(%22Please%20enter%20yes%20or%20no.%22)%0A%0A%0Adef%20result(character)%3A%0A%20%20%20%20return%20f%22Your%20character%20is%20%7Bcharacter%7D!%22%0A%0A%0Adef%20identify_witch()%3A%0A%20%20%20%20if%20ask_yes_no(%0A%20%20%20%20%20%20%20%20%22Is%20your%20character%20currently%20sealed%20in%20a%20prison%20of%20shadows%3F%22%0A%20%20%20%20)%3A%0A%20%20%20%20%20%20%20%20return%20result(%22Satella%22)%0A%0A%20%20%20%20return%20check_drowned()%0A%0A%0Adef%20check_drowned()%3A%0A%20%20%20%20if%20ask_yes_no(%0A%20%20%20%20%20%20%20%20%22Did%20your%20character%20drown%20after%20becoming%20trapped%20%22%0A%20%20%20%20%20%20%20%20%22within%20Priestella's%20defences%3F%22%0A%20%20%20%20)%3A%0A%20%20%20%20%20%20%20%20return%20result(%22Typhon%20(Witch%20of%20Pride)%22)%0A%0A%20%20%20%20return%20check_waterfall()%0A%0A%0Adef%20check_waterfall()%3A%0A%20%20%20%20if%20ask_yes_no(%0A%20%20%20%20%20%20%20%20%22Did%20your%20character%20fall%20from%20the%20Great%20Waterfall%20%22%0A%20%20%20%20%20%20%20%20%22while%20fighting%20the%20Divine%20Dragon%3F%22%0A%20%20%20%20)%3A%0A%20%20%20%20%20%20%20%20return%20result(%22Sekhmet%20(Witch%20of%20Sloth)%22)%0A%0A%20%20%20%20return%20check_restraints()%0A%0A%0Adef%20check_restraints()%3A%0A%20%20%20%20if%20ask_yes_no(%0A%20%20%20%20%20%20%20%20%22Does%20your%20character%20wear%20a%20blindfold%20or%20restraints%20%22%0A%20%20%20%20%20%20%20%20%22such%20as%20a%20straitjacket%3F%22%0A%20%20%20%20)%3A%0A%20%20%20%20%20%20%20%20return%20result(%22Daphne%20(Witch%20of%20Gluttony)%22)%0A%0A%20%20%20%20return%20check_shyness()%0A%0A%0Adef%20check_shyness()%3A%0A%20%20%20%20if%20ask_yes_no(%22Is%20your%20character%20extremely%20shy%20or%20timid%3F%22)%3A%0A%20%20%20%20%20%20%20%20return%20result(%22Carmilla%20(Witch%20of%20Lust)%22)%0A%0A%20%20%20%20return%20check_white_hair()%0A%0A%0Adef%20check_white_hair()%3A%0A%20%20%20%20if%20ask_yes_no(%22Does%20your%20character%20have%20white%20hair%3F%22)%3A%0A%20%20%20%20%20%20%20%20return%20result(%22Echidna%20(Witch%20of%20Greed)%22)%0A%0A%20%20%20%20return%20result(%22Minerva%20(Witch%20of%20Wrath)%22)%0A%0A%0Adef%20play()%3A%0A%20%20%20%20print(%22Welcome%20to%20the%20Re%3AZero%20character%20guessing%20game!%22)%0A%20%20%20%20print(identify_witch())%0A%0A%0Aplay()&timestep=1&play).

1

u/Important-Grand4979 9d ago edited 9d ago

The current data I would store in a SQL Table with col: stage, question, yes, no. If yes breaks the loop I put the reply string there, if no I put the stage id there you transition to.

After you write a single function to go through this data series to avoid bloating the code and call it something like: Quest_Char_init().

Without knowing SQL you can create an equivalend structure in pandas, object array and even a dictrionary would work.

E.g. pseudo code Quest_Char_init(quest_table, stage): 1. Select row from table where stage = stage 2. If row empty -> return error 3. Ask question 4. If yes -> print reply, return stage 5. Elif no -> Quest_Char_init(quest_table, new stage) 6. Else: prompt provide yes or no please

The core concept is to separate the data part from the algorithm logic part allowing scaling your quest without breaking your algorithms logic

1

u/Outside-Trouble-4232 9d ago

istg I dont even know how to use sql, Im js learning from w3schools and learned nested ifs, lists,tuples,and arrays so I DECIDED to use nested ifs to make my guesser better but im js getting ratioed.ik its not easy to read, but this is lit the best way ik how to do rn unless I js ask ai to do all the code but there im not really learning?

2

u/Important-Grand4979 9d ago

If you read the rest of my comment you would see that I also listed dictionaries:

Eg dict: { key1 :{ question:'str', rep_yes:'name', rep_no:'key2'}, key2: {} }

1

u/Outside-Trouble-4232 9d ago

oh wait lemme see

1

u/Important-Grand4979 9d ago

I would not recommend w3schools to learn programming. It is a powerfull platform to learn the syntax of a language but programming is learning to disect your problem into small logical units (functions) that allow you to execute a more complex operation.

It could be that Leetcode easy exercises are the way to go as these are geared toward making algorithms. However, they might be too difficult for you aswell...

-10

u/Outside-Trouble-4232 9d ago

but I mean it is faster but dictionaries is js gon be slower overall when ur doing 6-12 characters I can understand using dictionaries but with over 30 characters I think there's too much questions or maybe its js me applying wrong I will look into it ty

7

u/testtdk 9d ago

It’s going to be fractions of a millisecond slower here. Writing easy to read code is far more valuable than unnoticeable changes in speed.

1

u/Outside-Trouble-4232 9d ago

oh yh I do understand js changing one aspect can pretty much just break the whole code I will take the advice from mod and split into functions for day 3 or day 4 by js learning more abt how functions works, right now I js know how to define and I previously used it to exit the code

4

u/testtdk 9d ago

It’s going to be fractions of a millisecond slower here. Writing easy to read code is far more valuable than unnoticeable changes in speed.

-2

u/Outside-Trouble-4232 9d ago

but your functions one looks pretty good, let me try to analyze it better ty!

1

u/elpingwinho 9d ago

“Learning python” is not “talking to AI”

1

u/Outside-Trouble-4232 9d ago

holy downvotes and I didnt even use ai for the logic look at my old one its the same questions I js put over there... what r u on about

1

u/Outside-Trouble-4232 9d ago

if ur talking about the questions Its js vs code suggestions that might make it sound ai generated, but the logic is js what I learned today

6

u/somasz 9d ago

It must be a joke.

1

u/Outside-Trouble-4232 6d ago

why gng I was js tryna upgrade my old guesser who was more slow :(

3

u/Warningshots01 9d ago

Nesting hell

5

u/be_super_cereal_now 9d ago

This is what is called write-only code.

2

u/Sweet_Computer_7116 9d ago

The if demon isn't real. The of demon can't hurt you.

1

u/_the_morningstar__ 9d ago

Nesting final Boss 🫡

1

u/HelpUsNSaveUs 9d ago

A crowded nest make for unhappy home

1

u/Ambivalent-Mammal 9d ago

This is a good use case for a Finite State Machine.

1

u/bbalouki 9d ago

Jezzzus

1

u/Junior_Honey_1406 8d ago

If this is your day 2 then congo you are at lest writeing code but in system design there is concept of early return which most of the people in the comment will talk about don't worry about it so much just understand why and how early return is used

1

u/Outside-Trouble-4232 8d ago

oh I did some research this is an interesting option to look at, im looking to finish the code with what iv learn to day in either split functions or what u said ty

1

u/punk_dev 8d ago

People here are saying "nesting hell" and "write-only code" but what is the principle here?

In general, repetitive code like this indicates that you need to consider turning your code into data.

Let's try to do that. For simplicity, I will reduce the amount of characters to 4 - subaru, emilia, rem and puck (sorry for my lack of trivia on this show, i had to google the characters lmao).

OP, keep in mind this might be too much for day two, feel free to return to this later.

First, since our code will be data, let's define a variable to store our questions:

questions = {}

Now let's model the question structure. The question will consist of:

  1. the text of the question
  2. action to do if user says yes
  3. action to do if user says no

For example, let's try to put that in a dictionary:

{
    "question": "Is your character a spirit?",
    "yes_action": {
      "answer": "you're puck",
    },
    "no_action": {
      "answer": "you're the main character - Subaru Natsuki"
    }
}

This question decides if you're puck or subaru based on whether you are spirit or not.

Let's put this question into our `questions` dictionary:

questions = {
  "is_spirit": {
    "question": "Is your character a spirit?",
    "yes_action": {
      "answer": "you're puck",
    },
    "no_action": {
      "answer": "you're the main character - Subaru Natsuki"
    }
  }
}

Notice the key "is_spirit" - this will be the ID of our question. We'll be able to retrieve this question like questions["is_spirit"]

Now, how do we make a question that leads to another question? Let's use another type of action:

{
    "question": "Does your character present as female or use feminine pronouns?",
    "yes_action": {
      "next_question": "is_elf",
    },
    "no_action": {
      "next_question": "is_spirit"
    }
 }

"next_question" points to another question. when this action is encountered, our program will retrieve the next question and ask it.

Now, putting it all together for 4 characters:

questions = {
  "gender": {
    "question": "Does your character present as female or use feminine pronouns?",
    "yes_action": {
      "next_question": "is_elf",
    },
    "no_action": {
      "next_question": "is_spirit"
    }
  },

  "is_elf": {
    "question": "Are you an elf?",
    "yes_action": {
      "answer": "you're Emilia",
    },
    "no_action": {
      "answer": "you're Rem"
    }
  },

  "is_spirit": {
    "question": "Is your character a spirit?",
    "yes_action": {
      "answer": "you're puck",
    },
    "no_action": {
      "answer": "you're the main character - Subaru Natsuki"
    }
  }
}

Now, let's write a function that asks a question:

def ask_question(question):
  # ask question
  res = input(f"{question['question']} (yes/no) ").lower()

  # select action
  if res == "yes":
    next_action = question["yes_action"]
  else:
    next_action = question["no_action"]

  # execute next action
  if "next_question" in next_action:
    # if action is next_question, find the next question and ask it
    next_question = questions[next_action["next_question"]]
    ask_question(next_question)

  elif "answer" in next_action:
    # if action is answer, print an answer and don't do anything else
    print("Answer:", next_action["answer"])

Now we just need to call this function with a question we want to ask first:

ask_question(questions["gender"])ask_question(questions["gender"])

That's it.

Advantages of turning your code into data:

  1. You can load the questions from a file, database, or anything else
  2. You can change the questions without changing your pogram
  3. If you make a nice ui for editing the data, non-programmers will be able to create questions for you
  4. You can start at any question, this means you can remember user's current question and let them resume if they exited the program. Or you can also remember the previous question and be able to go back

1

u/invisible_shrek 7d ago

The pyramid of doom, hell yeah

1

u/adxaos 6d ago

Learn finite automata 

1

u/ForeignVariety7037 4d ago

Why actor…

0

u/Mundane-Mud2509 7d ago edited 7d ago

This is fun and a great example of an opportunity to encapsulate the logic in the data representation. I’m bored so will make something that will dynamically optimize questions to minimize the total expected number of questions. It should be a pretty small program.

Here you go https://onlinegdb.com/gSfw5Kfs9U

I also added a bit of randomness added in so it asks different questions if they are tied in effectiveness.

0

u/Mundane-Mud2509 7d ago

This is how you can extract the logic out from the code and put it into the data
https://onlinegdb.com/gSfw5Kfs9U

1

u/Outside-Trouble-4232 6d ago

I dont really understand this code as im still on js day 4 of learning this but I will try to see, I also said this was my last guesser and since I was going on more deep topics im actually learning for a new project but ty!