Tournament
1. Readme
锦标赛
统计一场小型足球比赛的结果.
基于一个输入文件,它包含哪个队与哪个队进行比赛,结果是什么。用下面的表格创建出一个文件:
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
那些缩写是什么意思?
- MP:赛次
- W:比赛赢了
- D:打平
- L:比赛输了
- P:分
一场胜利,3 分。打平 1 分。输了 0 分.
结果应该按分数下降排序。在平局的情况下,球队按字母顺序排列。
输入
你的梳理程序,将接收像这样的输入:
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
一行中首个队伍名是主队。所以这一行
Allegoric Alaskans;Blithering Badgers;win
意味着,Allegoric Alaskans 打败了 Blithering Badgers。
这行:
Courageous Californians;Blithering Badgers;loss
意味着,Courageous Californians 输给了 Blithering Badgers
这行:
Devastating Donkeys;Courageous Californians;draw
意味着,Devastating Donkeys 与 Courageous Californians 打平
2. 开始你的表演
pub fn tally(match_results: &str) -> String { unimplemented!( "Given the result of the played matches '{}' return a properly formatted tally table string.", match_results ); }
3. 测试代码查看
# #![allow(unused_variables)] #fn main() { #[test] fn just_the_header_if_no_input() { let input = ""; let expected = "Team | MP | W | D | L | P"; assert_eq!(tally(&input), expected); } #[test] //#[ignore] fn a_win_is_three_points_a_loss_is_zero_points() { let input = "Allegoric Alaskans;Blithering Badgers;win"; let expected = "Team | MP | W | D | L | P\n".to_string() + "Allegoric Alaskans | 1 | 1 | 0 | 0 | 3\n" + "Blithering Badgers | 1 | 0 | 0 | 1 | 0"; assert_eq!(tally(&input), expected); } #[test] //#[ignore] fn a_win_can_also_be_expressed_as_a_loss() { let input = "Blithering Badgers;Allegoric Alaskans;loss"; let expected = "Team | MP | W | D | L | P\n".to_string() + "Allegoric Alaskans | 1 | 1 | 0 | 0 | 3\n" + "Blithering Badgers | 1 | 0 | 0 | 1 | 0"; assert_eq!(tally(&input), expected); } #[test] //#[ignore] fn a_different_team_can_win() { let input = "Blithering Badgers;Allegoric Alaskans;win"; let expected = "Team | MP | W | D | L | P\n".to_string() + "Blithering Badgers | 1 | 1 | 0 | 0 | 3\n" + "Allegoric Alaskans | 1 | 0 | 0 | 1 | 0"; assert_eq!(tally(&input), expected); } #[test] //#[ignore] fn a_draw_is_one_point_each() { let input = "Allegoric Alaskans;Blithering Badgers;draw"; let expected = "Team | MP | W | D | L | P\n".to_string() + "Allegoric Alaskans | 1 | 0 | 1 | 0 | 1\n" + "Blithering Badgers | 1 | 0 | 1 | 0 | 1"; assert_eq!(tally(&input), expected); } #[test] //#[ignore] fn there_can_be_more_than_one_match() { let input = "Allegoric Alaskans;Blithering Badgers;win\n".to_string() + "Allegoric Alaskans;Blithering Badgers;win"; let expected = "Team | MP | W | D | L | P\n".to_string() + "Allegoric Alaskans | 2 | 2 | 0 | 0 | 6\n" + "Blithering Badgers | 2 | 0 | 0 | 2 | 0"; assert_eq!(tally(&input), expected); } #[test] //#[ignore] fn there_can_be_more_than_one_winner() { let input = "Allegoric Alaskans;Blithering Badgers;loss\n".to_string() + "Allegoric Alaskans;Blithering Badgers;win"; let expected = "Team | MP | W | D | L | P\n".to_string() + "Allegoric Alaskans | 2 | 1 | 0 | 1 | 3\n" + "Blithering Badgers | 2 | 1 | 0 | 1 | 3"; assert_eq!(tally(&input), expected); } #[test] //#[ignore] fn there_can_be_more_than_two_teams() { let input = "Allegoric Alaskans;Blithering Badgers;win\n".to_string() + "Blithering Badgers;Courageous Californians;win\n" + "Courageous Californians;Allegoric Alaskans;loss"; let expected = "Team | MP | W | D | L | P\n".to_string() + "Allegoric Alaskans | 2 | 2 | 0 | 0 | 6\n" + "Blithering Badgers | 2 | 1 | 0 | 1 | 3\n" + "Courageous Californians | 2 | 0 | 0 | 2 | 0"; assert_eq!(tally(&input), expected); } #[test] //#[ignore] fn typical_input() { let input = "Allegoric Alaskans;Blithering Badgers;win\n".to_string() + "Devastating Donkeys;Courageous Californians;draw\n" + "Devastating Donkeys;Allegoric Alaskans;win\n" + "Courageous Californians;Blithering Badgers;loss\n" + "Blithering Badgers;Devastating Donkeys;loss\n" + "Allegoric Alaskans;Courageous Californians;win"; let expected = "Team | MP | W | D | L | P\n".to_string() + "Devastating Donkeys | 3 | 2 | 1 | 0 | 7\n" + "Allegoric Alaskans | 3 | 2 | 0 | 1 | 6\n" + "Blithering Badgers | 3 | 1 | 0 | 2 | 3\n" + "Courageous Californians | 3 | 0 | 1 | 2 | 1"; assert_eq!(tally(&input), expected); } #[test] //#[ignore] fn incomplete_competition_not_all_pairs_have_played() { let input = "Allegoric Alaskans;Blithering Badgers;loss\n".to_string() + "Devastating Donkeys;Allegoric Alaskans;loss\n" + "Courageous Californians;Blithering Badgers;draw\n" + "Allegoric Alaskans;Courageous Californians;win"; let expected = "Team | MP | W | D | L | P\n".to_string() + "Allegoric Alaskans | 3 | 2 | 0 | 1 | 6\n" + "Blithering Badgers | 2 | 1 | 1 | 0 | 4\n" + "Courageous Californians | 2 | 0 | 1 | 1 | 1\n" + "Devastating Donkeys | 1 | 0 | 0 | 1 | 0"; assert_eq!(tally(&input), expected); } #[test] //#[ignore] fn ties_broken_alphabetically() { let input = "Courageous Californians;Devastating Donkeys;win\n".to_string() + "Allegoric Alaskans;Blithering Badgers;win\n" + "Devastating Donkeys;Allegoric Alaskans;loss\n" + "Courageous Californians;Blithering Badgers;win\n" + "Blithering Badgers;Devastating Donkeys;draw\n" + "Allegoric Alaskans;Courageous Californians;draw"; let expected = "Team | MP | W | D | L | P\n".to_string() + "Allegoric Alaskans | 3 | 2 | 1 | 0 | 7\n" + "Courageous Californians | 3 | 2 | 1 | 0 | 7\n" + "Blithering Badgers | 3 | 0 | 1 | 2 | 1\n" + "Devastating Donkeys | 3 | 0 | 1 | 2 | 1"; assert_eq!(tally(&input), expected); } #}
4. 答案
# #![allow(unused_variables)] #fn main() { use std::cmp::Ordering::Equal; use std::collections::HashMap; enum GameResult { Win, Draw, Loss, } struct TeamResult { wins: u32, draws: u32, losses: u32, } impl TeamResult { fn new() -> TeamResult { TeamResult { wins: 0, draws: 0, losses: 0, } } fn add_game_result(&mut self, result: GameResult) { match result { GameResult::Win => self.wins += 1, GameResult::Draw => self.draws += 1, GameResult::Loss => self.losses += 1, } } } pub fn tally(input: &str) -> String { let mut results: HashMap<String, TeamResult> = HashMap::new(); for line in input.to_string().lines() { let parts: Vec<&str> = line.trim_right().split(';').collect(); if parts.len() != 3 { continue; } let team1 = parts[0]; let team2 = parts[1]; let outcome = parts[2]; match outcome { "win" => { add_game_result(&mut results, team1.to_string(), GameResult::Win); add_game_result(&mut results, team2.to_string(), GameResult::Loss); } "draw" => { add_game_result(&mut results, team1.to_string(), GameResult::Draw); add_game_result(&mut results, team2.to_string(), GameResult::Draw); } "loss" => { add_game_result(&mut results, team1.to_string(), GameResult::Loss); add_game_result(&mut results, team2.to_string(), GameResult::Win); } _ => (), // Ignore bad lines } } write_tally(&results) } fn write_tally(results: &HashMap<String, TeamResult>) -> String { let mut v: Vec<_> = results .iter() .map(|(team, r)| { let games = r.wins + r.draws + r.losses; let points = r.wins * 3 + r.draws; (team, games, r, points) }) .collect(); // Sort by points descending, then name A-Z. v.sort_by(|a, b| match a.3.cmp(&(b.3)).reverse() { Equal => a.0.cmp(&(b.0)), other => other, }); let mut lines = vec![format!("{:30} | MP | W | D | L | P", "Team")]; lines.extend(v.iter().map(|&(ref team, games, r, points)| { format!( "{:30} | {:2} | {:2} | {:2} | {:2} | {:2}", team, games, r.wins, r.draws, r.losses, points ) })); lines.join("\n") } fn add_game_result(results: &mut HashMap<String, TeamResult>, team: String, result: GameResult) { results .entry(team) .or_insert(TeamResult::new()) .add_game_result(result); } #}