Skip to content

Commit

Permalink
ADD: new exercise
Browse files Browse the repository at this point in the history
  • Loading branch information
MrTob committed Oct 25, 2024
1 parent af8519f commit 22fd796
Show file tree
Hide file tree
Showing 8 changed files with 327 additions and 0 deletions.
70 changes: 70 additions & 0 deletions exercises/practice/result-analyzer/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Instructions

The first line of the CSV file contains the headings, the other lines contain the results of the participants.
Each line has the following elements separated by commas: an id, a name, then 10 points for 10 exercises.
A maximum of 10 points can be achieved in each exercise. A value of -1 means that no solution has been
submitted.
The lines of the files can be read by:
```scala
val lines = readCSV()
```
For the following calculations should be solved using Scala’s collections with their higher-order
functions. Try to implement each calculation by a single chain of operations.

## Task 1: Building a list of Results objects
The first task is to build a list of Results objects from the read lines. Implement a case class Results
with an id of type Int, as name of type String and an list of points of type List[Int]. Then compute
the list of Results objects for the participants
```scala
val resultList : List[Results] = ???
```

## Task 2: Number of solved tasks
From the list of Results objects, create a map that contains the number of solved exercises for each
student. An exercise is considered solved if at least 3 points have been achieved.

## Task 3: Sufficient tasks solved
A student must solve at least 8 exercises to pass the course. Determine which students have submitted
enough solutions and which have not enough solutions.
```scala
val sufficientSolved : (Set[String], Set[String]) = ...
```
_Hint: Use method partition._

## Task 4: Grading

Next, the grades should be determined. The grades are calculated based on the points: There must be at least eight solutions with at least 3
points. If this is the case, the grading is done based on the average of the best eight solutions according
to the following scheme:
```
- [0.0 .. 5.0) : INSUFFICIENT
- [5.0 .. 6.25) : SUFFICIENT
- [6.25 .. 7.5) : SATISFACTORY
- [7.5 .. 8.75) : GOOD
- [8.75 .. 1.0] : EXCELLENT
```
```scala
val grades: Map[String, Grade] = ...
```

## Task 5: Grade statistics

Compute statistic measurement from the grading. For each grade, compute the number of students with
that grade:
```scala
val nStudentsWithGrade : Map[Grade, Int] = ...
```

## Task 6: Number solved per assignment
For the 10 exercises, compute how many students have solved them (at least 3 points). Result is a list of
10 numbers, which indicate how many students have solved the exercises:
```scala
val nSolvedPerAssnmt : List[(Int, Int)] = ...
```

## Task 7: Average points per assignment
For the 10 exercises, compute the average of the achieved points. Only the submitted exercises (points
!= -1) should be considered:
```scala
val avrgPointsPerAssnmt : List[(Int, Double)] = ...
```
8 changes: 8 additions & 0 deletions exercises/practice/result-analyzer/.docs/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Processing Results with Collections
In this assignment, we want to use the Scala collections API for analyzing the results of a programming
course. The starting point is a CSV file in which the points achieved in 10 programming exercises are
stored for the course participants:
ID,Name,1,2,3,4,5,6,7,8,9,10
1,Alred Maier,10,8,2,7,10,9,7,6,7,2
2,Fritz Michalik,8,6,5,7,-1,-1,8,6,8,10
...
4 changes: 4 additions & 0 deletions exercises/practice/result-analyzer/.meta/Example.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
object ResultsAnalysis {

}

25 changes: 25 additions & 0 deletions exercises/practice/result-analyzer/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"authors": [
"mrtob"
],
"contributors": [
"mrtob"
],
"files": {
"solution": [
"src/main/scala/ResultsAnalysis.scala"
],
"test": [
"src/test/scala/ResultsAnalysisTest.scala"
],
"example": [
".meta/Example.scala"
],
"invalidator": [
"build.sbt"
]
},
"blurb": "Analyze the points of students in a class to ´genrate statistics.",
"source": "Exercism",
"source_url": ""
}
3 changes: 3 additions & 0 deletions exercises/practice/result-analyzer/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
scalaVersion := "3.4.2"

libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sbt.version=1.10.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
def readCSV(): List[String] = {
List(
"ID,Name,1,2,3,4,5,6,7,8,9,10",
"1,Jane Doe,9,10,9,6,10,9,10,10,10,9",
"2,John Doe,8,6,5,7,-1,-1,8,6,8,10",
"3,Jake Doe,10,9,9,-1,5,-1,8,-1,10,9",
"4,Jill Doe,10,8,2,7,10,9,7,6,7,2",
)
}

case class Results(id: Int, name: String, points: IndexedSeq[Int])

enum Grade:
case EXCELLENT, GOOD, SATISFACTORY, SUFFICIENT, INSUFFICIENT

object ResultsAnalysis {

def task1(lines: List[String]): List[Results] =
//TODO: Implement this method
???

def task2(resultList: List[Results]): Map[String, Int] =
//TODO: Implement this method
???

def task3(nSolvedPerStnd: Map[String, Int]): (Set[String], Set[String]) =
//TODO: Implement this method
???

def task4(resultList: List[Results]): Map[String, Grade] =
//TODO: Implement this method
???

def task5(resultList: List[Results]): Map[Grade, Int] =
//TODO: Implement this method
???

def task6(resultList: List[Results]): List[(Int, Int)] =
//TODO: Implement this method
???

def task7(resultList: List[Results]): List[(Int, Double)] =
//TODO: Implement this method
???

def main(args: Array[String]): Unit = {
val lines = readCSV()

// Task 1
val resultList: List[Results] = task1(lines)

// Task 2
val nSolvedPerStnd = task2(resultList)

// Task 3
val sufficientSolved = task3(nSolvedPerStnd)

// Task 4
val grades = task4(resultList)

//Task 5
val nStudentsWithGrade = task5(resultList)

//Task 6
val nSolvedPerAssnmt = task6(resultList)

//Task 7
val avrgPointsPerAssnmt = task7(resultList)
}

private def computeGrade(points: IndexedSeq[Int]): Grade = {
if (points.count(p => p >= 3) < 8) then Grade.INSUFFICIENT
else {
val avrg = points.sorted.drop(2).sum / 8
if (avrg < 5.0) then Grade.INSUFFICIENT
else if (avrg < 6.5) then Grade.SUFFICIENT
else if (avrg < 8.0) then Grade.SATISFACTORY
else if (avrg < 9.0) then Grade.GOOD
else Grade.EXCELLENT
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.matchers.should.Matchers

import scala.collection.immutable.HashMap


/** @version 1.2.0 */
class ResultsAnalysisTest extends AnyFunSuite with Matchers {

test("Task 1") {
val lines = List(
"ID,Name,1,2,3,4,5,6,7,8,9,10",
"1,Jane Doe,9,10,9,6,10,9,10,10,10,9",
"2,John Doe,8,6,5,7,-1,-1,8,6,8,10",
"3,Jake Doe,10,9,9,-1,5,-1,8,-1,10,9",
"4,Jill Doe,10,8,2,7,10,9,7,6,7,2",
)

val expectedResults = List(
Results(1, "Jane Doe", IndexedSeq(9, 10, 9, 6, 10, 9, 10, 10, 10, 9)),
Results(2, "John Doe", IndexedSeq(8, 6, 5, 7, -1, -1, 8, 6, 8, 10)),
Results(3, "Jake Doe", IndexedSeq(10, 9, 9, -1, 5, -1, 8, -1, 10, 9)),
Results(4, "Jill Doe", IndexedSeq(10, 8, 2, 7, 10, 9, 7, 6, 7, 2))
)

val resultList = ResultsAnalysis.task1(lines)
resultList shouldEqual expectedResults
}

test("Task 2") {
val results = List(
Results(1, "Jane Doe", IndexedSeq(9, 10, 9, 6, 10, 9, 10, 10, 10, 9)),
Results(2, "John Doe", IndexedSeq(8, 6, 5, 7, -1, -1, 8, 6, 8, 10)),
Results(3, "Jake Doe", IndexedSeq(10, 9, 9, -1, 5, -1, 8, -1, 10, 9)),
Results(4, "Jill Doe", IndexedSeq(10, 8, 2, 7, 10, 9, 7, 6, 7, 2))
)

val expectedResults = Map(
"Jane Doe" -> 10,
"John Doe" -> 8,
"Jake Doe" -> 7,
"Jill Doe" -> 8
)

val resultList = ResultsAnalysis.task2(results)
resultList shouldEqual expectedResults
}

test("Task 3") {
val results = Map(
"Jane Doe" -> 10,
"John Doe" -> 8,
"Jake Doe" -> 7,
"Jill Doe" -> 8
)

val expectedResults = (Set("Jane Doe", "John Doe", "Jill Doe"), Set("Jake Doe"))

val resultList = ResultsAnalysis.task3(results)
resultList shouldEqual expectedResults
}

test("Task 4") {
val results = List(
Results(1, "Jane Doe", IndexedSeq(9, 10, 9, 6, 10, 9, 10, 10, 10, 9)),
Results(2, "John Doe", IndexedSeq(8, 6, 5, 7, -1, -1, 8, 6, 8, 10)),
Results(3, "Jake Doe", IndexedSeq(10, 9, 9, -1, 5, -1, 8, -1, 10, 9)),
Results(4, "Jill Doe", IndexedSeq(10, 8, 2, 7, 10, 9, 7, 6, 7, 2))
)

val expectedResults = Map(
"Jane Doe" -> Grade.EXCELLENT,
"John Doe" -> Grade.SATISFACTORY,
"Jake Doe" -> Grade.INSUFFICIENT,
"Jill Doe" -> Grade.GOOD
)

val resultList = ResultsAnalysis.task4(results)
resultList shouldEqual expectedResults
}

test("Task 5") {
val results = List(
Results(1, "Jane Doe", IndexedSeq(9, 10, 9, 6, 10, 9, 10, 10, 10, 9)),
Results(2, "John Doe", IndexedSeq(8, 6, 5, 7, -1, -1, 8, 6, 8, 10)),
Results(3, "Jake Doe", IndexedSeq(10, 9, 9, -1, 5, -1, 8, -1, 10, 9)),
Results(4, "Jill Doe", IndexedSeq(10, 8, 2, 7, 10, 9, 7, 6, 7, 2))
)

val expectedResults = HashMap(
Grade.EXCELLENT -> 1,
Grade.SATISFACTORY -> 1,
Grade.INSUFFICIENT -> 1,
Grade.GOOD -> 1
)

val resultList = ResultsAnalysis.task5(results)
resultList shouldEqual expectedResults
}

test("Task 6") {
val results = List(
Results(1, "Jane Doe", IndexedSeq(9, 10, 9, 6, 10, 9, 10, 10, 10, 9)),
Results(2, "John Doe", IndexedSeq(8, 6, 5, 7, -1, -1, 8, 6, 8, 10)),
Results(3, "Jake Doe", IndexedSeq(10, 9, 9, -1, 5, -1, 8, -1, 10, 9)),
Results(4, "Jill Doe", IndexedSeq(10, 8, 2, 7, 10, 9, 7, 6, 7, 2))
)

val expectedResults = List(
(1, 4), (2, 4), (3, 3), (4, 3), (5, 3), (6, 2), (7, 4), (8, 3), (9, 4), (10, 3)
)

val resultList = ResultsAnalysis.task6(results)
resultList shouldEqual expectedResults
}

test("Task 7"){
val results = List(
Results(1, "Jane Doe", IndexedSeq(9, 10, 9, 6, 10, 9, 10, 10, 10, 9)),
Results(2, "John Doe", IndexedSeq(8, 6, 5, 7, -1, -1, 8, 6, 8, 10)),
Results(3, "Jake Doe", IndexedSeq(10, 9, 9, -1, 5, -1, 8, -1, 10, 9)),
Results(4, "Jill Doe", IndexedSeq(10, 8, 2, 7, 10, 9, 7, 6, 7, 2))
)

val expectedResults = List(
(1,9.25), (2,8.25), (3,6.25), (4,6.666666666666667), (5,8.333333333333334), (6,9.0), (7,8.25), (8,7.333333333333333), (9,8.75), (10,7.5)
)

val resultList = ResultsAnalysis.task7(results)
resultList shouldEqual expectedResults

}

}

0 comments on commit 22fd796

Please sign in to comment.