Skip to content

Commit be98a1b

Browse files
authored
[New Exercise] Add high-scores exercise (#866)
* Add high-scores exercise * Fixes
1 parent 6492d8c commit be98a1b

File tree

10 files changed

+262
-0
lines changed

10 files changed

+262
-0
lines changed

config.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,18 @@
528528
"prerequisites": [],
529529
"difficulty": 2
530530
},
531+
{
532+
"slug": "high-scores",
533+
"name": "High Scores",
534+
"uuid": "6492df34-e0be-4b67-9218-cd732dea2da7",
535+
"practices": [],
536+
"prerequisites": [],
537+
"difficulty": 2,
538+
"topics": [
539+
"arrays",
540+
"stored-properties"
541+
]
542+
},
531543
{
532544
"slug": "binary-search",
533545
"name": "Binary Search",
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Instructions append
2+
3+
## Some Additional Notes for Swift Implementation
4+
5+
The tests for this exercise expect you to implement a couple of properties that return either a value of type `Int` or an [array][array] of type `[Int]`. Feel free to skim through the Array class documentation for useful methods that may help in your solution.
6+
7+
The final tests check for [immutability][immutability]. None of the properties you are tasked with writing should modify the scores of the game.
8+
9+
If you want some extra practice, you can implement a function that adds new scores to the game or handle empty array
10+
11+
[array]: https://developer.apple.com/documentation/swift/array
12+
[immutability]: https://en.wikipedia.org/wiki/Immutable_object
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Instructions
2+
3+
Manage a game player's High Score list.
4+
5+
Your task is to build a high-score component of the classic Frogger game, one of the highest selling and most addictive games of all time, and a classic of the arcade era.
6+
Your task is to write methods that return the highest score from the list, the last added score and the three highest scores.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import Foundation
2+
3+
struct HighScores {
4+
5+
let scores: [Int]
6+
let latest: Int?
7+
let personalBest: Int?
8+
let topThree: [Int]
9+
10+
init(scores: [Int]) {
11+
self.scores = scores
12+
self.latest = scores.last
13+
self.personalBest = scores.max()
14+
self.topThree = Array(scores.sorted(by: >).prefix(3))
15+
}
16+
17+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"authors": [
3+
"Sencudra"
4+
],
5+
"files": {
6+
"solution": [
7+
"Sources/HighScores/HighScores.swift"
8+
],
9+
"test": [
10+
"Tests/HighScoresTests/HighScoresTests.swift"
11+
],
12+
"example": [
13+
".meta/Sources/HighScores/HighScoresExample.swift"
14+
]
15+
},
16+
"blurb": "Manage a player's High Score list.",
17+
"source": "Tribute to the eighties' arcade game Frogger"
18+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import Testing
2+
import Foundation
3+
@testable import {{exercise | camelCase}}
4+
5+
let RUNALL = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "false"]) ?? false
6+
7+
@Suite struct {{exercise | camelCase}}Tests {
8+
{% for case in cases %}
9+
{% if not case.cases %}
10+
{% if forloop.first %}
11+
@Test("{{case.description}}")
12+
{% else %}
13+
@Test("{{case.description}}", .enabled(if: RUNALL))
14+
{% endif -%}
15+
func test{{case.description | camelCase}}() {
16+
#expect(HighScores(scores: {{case.input.scores}}).{{case.property}} == {{case.expected}})
17+
}
18+
{%- elif case.cases %}
19+
{% for subCase in case.cases %}
20+
@Test("{{subCase.description}}", .enabled(if: RUNALL))
21+
func test{{subCase.description | camelCase}}() {
22+
var hs = HighScores(scores: {{subCase.input.scores}})
23+
{%- if subCase.property == "latestAfterTopThree" or subCase.property == "scoresAfterTopThree" %}
24+
hs.topThree
25+
{% elif subCase.property == "latestAfterBest" or subCase.property == "scoresAfterBest" %}
26+
hs.personalBest
27+
{% endif -%}
28+
#expect(hs.
29+
{%- if subCase.property == "personalTopThree" -%}
30+
topThree
31+
{%- elif subCase.property == "latestAfterTopThree" or subCase.property == "latestAfterBest" -%}
32+
latest
33+
{%- elif subCase.property == "scoresAfterTopThree" or subCase.property == "scoresAfterBest" -%}
34+
scores
35+
{%- endif %} == {{subCase.expected}})
36+
}
37+
{% endfor -%}
38+
{%- endif %}
39+
{% endfor -%}
40+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[1035eb93-2208-4c22-bab8-fef06769a73c]
13+
description = "List of scores"
14+
15+
[6aa5dbf5-78fa-4375-b22c-ffaa989732d2]
16+
description = "Latest score"
17+
18+
[b661a2e1-aebf-4f50-9139-0fb817dd12c6]
19+
description = "Personal best"
20+
21+
[3d996a97-c81c-4642-9afc-80b80dc14015]
22+
description = "Top 3 scores -> Personal top three from a list of scores"
23+
24+
[1084ecb5-3eb4-46fe-a816-e40331a4e83a]
25+
description = "Top 3 scores -> Personal top highest to lowest"
26+
27+
[e6465b6b-5a11-4936-bfe3-35241c4f4f16]
28+
description = "Top 3 scores -> Personal top when there is a tie"
29+
30+
[f73b02af-c8fd-41c9-91b9-c86eaa86bce2]
31+
description = "Top 3 scores -> Personal top when there are less than 3"
32+
33+
[16608eae-f60f-4a88-800e-aabce5df2865]
34+
description = "Top 3 scores -> Personal top when there is only one"
35+
36+
[2df075f9-fec9-4756-8f40-98c52a11504f]
37+
description = "Top 3 scores -> Latest score after personal top scores"
38+
39+
[809c4058-7eb1-4206-b01e-79238b9b71bc]
40+
description = "Top 3 scores -> Scores after personal top scores"
41+
42+
[ddb0efc0-9a86-4f82-bc30-21ae0bdc6418]
43+
description = "Top 3 scores -> Latest score after personal best"
44+
45+
[6a0fd2d1-4cc4-46b9-a5bb-2fb667ca2364]
46+
description = "Top 3 scores -> Scores after personal best"
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// swift-tools-version:6.0
2+
3+
import PackageDescription
4+
5+
let package = Package(
6+
name: "HighScores",
7+
products: [
8+
.library(
9+
name: "HighScores",
10+
targets: ["HighScores"]),
11+
],
12+
dependencies: [],
13+
targets: [
14+
.target(
15+
name: "HighScores",
16+
dependencies: []),
17+
.testTarget(
18+
name: "HighScoresTests",
19+
dependencies: ["HighScores"]),
20+
]
21+
)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import Foundation
2+
3+
struct HighScores {
4+
5+
// Write your code for the 'High Scores' exercise here.
6+
7+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import Foundation
2+
import Testing
3+
4+
@testable import HighScores
5+
6+
let RUNALL = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "false"]) ?? false
7+
8+
@Suite struct HighScoresTests {
9+
10+
@Test("List of scores")
11+
func testListOfScores() {
12+
#expect(HighScores(scores: [30, 50, 20, 70]).scores == [30, 50, 20, 70])
13+
}
14+
15+
@Test("Latest score", .enabled(if: RUNALL))
16+
func testLatestScore() {
17+
#expect(HighScores(scores: [100, 0, 90, 30]).latest == 30)
18+
}
19+
20+
@Test("Personal best", .enabled(if: RUNALL))
21+
func testPersonalBest() {
22+
#expect(HighScores(scores: [40, 100, 70]).personalBest == 100)
23+
}
24+
25+
@Test("Personal top three from a list of scores", .enabled(if: RUNALL))
26+
func testPersonalTopThreeFromAListOfScores() {
27+
var hs = HighScores(scores: [10, 30, 90, 30, 100, 20, 10, 0, 30, 40, 40, 70, 70])
28+
#expect(hs.topThree == [100, 90, 70])
29+
}
30+
31+
@Test("Personal top highest to lowest", .enabled(if: RUNALL))
32+
func testPersonalTopHighestToLowest() {
33+
var hs = HighScores(scores: [20, 10, 30])
34+
#expect(hs.topThree == [30, 20, 10])
35+
}
36+
37+
@Test("Personal top when there is a tie", .enabled(if: RUNALL))
38+
func testPersonalTopWhenThereIsATie() {
39+
var hs = HighScores(scores: [40, 20, 40, 30])
40+
#expect(hs.topThree == [40, 40, 30])
41+
}
42+
43+
@Test("Personal top when there are less than 3", .enabled(if: RUNALL))
44+
func testPersonalTopWhenThereAreLessThan3() {
45+
var hs = HighScores(scores: [30, 70])
46+
#expect(hs.topThree == [70, 30])
47+
}
48+
49+
@Test("Personal top when there is only one", .enabled(if: RUNALL))
50+
func testPersonalTopWhenThereIsOnlyOne() {
51+
var hs = HighScores(scores: [40])
52+
#expect(hs.topThree == [40])
53+
}
54+
55+
@Test("Latest score after personal top scores", .enabled(if: RUNALL))
56+
func testLatestScoreAfterPersonalTopScores() {
57+
var hs = HighScores(scores: [70, 50, 20, 30])
58+
hs.topThree
59+
#expect(hs.latest == 30)
60+
}
61+
62+
@Test("Scores after personal top scores", .enabled(if: RUNALL))
63+
func testScoresAfterPersonalTopScores() {
64+
var hs = HighScores(scores: [30, 50, 20, 70])
65+
hs.topThree
66+
#expect(hs.scores == [30, 50, 20, 70])
67+
}
68+
69+
@Test("Latest score after personal best", .enabled(if: RUNALL))
70+
func testLatestScoreAfterPersonalBest() {
71+
var hs = HighScores(scores: [20, 70, 15, 25, 30])
72+
hs.personalBest
73+
#expect(hs.latest == 30)
74+
}
75+
76+
@Test("Scores after personal best", .enabled(if: RUNALL))
77+
func testScoresAfterPersonalBest() {
78+
var hs = HighScores(scores: [20, 70, 15, 25, 30])
79+
hs.personalBest
80+
#expect(hs.scores == [20, 70, 15, 25, 30])
81+
}
82+
83+
}

0 commit comments

Comments
 (0)