-
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
465 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
# Instructions | ||
|
||
Tally the results of a small football competition. | ||
|
||
Based on an input file containing which team played against which and what the outcome was, create a file with a table like this: | ||
|
||
```text | ||
Team | MP | W | D | L | P | ||
Devastating Donkeys | 3 | 2 | 1 | 0 | 7 | ||
Allegoric Alaskans | 3 | 2 | 0 | 1 | 6 | ||
Blithering Badgers | 3 | 1 | 0 | 2 | 3 | ||
Courageous Californians | 3 | 0 | 1 | 2 | 1 | ||
``` | ||
|
||
What do those abbreviations mean? | ||
|
||
- MP: Matches Played | ||
- W: Matches Won | ||
- D: Matches Drawn (Tied) | ||
- L: Matches Lost | ||
- P: Points | ||
|
||
A win earns a team 3 points. | ||
A draw earns 1. | ||
A loss earns 0. | ||
|
||
The outcome is ordered by points, descending. | ||
In case of a tie, teams are ordered alphabetically. | ||
|
||
## Input | ||
|
||
Your tallying program will receive input that looks like: | ||
|
||
```text | ||
Allegoric Alaskans;Blithering Badgers;win | ||
Devastating Donkeys;Courageous Californians;draw | ||
Devastating Donkeys;Allegoric Alaskans;win | ||
Courageous Californians;Blithering Badgers;loss | ||
Blithering Badgers;Devastating Donkeys;loss | ||
Allegoric Alaskans;Courageous Californians;win | ||
``` | ||
|
||
The result of the match refers to the first team listed. | ||
So this line: | ||
|
||
```text | ||
Allegoric Alaskans;Blithering Badgers;win | ||
``` | ||
|
||
means that the Allegoric Alaskans beat the Blithering Badgers. | ||
|
||
This line: | ||
|
||
```text | ||
Courageous Californians;Blithering Badgers;loss | ||
``` | ||
|
||
means that the Blithering Badgers beat the Courageous Californians. | ||
|
||
And this line: | ||
|
||
```text | ||
Devastating Donkeys;Courageous Californians;draw | ||
``` | ||
|
||
means that the Devastating Donkeys and Courageous Californians tied. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
module [tally] | ||
|
||
MatchResult : [Win, Loss, Draw] | ||
TeamTally : { mp : U64, w : U64, d : U64, l : U64, p : U64 } | ||
|
||
tally : Str -> Result Str [InvalidRow Str, InvalidResult Str] | ||
tally = \table -> | ||
if table == "" then | ||
Ok header | ||
else | ||
|
||
table | ||
|> Str.split "\n" | ||
|> List.mapTry? \row -> | ||
when row |> Str.split ";" is | ||
[team1, team2, resultStr] -> | ||
result = resultStr |> parseResult? | ||
Ok (team1, team2, result) | ||
|
||
_ -> Err (InvalidRow row) | ||
|> List.walk (Dict.empty {}) \tallyDict, (team1, team2, result) -> | ||
tallyDict | ||
|> updateTallyDict team1 result | ||
|> updateTallyDict team2 (oppositeResult result) | ||
|> tallyDictToTable | ||
|> Ok | ||
|
||
parseResult : Str -> Result MatchResult [InvalidResult Str] | ||
parseResult = \resultStr -> | ||
when resultStr is | ||
"win" -> Ok Win | ||
"loss" -> Ok Loss | ||
"draw" -> Ok Draw | ||
_ -> Err (InvalidResult resultStr) | ||
|
||
oppositeResult : MatchResult -> MatchResult | ||
oppositeResult = \result -> | ||
when result is | ||
Win -> Loss | ||
Loss -> Win | ||
Draw -> Draw | ||
|
||
updateTallyDict : Dict Str TeamTally, Str, MatchResult -> Dict Str TeamTally | ||
updateTallyDict = \tallyDict, team, result -> | ||
tallyDict | ||
|> Dict.update team \maybeTeamTally -> | ||
when maybeTeamTally is | ||
Ok teamTally -> Ok (teamTally |> updateTeamTally result) | ||
Err Missing -> Ok ({ mp: 0, w: 0, d: 0, l: 0, p: 0 } |> updateTeamTally result) | ||
|
||
updateTeamTally : TeamTally, MatchResult -> TeamTally | ||
updateTeamTally = \teamTally, result -> | ||
when result is | ||
Win -> { teamTally & mp: teamTally.mp + 1, w: teamTally.w + 1, p: teamTally.p + 3 } | ||
Draw -> { teamTally & mp: teamTally.mp + 1, d: teamTally.d + 1, p: teamTally.p + 1 } | ||
Loss -> { teamTally & mp: teamTally.mp + 1, l: teamTally.l + 1 } | ||
|
||
tallyDictToTable : Dict Str TeamTally -> Str | ||
tallyDictToTable = \tallyDict -> | ||
tableContent = | ||
tallyDict | ||
|> Dict.toList | ||
|> List.sortWith \(team1, teamTally1), (team2, teamTally2) -> | ||
when Num.compare teamTally1.p teamTally2.p is | ||
GT -> LT | ||
LT -> GT | ||
EQ -> compareStrings team1 team2 | ||
|> List.map \(team, teamTally) -> | ||
tallyColumns = | ||
[.mp, .w, .d, .l, .p] | ||
|> List.map \field -> teamTally |> field |> alignRight | ||
|> Str.joinWith " | " | ||
"$(team |> padRight 30) | $(tallyColumns)" | ||
|> Str.joinWith "\n" | ||
"$(header)\n$(tableContent)" | ||
|
||
header : Str | ||
header = "Team | MP | W | D | L | P" | ||
|
||
## Compare two strings, first by their UTF8 representations, then by length: | ||
## "" < "ABC" < "abc" < "abcdef" | ||
compareStrings : Str, Str -> [LT, EQ, GT] | ||
compareStrings = \string1, string2 -> | ||
b1 = string1 |> Str.toUtf8 | ||
b2 = string2 |> Str.toUtf8 | ||
result = | ||
List.map2 b1 b2 \c1, c2 -> Num.compare c1 c2 | ||
|> List.walkTry (Ok EQ) \_state, cmp -> | ||
when cmp is | ||
EQ -> Ok EQ | ||
res -> Err res | ||
when result is | ||
Ok _cmp -> Num.compare (List.len b1) (List.len b2) | ||
Err res -> res | ||
|
||
## Pad a string with spaces on the right to reach a given width. | ||
## Warning: this function assumes that the input string is ASCII | ||
padRight : Str, U64 -> Str | ||
padRight = \string, width -> | ||
chars = string |> Str.toUtf8 | ||
length = chars |> List.len | ||
spaces = if length < width then List.repeat " " (width - length) |> Str.joinWith "" else "" | ||
"$(string)$(spaces)" | ||
|
||
## Convert a number to a right-aligned string of width 2 or more | ||
alignRight : U64 -> Str | ||
alignRight = \number -> | ||
if number < 10 then " $(number |> Num.toStr)" else "$(number |> Num.toStr)" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"authors": [ | ||
"ageron" | ||
], | ||
"files": { | ||
"solution": [ | ||
"Tournament.roc" | ||
], | ||
"test": [ | ||
"tournament-test.roc" | ||
], | ||
"example": [ | ||
".meta/Example.roc" | ||
] | ||
}, | ||
"blurb": "Tally the results of a small football competition." | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{%- import "generator_macros.j2" as macros with context -%} | ||
{{ macros.canonical_ref() }} | ||
{{ macros.header() }} | ||
|
||
import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_camel }}] | ||
|
||
{% for case in cases -%} | ||
# {{ case["description"] }} | ||
expect | ||
table = {{ case["input"]["rows"] | to_roc_multiline_string | indent(8) }} | ||
result = {{ case["property"] | to_camel }} table | ||
expected = Ok {{ case["expected"] | to_roc_multiline_string | indent(8) }} | ||
result == expected | ||
|
||
{% endfor %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# This is an auto-generated file. | ||
# | ||
# Regenerating this file via `configlet sync` will: | ||
# - Recreate every `description` key/value pair | ||
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications | ||
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) | ||
# - Preserve any other key/value pair | ||
# | ||
# As user-added comments (using the # character) will be removed when this file | ||
# is regenerated, comments can be added via a `comment` key. | ||
|
||
[67e9fab1-07c1-49cf-9159-bc8671cc7c9c] | ||
description = "just the header if no input" | ||
|
||
[1b4a8aef-0734-4007-80a2-0626178c88f4] | ||
description = "a win is three points, a loss is zero points" | ||
|
||
[5f45ac09-4efe-46e7-8ddb-75ad85f86e05] | ||
description = "a win can also be expressed as a loss" | ||
|
||
[fd297368-efa0-442d-9f37-dd3f9a437239] | ||
description = "a different team can win" | ||
|
||
[26c016f9-e753-4a93-94e9-842f7b4d70fc] | ||
description = "a draw is one point each" | ||
|
||
[731204f6-4f34-4928-97eb-1c307ba83e62] | ||
description = "There can be more than one match" | ||
|
||
[49dc2463-42af-4ea6-95dc-f06cc5776adf] | ||
description = "There can be more than one winner" | ||
|
||
[6d930f33-435c-4e6f-9e2d-63fa85ce7dc7] | ||
description = "There can be more than two teams" | ||
|
||
[97022974-0c8a-4a50-8fe7-e36bdd8a5945] | ||
description = "typical input" | ||
|
||
[fe562f0d-ac0a-4c62-b9c9-44ee3236392b] | ||
description = "incomplete competition (not all pairs have played)" | ||
|
||
[3aa0386f-150b-4f99-90bb-5195e7b7d3b8] | ||
description = "ties broken alphabetically" | ||
|
||
[f9e20931-8a65-442a-81f6-503c0205b17a] | ||
description = "ensure points sorted numerically" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module [tally] | ||
|
||
tally : Str -> Result Str _ | ||
tally = \table -> | ||
crash "Please implement the 'tally' function" |
Oops, something went wrong.