Necesito ayuda con una calculadora de calificación ponderada, tengo los bits que necesito para calcular los datos y los promedios ponderados. Mi problema es importar los datos y almacenarlos. Creo que necesito usar listas, pero no estoy seguro de cómo separar cada entrada, sé que puedo usar .split () y probablemente lo haré. Pero mi verdadero problema es descubrir cómo almacenar estos valores y luego escribir en un archivo de salida.

Así es como se verá el archivo .txt para la entrada que estoy importando a mi programa con un comando "open (" score.txt "," r ")"

Babbage, Charles
10.0   9.5    8.0  10.0
 9.5  10.0    9.0
85.0  92.0   81.0
Turing, Alan
10.0   8.0    6.0
10.0  10.0    9.0   9.5
90.0  92.0   88.5
Hopper, Grace
10.0  10.0    8.0
10.0  10.0    9.0   9.5
90.0  92.0   88.0
Van Rossum, Guido
 7.5   8.5
 7.5   8.5    6.0   9.0
68.0  81.0   70.0
Backus, John
 9.5   9.5   10.0   8.0   9.5  10.0
 7.5   8.5    6.0   9.0  10.0
99.0  93.0  100.0
Crawley, Bryan
 6.0
 7.5
70.0  60.0   55.5

Intenté usar s.isdigit y s.isalpha y eso realmente no funcionó. La primera línea son cuestionarios, la segunda línea son proyectos y la tercera son exámenes. El número de pruebas y exámenes es arbitrario, los exámenes siempre tendrán tres.

Así es como debe verse la salida:

Babbage, Charles      89.4   B
Turing, Alan          91.3   A
Hopper, Grace         92.7   A
Van Rossum, Guido     75.5   C
Backus, John          94.4   A
Crawley, Bryan        63.9   D

Así es como se ve mi código ahora:

quiz_scores = []

while True:
    score = float(input("Quiz #{} ----- ".format(len(quiz_scores)+1)))
    if score == -1:
        break
    quiz_scores.append(score)
quiz_total = sum(quiz_scores) - min(quiz_scores)
if len(quiz_scores)>1:
    quiz_avg =  (quiz_total/((len(quiz_scores))-1)*10)
else:
    quiz_avg = (quiz_total/(len(quiz_scores)*10)

print()

project_scores = []

while True:
    score2 = float(input("Project #{} -- ".format(len(project_scores)+1)))
    if score2 == -1:
        break
    project_scores.append(score2)

project_total = sum(project_scores)
project_avg = (project_total/(len(project_scores))*10)

print()

exam1 = float(input("Exam #1 ----- "))
exam2 = float(input("Exam #2 ----- "))


print()

final = float(input("Final Exam -- "))

average = ((quiz_avg*.15)+(project_avg*.20)+(exam1*.20)+(exam2*.20)+(final*.25))

print("Average ---- %.2f" % average)



if 90 <= average <= 100:
    print("Grade ------- A")
if 80 <= average < 90:
    print("Grade ------- B")
if 70 <= average < 80:
    print("Grade ------- C")
if 60 <= average < 70:
    print("Grade ------- D")
if 0 <= average < 60:
    print("Grade ------- F")

Definitivamente busca aprender aquí, no solo copiar y pegar lo que comenta; así que tengan paciencia conmigo si tengo algunas preguntas para ustedes.

Gracias a todos, esta comunidad ha sido muy útil.

0
JediObiJohn 31 oct. 2017 a las 07:09

3 respuestas

La mejor respuesta

Espero que puedas entender lo que se ha hecho aquí ... si tienes alguna pregunta, házmelo saber.

gradebook={}
input_name = input("Enter input file:")
output_name = input("Enter input file:")

with open(input_name,"r") as file:
    for line in file:
        if line[0].isalpha():
            gradebook[line.strip()] = {'quizzes':next(file).strip().split(' '), 
                                        'projects':next(file).strip().split(' '), 
                                        'tests':next(file).strip().split(' ')
                                        }
for student, values in gradebook.items():
    quizzes = []
    projects = []
    tests = []
    for category, grades in values.items():
        for grade in grades:
            if grade != '':
                exec("%s.append(float(grade))"% category)
                # ^^^ THIS IS THE SAME AS THE FOLLOWING 
                #if category == 'quizzes':
                #   quizzes.append(float(grade))
                #if category == 'projects':
                #   projects.append(float(grade))
                #if category == 'tests':
                #   tests.append(float(grade))

    quiz_total = sum(quizzes) - min(quizzes)

    if len(quizzes)>1:
        quiz_avg =  (quiz_total/((len(quizzes))-1)*10) 
    else:
        quiz_avg = (quiz_total*10) #no reason to divide by len(quizzes) if it is 1

    project_total = sum(projects)
    project_avg = (project_total/(len(projects))*10)

    exam1 = tests[0]
    exam2 = tests[1]
    final = tests[2]

    average = ((quiz_avg*.15)+(project_avg*.20)+(exam1*.20)+(exam2*.20)+(final*.25))

    if 90 <= average <= 100:
        final_grade = "A"
    if 80 <= average < 90:
        final_grade = "B"
    if 70 <= average < 80:
        final_grade = "C"
    if 60 <= average < 70:
        final_grade = "D"
    if 0 <= average < 60:
        final_grade = "F"

    with open(output_name,"a") as file:
        file.write("{0:20} {1:0.1f} {2:>4}\n".format(student, average, final_grade))

Esto genera lo siguiente:

Babbage, Charles     89.4    B
Turing, Alan         91.3    A
Hopper, Grace        92.7    A
Van Rossum, Guido    75.5    C
Backus, John         94.3    A
Crawley, Bryan       54.9    F

¿No estás seguro de por qué la calificación de Bryan Crawley es más baja de lo que esperabas?

0
0TTT0 1 nov. 2017 a las 05:05

Quizás quieras usar .csv en su lugar. Al importar csv o pandas, puede guardar / cargar datos en / desde archivos csv.

Ver documentos oficiales para más detalles.

0
Moyan 31 oct. 2017 a las 04:27

Editar: he eliminado el uso de NumPy y Pandas. Si desea respuestas más detalladas o específicas a su pregunta, debe actualizar su pregunta original o poner en los comentarios.

Si no puede elegir cómo se verá su entrada de datos antes de hacerlo, como sugirió @martineau, podría hacer algo como esto:

# Ordered dictionary will let us add keys to a dictionary {}, but if we
# access the keys, it will retain the order we added them, which is not
# the default behaviour of a normal dict.
from collections import OrderedDict

# Load the file and sequentially add lines for users. You can simplify
# if they always have 3 lines each
with open('scores.txt') as f:

    out_dict = OrderedDict()
    # Load in each line from the file
    for line in f.readlines():

        # remove commas, replace(), strip newline characters '\n', strip();
        # split the line on spaces '81 81 30' -> ['81', '81', '30']
        line_split = [i for i in line.strip().replace(',', '').split(' ') if i != '']

        # From your current format, we know that some lines start with a character when there is a name, or a digit if it is a number
        # float('4') will give 4
        # float('s') will raise a ValueError exception
        #

        try:
            # If we do not raise an exception, we know it is an integer/float
            vals = [float(i) for i in line_split]
            # We can keep adding the values to the last entry in our dictionary, i.e., to the last name we created
            # As we used OrderedDict, we do not have to worry that we will retrieve a random key.
            out_dict[[i for i in out_dict.keys()][-1]].extend(vals)
        except ValueError:
            # So, if we raise an exception, we know it is 'Charles Babbage'
            # A new name is a new key, so put a new key in out_dict, and make the value a list we can keep adding to
            out_dict[line.strip()] = []

Entonces puedes jugar con este diccionario como quieras. También puedes hacer que get_score y get_grade funcionen como quieras, por ahora solo tomé el promedio ya que no entendí completamente tu intención ...

# Some functions to define how the score and grading works
def get_score(scores):
    return sum(scores)/(1.0*len(scores))

def get_grade(score):
    if 90 <= score <= 100:
        return 'A'
    if 80 <= score < 90:
        return 'B'
    if 70 <= score < 80:
        return 'C'
    if 60 <= score < 70:
        return 'D'
    if 0 <= score < 60:
        return 'E'

for key, item in out_dict.items():
    print(key, get_score(item), get_grade(get_score(item)))

La salida se verá así:

Babbage, Charles 32.4 E
Turing, Alan 33.3 E
Hopper, Grace 33.65 E
Van Rossum, Guido 29.5555555556 E
Backus, John 27.8214285714 E
Crawley, Bryan 39.8 E
0
jonnybazookatone 2 nov. 2017 a las 09:10