自动化无聊的东西:随机测验生成器

时间:2018-10-20 08:43:23

标签: python python-3.x

我一直在遵循一本教程书中的示例程序,该程序是获取一本包含美国所有50个州及其首都的字典,然后创建一个随机的多选AD问题集,然后将这些问题作为随机和3个不同的测验打印出3个不同的文件。然后将每个测验中所有问题的答案打印到答案文件中,以与每个问题文件一起使用。

作为测试,我现在仅以5的范围进行测试。当我运行程序时,程序会按预期运行,但每次测试仅创建25个问题/答案组合,而不是50个。

我已经检查了几次,不知道为什么会这样。任何输入将不胜感激,谢谢。

# randomQuizGenerator.py - Creates quizzes with questions and answers in
# random order, along with the answer key.

import random

capitals = {'Alabama': 'Montgomery', 'Alaska': 'Juneau', 'Arizona': 'Phoenix',
        'Arkansas': 'Little Rock', 'California': 'Sacramento', 'Colorado': 'Denver',
        'Connecticut': 'Hartford', 'Delaware': 'Dover', 'Florida': 'Tallahassee',
        'Georgia': 'Atlanta', 'Hawaii': 'Honolulu', 'Idaho': 'Boise', 'Illinois':
        'Springfield', 'Indiana': 'Indianapolis', 'Iowa': 'Des Moines', 'Kansas':
        'Topeka', 'Kentucky': 'Frankfort', 'Louisiana': 'Baton Rouge', 'Maine':
        'Augusta', 'Maryland': 'Annapolis', 'Massachusetts': 'Boston', 'Michigan':
        'Lansing', 'Minnesota': 'Saint Paul', 'Mississippi': 'Jackson', 'Missouri':
        'Jefferson City', 'Montana': 'Helena', 'Nebraska': 'Lincoln', 'Nevada':
        'Carson City', 'New Hampshire': 'Concord', 'New Jersey': 'Trenton',
        'New Mexico': 'Santa Fe', 'New York': 'Albany', 'North Carolina': 'Raleigh',
        'North Dakota': 'Bismarck', 'Ohio': 'Columbus', 'Oklahoma': 'Oklahoma City',
        'Oregon': 'Salem', 'Pennsylvania': 'Harrisburg', 'Rhode Island': 'Providence',
        'South Carolina': 'Columbia', 'South Dakota': 'Pierre', 'Tennessee':
        'Nashville', 'Texas': 'Austin', 'Utah': 'Salt Lake City', 'Vermont':
        'Montpelier', 'Virginia': 'Richmond', 'Washington': 'Olympia',
        'West Virginia': 'Charleston', 'Wisconsin': 'Madison', 'Wyoming': 'Cheyenne'}

# Generate 5 quiz files.
for quizNum in range(5):
    # Create the quiz and answer key files.
    quizFile = open('capitalsquiz%s.txt' % (quizNum+1), 'w')
    answerFile = open('capitalsquiz_answers%s.txt' % (quizNum+1), 'w')

    # Write out the header for the quiz.
    quizFile.write('Capitals Quiz #%s' % (quizNum+1) + '\nName:\nDate:\n\n')
    quizFile.write('What is the capital of:\n')
    answerFile.write('Capitals Quiz %s' % (quizNum+1) + '\n\n')

    # Shuffle the order of the states.
    states = list(capitals.keys())
    random.shuffle(states)

    # Loop through all 50 states, making a question for each.
    # set question number = 0
    q_num = 0
    for st in states:
        # question number increase
        q_num += 1
        random.shuffle(states)

        # unused needed for choosing 3 incorrect options
        unusedStates = states

        # write question number and state name (QUESTION)
        quizFile.write('Q%s: ' % q_num + st + '?\n')

        # create answer options list and fill with 1 correct answer + 3 incorrect ones
        answerOptions = [None] * 3
        answerOptions.append(capitals[st])
        # remove correct answer to avoid duplication
        unusedStates.remove(st)
        for Opt in range(0, 3):
            curr_ans = unusedStates[Opt]
            answerOptions[Opt] = capitals[curr_ans]
        # randomise answer list
        random.shuffle(answerOptions)
        # write answers
        for i in range(0, 4):
            quizFile.write(answerOptions[i]+'   ')
        quizFile.write('\n')

        # write correct answer in answer file
        answerFile.write(capitals[st]+'\n')

    quizFile.close()
    answerFile.close()

3 个答案:

答案 0 :(得分:1)

@hlfrmn找到了代码罪魁祸首-我想指出另一件事-使用

with open("filename.txt","w") as f:
    f.write("something")

一种方法可以自动关闭文件,即使您遇到异常,也可以使用执行某些任务的功能对其进行结构化。

数据定义:

capitals = {'Alabama': 'Montgomery', 'Alaska': 'Juneau', 'Arizona': 'Phoenix',
        'Arkansas': 'Little Rock', 'California': 'Sacramento', 'Colorado': 'Denver',
        'Connecticut': 'Hartford', 'Delaware': 'Dover', 'Florida': 'Tallahassee',
        'Georgia': 'Atlanta', 'Hawaii': 'Honolulu', 'Idaho': 'Boise', 'Illinois':
        'Springfield', 'Indiana': 'Indianapolis', 'Iowa': 'Des Moines', 'Kansas':
        'Topeka', 'Kentucky': 'Frankfort', 'Louisiana': 'Baton Rouge', 'Maine':
        'Augusta', 'Maryland': 'Annapolis', 'Massachusetts': 'Boston', 'Michigan':
        'Lansing', 'Minnesota': 'Saint Paul', 'Mississippi': 'Jackson', 'Missouri':
        'Jefferson City', 'Montana': 'Helena', 'Nebraska': 'Lincoln', 'Nevada':
        'Carson City', 'New Hampshire': 'Concord', 'New Jersey': 'Trenton',
        'New Mexico': 'Santa Fe', 'New York': 'Albany', 'North Carolina': 'Raleigh',
        'North Dakota': 'Bismarck', 'Ohio': 'Columbus', 'Oklahoma': 'Oklahoma City',
        'Oregon': 'Salem', 'Pennsylvania': 'Harrisburg', 'Rhode Island': 'Providence',
        'South Carolina': 'Columbia', 'South Dakota': 'Pierre', 'Tennessee':
        'Nashville', 'Texas': 'Austin', 'Utah': 'Salt Lake City', 'Vermont':
        'Montpelier', 'Virginia': 'Richmond', 'Washington': 'Olympia',
        'West Virginia': 'Charleston', 'Wisconsin': 'Madison', 'Wyoming': 'Cheyenne'}

和代码:

import random

def generateAllQuestions(caps):
    """Generates all questions including 3 wrong answers. Returns a list of
     [tuple(state,correct) and list of 3 wrong answers]."""
    q = []
    for state in capitals:
        # get 4 other answers 
        # remove the correct one if it is inside the random sample
        # use only 3 of them
        others = [ val for key,val in random.sample(capitals.items(),k=4) if key != state][0:3]

        # compile [tuple: (item,correct_answer),[other_answers]]
        q.append([(state,capitals[state])] + [others])

    return q

def partitionIntoNParts(n,data):
    """Takes the data and partiniones it into n random equally long (if possible)
    sublists"""
    ld = len(data)
    size_part = ld // n
    idx = 0
    random.shuffle(data)
    while idx < ld:
        yield data[idx:idx + size_part]
        idx += size_part

def writeHeader(f,a,n):
    """Write the header for Q and A file"""
    a.write(f"Capitals Quiz #{n+1}\n\n")
    f.write(f"Capitals Quiz #{n+1}\nName:\nDate:\n\nWhat is the capital of:\n")

def writeQandA(f,a,q_num,q):
    """Write a single questions into Q-file and a single answer into A-file"""
    state,correct = q[0] # the tuple
    others = q[1]        # the others

    a.write(f"{q_num+1:>3}.) {state:<14} : {correct}\n")
    f.write(f"{q_num+1:>3}.) {state:<14} : ")
    solutions = others + [correct]
    random.shuffle(solutions) # use sort() to always get alphabetical order
    for town in solutions:
        f.write(f"[ ] {town:<14}    ")
    f.write("\n\n")


# how many files to use?
filecount = 5

qs = generateAllQuestions(capitals)

parts = partitionIntoNParts(filecount,qs)

# write files based on partioning 
for idx,content in enumerate(parts):
    with open(f"capitalsquiz{idx+1}.txt","w") as quiz_file,\
        open(f"capitalsquiz{idx+1}_answers.txt","w") as answ_file:

        writeHeader(quiz_file,answ_file,idx)
        # write Q and A into file
        for q_num,q in enumerate(content):
            writeQandA(quiz_file,answ_file,q_num,q)

# check one files content:
print(open("capitalsquiz2.txt").read())
print(open("capitalsquiz2_answers.txt").read())

capitalsquiz2.txt的内容:

Capitals Quiz #2
Name:
Date:

What is the capital of:
  1.) Oklahoma       : [ ] Oklahoma City     [ ] Phoenix           [ ] Juneau            [ ] Olympia

  2.) Virginia       : [ ] Austin            [ ] Pierre            [ ] Saint Paul        [ ] Richmond

  3.) North Carolina : [ ] Raleigh           [ ] Tallahassee       [ ] Dover             [ ] Harrisburg

  4.) Montana        : [ ] Helena            [ ] Raleigh           [ ] Hartford          [ ] Madison

  5.) Alaska         : [ ] Nashville         [ ] Albany            [ ] Juneau            [ ] Lansing

  6.) Kentucky       : [ ] Charleston        [ ] Cheyenne          [ ] Frankfort         [ ] Oklahoma City

  7.) Florida        : [ ] Trenton           [ ] Pierre            [ ] Tallahassee       [ ] Honolulu

  8.) Rhode Island   : [ ] Providence        [ ] Madison           [ ] Santa Fe          [ ] Trenton

  9.) Arkansas       : [ ] Boston            [ ] Little Rock       [ ] Harrisburg        [ ] Denver

 10.) Wisconsin      : [ ] Montgomery        [ ] Pierre            [ ] Madison           [ ] Richmond

capitalsquiz2_answers.txt`的内容:

Capitals Quiz #1

  1.) Oklahoma       : Oklahoma City
  2.) Virginia       : Richmond
  3.) North Carolina : Raleigh
  4.) Montana        : Helena
  5.) Alaska         : Juneau
  6.) Kentucky       : Frankfort
  7.) Florida        : Tallahassee
  8.) Rhode Island   : Providence
  9.) Arkansas       : Little Rock
 10.) Wisconsin      : Madison

答案 1 :(得分:1)

发生这种情况的原因是,您在迭代集合时正在修改它:

states = [1,2,3,4,5,6,7,8,9,10]
for st in states:
    print(st)
    states.remove(st)

此代码段将打印出来:

1
3
5
7
9

您尝试过的是:

unusedStates = states
unusedStates.remove(st)

,但这不会复制列表。它将为同一列表创建另一个名称。

这里是一个略有变化的版本,但我绝不是“ Python专业人士”。

import random

capitals = {'Alabama': 'Montgomery', 'Alaska': 'Juneau', 'Arizona': 'Phoenix',
            'Arkansas': 'Little Rock', 'California': 'Sacramento', 'Colorado': 'Denver',
            'Connecticut': 'Hartford'}
states = list(capitals.keys())

random.shuffle(states)

# Loop through all 50 states, making a question for each.

for idx, state in enumerate(states):
    # use this for 1-based humans
    q_num = idx + 1

    # the 49 other states
    other_states = states[:idx] + states[idx+1:]
    # pick 3 states (guaranteed to be unique)
    answer_states = random.sample(other_states, 3)
    # add the correct one
    answer_states.append(state)

    # convert states to capitals
    answer_options = [capitals[st] for st in answer_states]

    # randomise answer list
    random.shuffle(answer_options)

    print('Question %s about %s' % (q_num, state))
    print('Options', answer_options)
    print('Correct Answer', capitals[state])
    print() #empty line

请注意使用random.sample来选择3个唯一选项,并使用enumerate遍历带有索引变量的列表。

还请注意使用“切片”创建了一个49个元素的列表。

答案 2 :(得分:0)

呵呵...我也很有趣地重组了您的程序。也许您可以从中学到一两个东西。

import random

capitals = {'Alabama': 'Montgomery', 'Alaska': 'Juneau', 'Arizona': 'Phoenix',
        'Arkansas': 'Little Rock', 'California': 'Sacramento', 'Colorado': 'Denver',
        'Connecticut': 'Hartford', 'Delaware': 'Dover', 'Florida': 'Tallahassee',
        'Georgia': 'Atlanta', 'Hawaii': 'Honolulu', 'Idaho': 'Boise', 'Illinois':
        'Springfield', 'Indiana': 'Indianapolis', 'Iowa': 'Des Moines', 'Kansas':
        'Topeka', 'Kentucky': 'Frankfort', 'Louisiana': 'Baton Rouge', 'Maine':
        'Augusta', 'Maryland': 'Annapolis', 'Massachusetts': 'Boston', 'Michigan':
        'Lansing', 'Minnesota': 'Saint Paul', 'Mississippi': 'Jackson', 'Missouri':
        'Jefferson City', 'Montana': 'Helena', 'Nebraska': 'Lincoln', 'Nevada':
        'Carson City', 'New Hampshire': 'Concord', 'New Jersey': 'Trenton',
        'New Mexico': 'Santa Fe', 'New York': 'Albany', 'North Carolina': 'Raleigh',
        'North Dakota': 'Bismarck', 'Ohio': 'Columbus', 'Oklahoma': 'Oklahoma City',
        'Oregon': 'Salem', 'Pennsylvania': 'Harrisburg', 'Rhode Island': 'Providence',
        'South Carolina': 'Columbia', 'South Dakota': 'Pierre', 'Tennessee':
        'Nashville', 'Texas': 'Austin', 'Utah': 'Salt Lake City', 'Vermont':
        'Montpelier', 'Virginia': 'Richmond', 'Washington': 'Olympia',
        'West Virginia': 'Charleston', 'Wisconsin': 'Madison', 'Wyoming': 'Cheyenne'}

quiz_answer_template = '''\
Capitals Quiz #{}

{}
'''

quiz_file_template = '''\
Capitals Quiz #{}
Name:
Date:

What is the capital of?
{}
'''

question_template = '''\
Q{} {}?
{}
'''

def create_answer_file(path, question_id, answers):
    with open(path, 'w') as f:
        s = quiz_answer_template.format(question_id, answers)
        f.write(s)

def create_quiz_file(path, question_id, question_and_options):
    with open(path, 'w') as f:
        s = quiz_file_template.format(question_id, question_and_options)
        f.write(s)

def get_quiz(dictionary, n):
    """Based on a dictionary with key and values will return 
      1) Questions with 4 options tab-separated as a string
      2) Correct answers as a string
      """
    output = []

    states = list(dictionary.keys())
    random.shuffle(states)  
    correct_answers = [dictionary.get(i) for i in states]

    for ind, st in enumerate(states[:n], 1):
        d = dictionary.copy()
        correct_answer = d.pop(st)
        incorrect_answers = list(d.values())
        random.shuffle(incorrect_answers)  
        options = [correct_answer] + incorrect_answers[:3]
        random.shuffle(options)
        output.append(question_template.format(ind, st, '\t'.join(options)))

    return '\n'.join(output), '\n'.join(correct_answers)

for quizNum in range(1, 6):
    questions_and_options, answers = get_quiz(capitals, n=50)
    create_quiz_file(f'capitalsquiz{quizNum}.txt', quizNum, questions_and_options)
    create_answer_file(f'capitalsquiz_answers{quizNum}.txt', quizNum, answers)