Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ADD: new exercise #846

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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

}

}