From 1c057609258f484120f11e0263c9c6c4572ae672 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A1s=20B=20Nagy?= <20251272+BNAndras@users.noreply.github.com> Date: Tue, 29 Jul 2025 22:02:27 -0700 Subject: [PATCH] Add `tournament` --- config.json | 9 ++ .../practice/tournament/.docs/instructions.md | 66 ++++++++++++++ .../practice/tournament/.meta/config.json | 31 +++++++ .../practice/tournament/.meta/example.vim | 80 +++++++++++++++++ .../practice/tournament/.meta/tests.toml | 46 ++++++++++ exercises/practice/tournament/inputs/01.txt | 0 exercises/practice/tournament/inputs/02.txt | 1 + exercises/practice/tournament/inputs/03.txt | 1 + exercises/practice/tournament/inputs/04.txt | 1 + exercises/practice/tournament/inputs/05.txt | 1 + exercises/practice/tournament/inputs/06.txt | 2 + exercises/practice/tournament/inputs/07.txt | 2 + exercises/practice/tournament/inputs/08.txt | 3 + exercises/practice/tournament/inputs/09.txt | 6 ++ exercises/practice/tournament/inputs/10.txt | 4 + exercises/practice/tournament/inputs/11.txt | 6 ++ exercises/practice/tournament/inputs/12.txt | 5 ++ .../practice/tournament/tournament.vader | 88 +++++++++++++++++++ exercises/practice/tournament/tournament.vim | 3 + 19 files changed, 355 insertions(+) create mode 100644 exercises/practice/tournament/.docs/instructions.md create mode 100644 exercises/practice/tournament/.meta/config.json create mode 100644 exercises/practice/tournament/.meta/example.vim create mode 100644 exercises/practice/tournament/.meta/tests.toml create mode 100644 exercises/practice/tournament/inputs/01.txt create mode 100644 exercises/practice/tournament/inputs/02.txt create mode 100644 exercises/practice/tournament/inputs/03.txt create mode 100644 exercises/practice/tournament/inputs/04.txt create mode 100644 exercises/practice/tournament/inputs/05.txt create mode 100644 exercises/practice/tournament/inputs/06.txt create mode 100644 exercises/practice/tournament/inputs/07.txt create mode 100644 exercises/practice/tournament/inputs/08.txt create mode 100644 exercises/practice/tournament/inputs/09.txt create mode 100644 exercises/practice/tournament/inputs/10.txt create mode 100644 exercises/practice/tournament/inputs/11.txt create mode 100644 exercises/practice/tournament/inputs/12.txt create mode 100644 exercises/practice/tournament/tournament.vader create mode 100644 exercises/practice/tournament/tournament.vim diff --git a/config.json b/config.json index 8e4aa5a..e3f6b1a 100644 --- a/config.json +++ b/config.json @@ -774,6 +774,15 @@ "prerequisites": [], "difficulty": 5 }, + { + "slug": "tournament", + "name": "Tournament", + "uuid": "452756cd-f85d-4853-8775-59a15abdc61e", + "practices": [], + "prerequisites": [], + "difficulty": 5, + "status": "wip" + }, { "slug": "transpose", "name": "Transpose", diff --git a/exercises/practice/tournament/.docs/instructions.md b/exercises/practice/tournament/.docs/instructions.md new file mode 100644 index 0000000..e5ca237 --- /dev/null +++ b/exercises/practice/tournament/.docs/instructions.md @@ -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. diff --git a/exercises/practice/tournament/.meta/config.json b/exercises/practice/tournament/.meta/config.json new file mode 100644 index 0000000..b71a6bb --- /dev/null +++ b/exercises/practice/tournament/.meta/config.json @@ -0,0 +1,31 @@ +{ + "authors": [ + "BNAndras" + ], + "files": { + "solution": [ + "tournament.vim" + ], + "test": [ + "tournament.vader" + ], + "editor": [ + "inputs/01.txt", + "inputs/02.txt", + "inputs/03.txt", + "inputs/04.txt", + "inputs/05.txt", + "inputs/06.txt", + "inputs/07.txt", + "inputs/08.txt", + "inputs/09.txt", + "inputs/10.txt", + "inputs/11.txt", + "inputs/12.txt" + ], + "example": [ + ".meta/example.vim" + ] + }, + "blurb": "Tally the results of a small football competition." +} diff --git a/exercises/practice/tournament/.meta/example.vim b/exercises/practice/tournament/.meta/example.vim new file mode 100644 index 0000000..05b6659 --- /dev/null +++ b/exercises/practice/tournament/.meta/example.vim @@ -0,0 +1,80 @@ +let s:HEADER = 'Team | MP | W | D | L | P' + +function! Tally(relative_input_csv) abort + let l:lines = readfile(a:relative_input_csv) + if empty(l:lines) + return s:HEADER + endif + + let l:team_data = s:ProcessGameResults(l:lines) + let l:team_standings = s:PrepareStandings(l:team_data) + let l:rows = s:BuildTableRows(l:team_standings) + + return s:HEADER . "\n" . join(l:rows, "\n") +endfunction + +function! s:ProcessGameResults(lines) abort + let l:teams = {} + for l:line in a:lines + let [l:team1, l:team2, l:result] = split(l:line, ';') + + if !has_key(l:teams, l:team1) + let l:teams[l:team1] = {'name': l:team1, 'W': 0, 'D': 0, 'L': 0} + endif + + if !has_key(l:teams, l:team2) + let l:teams[l:team2] = {'name': l:team2, 'W': 0, 'D': 0, 'L': 0} + endif + + if l:result ==? 'win' + let l:teams[l:team1]['W'] += 1 + let l:teams[l:team2]['L'] += 1 + elseif l:result ==? 'loss' + let l:teams[l:team1]['L'] += 1 + let l:teams[l:team2]['W'] += 1 + elseif l:result ==? 'draw' + let l:teams[l:team1]['D'] += 1 + let l:teams[l:team2]['D'] += 1 + endif + endfor + + return l:teams +endfunction + +function! s:PrepareStandings(teams) abort + let l:standings = [] + for l:team in keys(a:teams) + let l:team_data = a:teams[l:team] + let l:team_data['MP'] = l:team_data['W'] + l:team_data['D'] + l:team_data['L'] + let l:team_data['P'] = l:team_data['W'] * 3 + l:team_data['D'] + call add(l:standings, l:team_data) + endfor + + call sort(l:standings, 's:SortTeams') + + return l:standings +endfunction + +function! s:BuildTableRows(teams) abort + let l:rows = [] + for l:team_data in a:teams + let l:row = printf('%-30s | %2d | %2d | %2d | %2d | %2d', + \ l:team_data['name'], + \ l:team_data['MP'], + \ l:team_data['W'], + \ l:team_data['D'], + \ l:team_data['L'], + \ l:team_data['P']) + call add(l:rows, l:row) + endfor + + return l:rows +endfunction + +function! s:SortTeams(teamA, teamB) abort + if a:teamA['P'] ==? a:teamB['P'] + return a:teamA['name'] > a:teamB['name'] + endif + + return a:teamA['P'] < a:teamB['P'] +endfunction diff --git a/exercises/practice/tournament/.meta/tests.toml b/exercises/practice/tournament/.meta/tests.toml new file mode 100644 index 0000000..0e33c87 --- /dev/null +++ b/exercises/practice/tournament/.meta/tests.toml @@ -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" diff --git a/exercises/practice/tournament/inputs/01.txt b/exercises/practice/tournament/inputs/01.txt new file mode 100644 index 0000000..e69de29 diff --git a/exercises/practice/tournament/inputs/02.txt b/exercises/practice/tournament/inputs/02.txt new file mode 100644 index 0000000..791561b --- /dev/null +++ b/exercises/practice/tournament/inputs/02.txt @@ -0,0 +1 @@ +Allegoric Alaskans;Blithering Badgers;win diff --git a/exercises/practice/tournament/inputs/03.txt b/exercises/practice/tournament/inputs/03.txt new file mode 100644 index 0000000..fdba6e1 --- /dev/null +++ b/exercises/practice/tournament/inputs/03.txt @@ -0,0 +1 @@ +Blithering Badgers;Allegoric Alaskans;loss diff --git a/exercises/practice/tournament/inputs/04.txt b/exercises/practice/tournament/inputs/04.txt new file mode 100644 index 0000000..30cac34 --- /dev/null +++ b/exercises/practice/tournament/inputs/04.txt @@ -0,0 +1 @@ +Blithering Badgers;Allegoric Alaskans;win diff --git a/exercises/practice/tournament/inputs/05.txt b/exercises/practice/tournament/inputs/05.txt new file mode 100644 index 0000000..f94c2b2 --- /dev/null +++ b/exercises/practice/tournament/inputs/05.txt @@ -0,0 +1 @@ +Allegoric Alaskans;Blithering Badgers;draw diff --git a/exercises/practice/tournament/inputs/06.txt b/exercises/practice/tournament/inputs/06.txt new file mode 100644 index 0000000..55e6e23 --- /dev/null +++ b/exercises/practice/tournament/inputs/06.txt @@ -0,0 +1,2 @@ +Allegoric Alaskans;Blithering Badgers;win +Allegoric Alaskans;Blithering Badgers;win diff --git a/exercises/practice/tournament/inputs/07.txt b/exercises/practice/tournament/inputs/07.txt new file mode 100644 index 0000000..2125598 --- /dev/null +++ b/exercises/practice/tournament/inputs/07.txt @@ -0,0 +1,2 @@ +Allegoric Alaskans;Blithering Badgers;loss +Allegoric Alaskans;Blithering Badgers;win diff --git a/exercises/practice/tournament/inputs/08.txt b/exercises/practice/tournament/inputs/08.txt new file mode 100644 index 0000000..ad97349 --- /dev/null +++ b/exercises/practice/tournament/inputs/08.txt @@ -0,0 +1,3 @@ +Allegoric Alaskans;Blithering Badgers;win +Blithering Badgers;Courageous Californians;win +Courageous Californians;Allegoric Alaskans;loss diff --git a/exercises/practice/tournament/inputs/09.txt b/exercises/practice/tournament/inputs/09.txt new file mode 100644 index 0000000..efce9d7 --- /dev/null +++ b/exercises/practice/tournament/inputs/09.txt @@ -0,0 +1,6 @@ +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 diff --git a/exercises/practice/tournament/inputs/10.txt b/exercises/practice/tournament/inputs/10.txt new file mode 100644 index 0000000..40a4f70 --- /dev/null +++ b/exercises/practice/tournament/inputs/10.txt @@ -0,0 +1,4 @@ +Allegoric Alaskans;Blithering Badgers;loss +Devastating Donkeys;Allegoric Alaskans;loss +Courageous Californians;Blithering Badgers;draw +Allegoric Alaskans;Courageous Californians;win diff --git a/exercises/practice/tournament/inputs/11.txt b/exercises/practice/tournament/inputs/11.txt new file mode 100644 index 0000000..30fe3d0 --- /dev/null +++ b/exercises/practice/tournament/inputs/11.txt @@ -0,0 +1,6 @@ +Courageous Californians;Devastating Donkeys;win +Allegoric Alaskans;Blithering Badgers;win +Devastating Donkeys;Allegoric Alaskans;loss +Courageous Californians;Blithering Badgers;win +Blithering Badgers;Devastating Donkeys;draw +Allegoric Alaskans;Courageous Californians;draw diff --git a/exercises/practice/tournament/inputs/12.txt b/exercises/practice/tournament/inputs/12.txt new file mode 100644 index 0000000..78f68bf --- /dev/null +++ b/exercises/practice/tournament/inputs/12.txt @@ -0,0 +1,5 @@ +Devastating Donkeys;Blithering Badgers;win +Devastating Donkeys;Blithering Badgers;win +Devastating Donkeys;Blithering Badgers;win +Devastating Donkeys;Blithering Badgers;win +Blithering Badgers;Devastating Donkeys;win diff --git a/exercises/practice/tournament/tournament.vader b/exercises/practice/tournament/tournament.vader new file mode 100644 index 0000000..e66cc55 --- /dev/null +++ b/exercises/practice/tournament/tournament.vader @@ -0,0 +1,88 @@ +Execute (just the header if no input): + let g:expected = 'Team | MP | W | D | L | P' + AssertEqual g:expected, Tally('inputs/01.txt') + +Execute (a win is three points, a loss is zero points): + let g:expected = join([ + \ 'Team | MP | W | D | L | P', + \ 'Allegoric Alaskans | 1 | 1 | 0 | 0 | 3', + \ 'Blithering Badgers | 1 | 0 | 0 | 1 | 0'], "\n") + AssertEqual g:expected, Tally('inputs/02.txt') + +Execute (a win can also be expressed as a loss): + let g:expected = join([ + \ 'Team | MP | W | D | L | P', + \ 'Allegoric Alaskans | 1 | 1 | 0 | 0 | 3', + \ 'Blithering Badgers | 1 | 0 | 0 | 1 | 0'], "\n") + AssertEqual g:expected, Tally('inputs/03.txt') + +Execute (a different team can win): + let g:expected = join([ + \ 'Team | MP | W | D | L | P', + \ 'Blithering Badgers | 1 | 1 | 0 | 0 | 3', + \ 'Allegoric Alaskans | 1 | 0 | 0 | 1 | 0'], "\n") + AssertEqual g:expected, Tally('inputs/04.txt') + +Execute (a draw is one point each): + let g:expected = join([ + \ 'Team | MP | W | D | L | P', + \ 'Allegoric Alaskans | 1 | 0 | 1 | 0 | 1', + \ 'Blithering Badgers | 1 | 0 | 1 | 0 | 1'], "\n") + AssertEqual g:expected, Tally('inputs/05.txt') + +Execute (There can be more than one match): + let g:expected = join([ + \ 'Team | MP | W | D | L | P', + \ 'Allegoric Alaskans | 2 | 2 | 0 | 0 | 6', + \ 'Blithering Badgers | 2 | 0 | 0 | 2 | 0'], "\n") + AssertEqual g:expected, Tally('inputs/06.txt') + +Execute (There can be more than one winner): + let g:expected = join([ + \ 'Team | MP | W | D | L | P', + \ 'Allegoric Alaskans | 2 | 1 | 0 | 1 | 3', + \ 'Blithering Badgers | 2 | 1 | 0 | 1 | 3'], "\n") + AssertEqual g:expected, Tally('inputs/07.txt') + + +Execute (There can be more than two teams): + let g:expected = join([ + \ 'Team | MP | W | D | L | P', + \ 'Allegoric Alaskans | 2 | 2 | 0 | 0 | 6', + \ 'Blithering Badgers | 2 | 1 | 0 | 1 | 3', + \ 'Courageous Californians | 2 | 0 | 0 | 2 | 0'], "\n") + AssertEqual g:expected, Tally('inputs/08.txt') + +Execute (typical input): + let g:expected = join([ + \ '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'], "\n") + AssertEqual g:expected, Tally('inputs/09.txt') + +Execute (incomplete competition (not all pairs have played)): + let g:expected = join([ + \ 'Team | MP | W | D | L | P', + \ 'Allegoric Alaskans | 3 | 2 | 0 | 1 | 6', + \ 'Blithering Badgers | 2 | 1 | 1 | 0 | 4', + \ 'Courageous Californians | 2 | 0 | 1 | 1 | 1', + \ 'Devastating Donkeys | 1 | 0 | 0 | 1 | 0'], "\n") + AssertEqual g:expected, Tally('inputs/10.txt') + +Execute (ties broken alphabetically): + let g:expected = join([ + \ 'Team | MP | W | D | L | P', + \ 'Allegoric Alaskans | 3 | 2 | 1 | 0 | 7', + \ 'Courageous Californians | 3 | 2 | 1 | 0 | 7', + \ 'Blithering Badgers | 3 | 0 | 1 | 2 | 1', + \ 'Devastating Donkeys | 3 | 0 | 1 | 2 | 1'], "\n") + AssertEqual g:expected, Tally('inputs/11.txt') + +Execute (ensure points sorted numerically): + let g:expected = join([ + \ 'Team | MP | W | D | L | P', + \ 'Devastating Donkeys | 5 | 4 | 0 | 1 | 12', + \ 'Blithering Badgers | 5 | 1 | 0 | 4 | 3'], "\n") + AssertEqual g:expected, Tally('inputs/12.txt') diff --git a/exercises/practice/tournament/tournament.vim b/exercises/practice/tournament/tournament.vim new file mode 100644 index 0000000..d489de8 --- /dev/null +++ b/exercises/practice/tournament/tournament.vim @@ -0,0 +1,3 @@ +function! Tally(relative_input_csv) abort + " your code goes here +endfunction