The prompt is as follows: This script will use a text menu to give the user options. The options will include the ability to add grades of different types as well as an option to print the current grades and average. Types of grades are tests, quizzes, and assignments. For the final average, the tests and assignments count 40% each and the quizzes make up the remaining 20%. The lowest quiz grade should be dropped. The menu will have numbers by each option and users enter a number to select that option. Note: grades are the numbers obtained (i.e. 0 to 100)
I have written the following code:
import io.StdIn._
//global var for grades, implemented as Lists so that updating is easier and efficient
var testList: List[Int] = Nil
var assignmentList:List[Int] = Nil
var quizList: List[Int] = Nil
//boolean variable to run program in a loop
var is_over: Boolean = false
while (!is_over) {
//display menu to let the user choose from the options
println("Choose an option from below\n1. Add grades\n2. Get grades and average\n3. Exit program ")
val chosenOption: Int = readInt()
//match to call the functions according to user selection
chosenOption match {
case 1 => println("\nWhich type of grade do you want to enter?\n1. Test\n2. Quiz\n3. Assignment")
returnGrades(readInt()) //pass the option for the type of grade to add
case 2 => outputGrades()
case 3 => is_over = true //option 3 will exit the program
case _ => println("Invalid option")
}
}
def returnGrades(option$:Int):Unit = {
//tell the user that while building the list, they enter -1 to exit building the list
println("\nEnter grades, \"-1\" to exit\n ")
//match to add grades of a specific type
option$ match {
case 1 => testList = buildList()
case 2 => quizList = buildList()
case 3 => assignmentList = buildList()
case _ => println("Error in value entered")
}
println("-"*40)
}
//recursive function to build a list
def buildList():List[Int] = {
val x: Int = readInt()
if (x < -1 || x>100) {
print("Invalid entry. Re-enter: ")
buildList()
} else if (x == -1) {
Nil
}
else x::buildList()
}
def outputGrades():Unit= {
//output current grades with .mkString
println("Grades for tests are : " + testList.mkString("\t"))
println("Grades for quizzes are : " + newQuizList().mkString("\t"))
println("Grades for assignments are: " + assignmentList.mkString("\t"))
val x:Double = 0.4 * calculateAverage(testList) + 0.4 * calculateAverage(assignmentList) +
0.2 * calculateAverage(quizList)
println("Average is: " + x )
println("-"*40)
}
//function for quizList so that the program does not returns an error if you use .min method on an empty list.
def newQuizList():List[Int] = {if (quizList.nonEmpty) quizList diff List(quizList.min) else Nil}
def calculateAverage(lst:List[Int]):Double = {if (lst.isEmpty) 0 else lst.sum/lst.length}
Are there perhaps more efficient ways to achieve the same goal?