LostCoder
LostCoder

Reputation: 11

How do I check if an answer is in a 2D list

blueprint = [[1,"A"], [2,"C"], [3,"B"], [4,"D"], [5,"A"], [6,"A"], [7,"B"], [8,"A"], [9,"C"], [10,"A"], [11,"D"], [12,"A"], [13,"C"], [14,"C"]
         ,[15,"B"], [16,"A"], [17,"B"], [18,"A"], [19,"C"], [20,"D"]]


def check_answer(students_answer):
    points = 0
    total = 20
    if students_answer[0]==blueprint[0][1]:
        points =+ 1
    elif students_answer[1]==blueprint[1][1]:
        points =+ 1
#etc.

    else:
        points =+ 0
    score = (points*100)/(total)
    return score

print(check_answer(["A", "C"]))

Why doesn't my function calculate the % of right answers for longer than answer 1, which is "A"?

Upvotes: 0

Views: 67

Answers (3)

deadvoid
deadvoid

Reputation: 1300

Why doesn't my function calculate the % of right answers for longer than answer 1, which is "A"?

Let's take a look at your data & function

# data
blueprint = [[1,"A"], [2,"C"], [3,"B"], [4,"D"], [5,"A"], [6,"A"], [7,"B"], [8,"A"], [9,"C"], [10,"A"], [11,"D"], [12,"A"], [13,"C"], [14,"C"], [15,"B"], [16,"A"], [17,"B"], [18,"A"], [19,"C"], [20,"D"]]

# function call
print(check_answer(["A", "C"]))

first list in blueprint is [1,"A"]. the check_answer() argument is ["A", "C"]. When the line in the loop here runs, it found what it's looking for

if students_answer[0]==blueprint[0][1]:    # students_answer[0] is "A", blueprint[0][1] is "A", too
    points =+ 1
elif students_answer[1]==blueprint[1][1]:
    points =+ 1
#etc.

that means it skips all the elifs & else, straight to calculating score. That's why score only contains the first "A".

one approach you can do is to use zip(*blueprint) to unpack the lists inside blueprint, into this

[(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20),
('A', 'C', 'B', 'D', 'A', 'A', 'B', 'A', 'C', 'A', 'D', 'A', 'C', 'C', 'B', 'A', 'B', 'A', 'C', 'D')]

then loop on that to count the grades.

so,

scorelist = list(zip(*blueprint))
total = len(scorelist[1])
answer_list = ["A", "C"]
first_a, second_a = answer_list
points = 0

for sc in scorelist[1]:
    if sc == first_a or sc == second_a:
        points += 1

score = (points*100)/(total)
print(score)

or you can even just joined all the scores strings & use str.count()

joined_scores = ''.join(scorelist[1])
print(joined_scores)
# 'ACBDAABACADACCBABACD'

points = joined_scores.count(first_a) + joined_scores.count(second_a)
print(points*100/total)
# 65.0

Upvotes: 1

blhsing
blhsing

Reputation: 106465

The first items in the tuples in your blueprint list are redundant because they are simply the indices of their respective tuples plus one. You should make it a simple list of strings instead:

blueprint = ['A', 'C', 'B', 'D', 'A', 'A', 'B', 'A', 'C', 'A', 'D', 'A', 'C', 'C', 'B', 'A', 'B', 'A', 'C', 'D']

so that you can calculate the percentage of right answers in student_answer with a zip of the two lists like this:

sum(1 for s, b in zip(student_answer, blueprint) if s == b) / len(student_answer) * 100

Upvotes: 1

Jean-François Fabre
Jean-François Fabre

Reputation: 140168

I don't get why you need to recall the list index in blueprint but if the data are like this, you could just zip the data together, unpack, and compare.

This way of doing it is really unefficient. What if you have 100 questions? will you copy/paste 100 times your (wrong) elif statements?

Score 1 for success, 0 for fail, divide by total and multiply by 100, in a generator comprehension fed to sum:

def check_answer(students_answer):
    return 100*(sum(correct==attempt for (_,correct),attempt in zip(blueprint,students_answer))/len(blueprint))

Upvotes: 1

Related Questions