1

I'm making a quiz of yes/no questions where answering yes/no depending on the question rewards a different amount of points, which after each question will be added to a total and displayed at the end.

However, there are around 50 questions in the quiz, and this would mean a mountain of if/else statements. Is there a way I can use a dictionary and a loop or something similar to significantly reduce the length of the program?

edit This repeated many times is what I'm trying to avoid. I'm thinking of adding a variable i and adding 1 to it after each question, and looking up the index of the next question. But is this only possible with a list?

print "The following are y/n questions."
total = 0 

q1 = raw_input("Do you exercise daily? ")
if q1 == "y":
    total += 1
else:
    total = total

print total
Ryan Werner
  • 177
  • 3
  • 5
  • 13
  • 2
    Please show us what you have tried so far! – Klaus D. Jan 11 '16 at 15:13
  • 2
    Where do you invision this massive if/else statement? Example code would help here – Sayse Jan 11 '16 at 15:13
  • 2
    Please add some code to improve your question. What ideas do you have? What kind of structure were you thinking? What have you started with? – Andy Jan 11 '16 at 15:13
  • 1
    Possible duplicate of [Replacements for switch statement in Python?](http://stackoverflow.com/questions/60208/replacements-for-switch-statement-in-python) – cat Jan 11 '16 at 15:13
  • There are a lot of dictionary-related solutions in that question; it's basically the same. – cat Jan 11 '16 at 15:14
  • If i'm understanding you right, this should be easy. Just set your dictionary up like this: test_answers = {'questionid/name': {'yes': 50, 'no': 25}}. Then accumulate points with something like: num_points += test_answers[questionid/name][question_answer] – disflux Jan 11 '16 at 15:15
  • @disflux - Dictionaries aren't replacements for classes... but if you think that is the answer to this question then you should add it as an answer. – Sayse Jan 11 '16 at 15:16
  • @Sayse I don't see anything in the OP looking for a class, but specifically looking for a dictionary-based answer – disflux Jan 11 '16 at 15:26

6 Answers6

3

Create a list of dictionaries. Each element is a question and the points for yes and no. You can then easily iterate over the list.

qa = [{"question": "Do you exercise?", "yes": 10, "no": 0},
       "question": "Do you smoke?", "yes": -10, "no": 0},
       ...
     ]
for item in qa.items():
    answer = raw_input("Do you exercise daily? ")
    score = item.get(answer)
    total = total + score

Of course, you'll need to add some additional code to handle the case where the user doesn't answer literally "yes" or "no", but that doesn't affect this solution. The point is, you create an object that represents a question, and the possible answers with scores, and then you iterate over a list of those objects.

You could even go a step further and create a custom class. You could do it like this, for example:

class Question(object):
    def __init__(self, question, yes=0, no=0):
        self.question = question
        self.yes = yes
        self.no = no

questions = [Question("Do you exercise?", yes=10, no=0),
             Question("Do you smoke?", yes=0, no=-10),
             ...
            ]

for question in questions:
    answer = raw_input(question.question)
    ...
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
3

At the lowest level, with your given example, all you really need is a list of questions to ask and then just loop over this

print "The following are y/n questions."
total = 0 

questions = ["Do you exercise daily? ", "Is this a second question?"]

for question in questions:
    q1 = raw_input(question)
    if q1 == "y":
        total += 1

print total

Of course this can be expanded to include a proper object class and so on..

I was thinking of using this approach, however, how would I tie different points values to each question? One question may be worth six, while another may be worth four. Could I make a second list containing the point values?

You make a question class and then make the list a list of these answers

class Question()
    def __init__(self, text, correct_answer_value)
        this.text = text
        this.value = correct_answer_value

print "The following are y/n questions."
total = 0 

questions = [Question("Do you exercise daily? ",1), Question("Is this a second question?",2)]

for question in questions:
    q1 = raw_input(question.text)
    if q1 == "y":
        total += question.value

print total
Sayse
  • 42,633
  • 14
  • 77
  • 146
  • I was thinking of using this approach, however, how would I tie different points values to each question? One question may be worth six, while another may be worth four. Could I make a second list containing the point values? – Ryan Werner Jan 11 '16 at 15:55
  • @RyanWerner - I've extended my answer – Sayse Jan 11 '16 at 15:58
  • I'm getting a strange error. It's saying that __init__ takes exactly two arguments, but that three were given. Two arguments are being given though. – Ryan Werner Jan 11 '16 at 16:23
  • 1
    @RyanWerner - I forgot to include `self` in here, fixed! – Sayse Jan 11 '16 at 16:24
1
# Firstly, declare your questions. Create it with their answer and associated score.
questions = {}
questions[1] = {}
questions[1]["question"] = "Is the sky blue? Y/N"
questions[1]["answer"] = True
questions[1]["score"] = 50

# We can add more questions
questions[2] = {}
questions[2]["question"] = "Is Python a programming language? Y/N"
questions[2]["answer"] = True
questions[2]["score"] = 150

# Set the initial score at 0
score = 0

# Loop over the questions
for key in questions:
    user_answer = None

    # We ask the question till the user answer Yes or Not
    while user_answer not in ["Y","N"]:
        user_answer = raw_input(questions[key]["question"])

    # If the user said Yes we keep True, if he said No we keep False
    user_answer = True if user_answer == "Y" else False 

    # We increment the score if the answer is the same that it's stored in your dictionary
    score += questions[key]["score"] if user_answer == questions[key]["answer"] else 0

print "Final score {0}".format(score)
Luis González
  • 3,199
  • 26
  • 43
  • 1
    It would be easier, given the amount of questions he's asking (50), to create the dictionary entries with a function, rather than declaring each one individually. That is assuming you want to keep your current 4-line/question format. Otherwise, you're looking at 200 lines of code just for the questions declaration. – disflux Jan 11 '16 at 15:41
  • @disflux I agree with you. I have written the easiest solution but is not the best way for declaring the questions. You are invited to edit my post if you think you could improve it! – Luis González Jan 11 '16 at 15:46
1

A bit of set-up code, like

def get_yesno(prompt):
    while True:
        response = raw_input(prompt).strip().lower()
        if response in {'y', 'yes'}:
            return True
        elif response in {'n', 'no'}:
            return False
        else:
            print("Please respond with yes or no.")

class YesNo:
    __slots__ = ('question', 'yes_points', 'no_points')

    def __init__(self, question, yes_points=1, no_points=0):
        self.question = question
        self.yes_points = yes_points
        self.no_points = no_points

    def ask(self):
        if get_yesno(self.question):
            return self.yes_points
        else:
            return self.no_points

means that you can easily define questions like

questions = [
    YesNo("Do you exercise daily? "),
    YesNo("Do you have more than 3 drinks a week? ", -5, 2)
]

and then your main program becomes

def main():
    score = sum(q.ask() for q in questions)
    print("Your score was {}".format(score))

if __name__ == "__main__":
    main()
Hugh Bothwell
  • 55,315
  • 8
  • 84
  • 99
0

Add your questions to a list. (Lists)

Then simply use:

for question in questionList:
    q1 = raw_input(question)
    if q1 == "y":
        total += 1
    else:
        total = total
print total
Mayuso
  • 1,291
  • 4
  • 19
  • 41
0

You specifically mention that you would like to use a dictionary, so this answer will provide a solution as to how to do that.

If you are only expecting answers to be 'yes'/'no', then you can setup your dictionary as follows:

test_dict = {'question1': {'yes': 100, 'no': 50}, 
             'question2': {'yes': 75, 'no': 25}}

You can then ask questions, grab their answers, and pass them through the dictionary to accumulate their points.

question1_ans = raw_input("Is your favorite animal a Rhino?").lower()

num_points += test_dict['question1'][question1_ans]

In that case, if you answer 'yes', then num_points will be 100. Else, answering no will result in num_points being 50.

Obviously this doesn't prevent them from answering something like: "FOO", instead of 'yes'/'no', which would result in a KeyError.

disflux
  • 429
  • 3
  • 12