Created
April 19, 2014 05:02
-
-
Save anonymous/11074621 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/python2 | |
# The goal of this is to take questions that are mapped to answers | |
# and then map each question to a permutation of n answers, including the correct one | |
# then iterate through each of these mappings and ask the user to select an answer, record whether it was correct or not | |
# repeat the questions "infinitely" until the user hits EOF, i.e. ctrl+d | |
from random import random | |
from sys import exit | |
from itertools import chain, repeat | |
# this is simply a concise way of writing 'accessor' functions for pairs | |
# I could have also used a normal function to do the same thing with index notation, but this is more concise and nice looking I think | |
# note that _ here is just another variable name, I call it _ to make it clear it is ignored | |
fst = lambda (a, _): a | |
snd = lambda (_, b): b | |
def shuffle(answers): | |
# What this does is create a list of pairs | |
# each pair is a random number (between 0 and 1) and an element of the list to be shuffled | |
# the syntax being used here is called a list comprehension, basically it allows you to do | |
# what a for loop would do except more concisely, and it creates a list for you | |
# e.g. [x for x in xs] just copies the list 'xs', and you can put any python expression in place of the first x | |
randomized = [(random(), answer) for answer in answers] | |
# what this does is it takes the list of randomized pairs and sorts it according to the random element | |
# key=fst is a way of saying that the key function, that is, the function used by 'sorted' to extract the element to be compared | |
# the key function is the function 'fst' which we defined earlier | |
# the call to map here simply gives you the second element of each pair, map takes a function and applies it to each element | |
# of the list and returns the result as a new list with the results of each function call in place of the old elements | |
# e.g. map(plus2, [1,2,3,4]) would give you [3,4,5,6] assuming we had a function called plus2 which just adds 2 to whatever you give it | |
return map(snd, sorted(randomized, key=fst)) | |
def permute_question(n, mapped_question, other_answers): | |
# this function simply shuffles around the possible answers to a question | |
question, correct_answer = mapped_question | |
# it might appear that this could result in an IndexError, but python slicing actually doesn't care if you do that | |
# it will just return the entire list | |
return (question, correct_answer, shuffle([correct_answer]+other_answers[0:n])) | |
def request_answer(max_amount): | |
# The goal here is to try to parse the input into an int type | |
# the % (blah, blargh) syntax is just a way of substituting in values to a string | |
# the "%s" stuff in the string gets substituted with whatever comes after the % in that order | |
try: | |
try: | |
selection = int(raw_input("Select an answer from %s to %s: " % (0, max_amount))) | |
except EOFError: | |
# if we get EOF just print a message and quit | |
print "Quitting..." | |
exit(0) # 0 signifies no errors | |
if selection > max_amount: # check that the integer is withing the bounds of possible answers | |
print "You did not select an answer within the correct boundary" | |
# re-request it until they do! | |
return request_answer(max_amount) | |
return selection | |
except ValueError: | |
print "Please enter a decimal integer with no other characters (you can enter spaces if you want)" | |
# re-request it until they enter an integer! | |
return request_answer(max_amount) | |
def ask(question): | |
# this simply takes a tuple (which is like a fixed size list) | |
# and it assigns names (variables) for each of the elements of the tuple | |
# for example a, b, c = (1,2,3) | |
# is equivalent to: | |
# triple = (1,2,3) | |
# a = triple[0] | |
# b = triple[1] | |
# c = triple[2] | |
# so it is just convenient syntax | |
text, correct_answer, possible_answers = question | |
print text | |
# enumerate gives us the index as well as the item | |
for n, answer in enumerate(possible_answers): | |
print "%s: %s" % (n, answer) | |
selection = request_answer(len(possible_answers)-1) | |
if correct_answer == possible_answers[selection]: | |
print "Correct! The answer is %s" % correct_answer | |
return True | |
print "False! The correct answer is %s" % correct_answer | |
return False | |
def parse_questions(input_string): | |
parsed = [] | |
for line in input_string: | |
splitted = line.split("=") # questions are separated from answers by = | |
if len(splitted) != 2: | |
raise ValueError("Lines must be in the format of question=answer where neither question or answer contains =") | |
splitted[1] = splitted[1][0:-1] # remove the trailing newline | |
parsed.append(splitted) | |
return parsed | |
with open("./test_questions", "r") as question_file: | |
# test_questions is a plain text file in the form of | |
# question=answer\nquestion2=answer2\nquestion3=ansswer3 | |
# and so on with however many questions you want (\n represents a newline character fyi) | |
# parse in the question file and shuffle around the questions and answers | |
questions = shuffle(parse_questions(question_file.readlines())) | |
# get a list of all possible answers to any question in the file | |
# turn it into a "set" so we can use the different method | |
all_answers = set(map(snd, questions)) | |
n = 12 | |
# chain.from_iterable(list) gives you a flattened list | |
# i.e. if list were [[1,2,3], [4,5,6]] it would return [1,2,3,4,5,6] | |
# repeat just repeats the list forever | |
# these work because the result is not evaluated right away | |
# you essentially get the results on-demand | |
for question, answer in chain.from_iterable(repeat(questions)): | |
other_answers = list(all_answers.difference(set([answer]))) | |
ask(permute_question(n, (question, answer), other_answers)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment