🎉 Exercism Research is now launched. Help Exercism, help science and have some fun at research.exercism.io 🎉
Avatar of katrinleinweber

katrinleinweber's solution

to Tournament in the R Track

Published at Jul 13 2018 · 0 comments
Instructions
Test suite
Solution

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:

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 should be ordered by points, descending. In case of a tie, teams are ordered alphabetically.

Input

Your tallying program will receive input that looks like:

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

Allegoric Alaskans;Blithering Badgers;win

Means that the Allegoric Alaskans beat the Blithering Badgers.

This line:

Courageous Californians;Blithering Badgers;loss

Means that the Blithering Badgers beat the Courageous Californians.

And this line:

Devastating Donkeys;Courageous Californians;draw

Means that the Devastating Donkeys and Courageous Californians tied.

Installation

See this guide for instructions on how to setup your local R environment.

How to implement your solution

In each problem folder, there is a file named <exercise_name>.R containing a function that returns a NULL value. Place your implementation inside the body of the function.

How to run tests

Inside of RStudio, simply execute the test_<exercise_name>.R script. This can be conveniently done with testthat's auto_test function. Because exercism code and tests are in the same folder, use this same path for both code_path and test_path parameters. On the command-line, you can also run Rscript test_<exercise_name>.R.

Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

test_tournament.R

source("./tournament.R")
library(testthat)

context("tournament")

options(stringsAsFactors = FALSE)

test_that("typical input", {
  input <- c(
    "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"
  )
  expect_equal(tournament(input),
               data.frame(
                 Team = c(
                   "Devastating Donkeys",
                   "Allegoric Alaskans",
                   "Blithering Badgers",
                   "Courageous Californians"
                 ),
                 MP = c(3, 3, 3, 3),
                 W = c(2, 2, 1, 0),
                 D = c(1, 0, 0, 1),
                 L = c(0, 1, 2, 2),
                 P = c(7, 6, 3, 1)
               ))
})

test_that("incomplete competition (not all pairs have played)", {
  input <- c(
    "Allegoric Alaskans;Blithering Badgers;loss",
    "Devastating Donkeys;Allegoric Alaskans;loss",
    "Courageous Californians;Blithering Badgers;draw",
    "Allegoric Alaskans;Courageous Californians;win"
  )
  expect_equal(tournament(input),
               data.frame(
                 Team = c(
                   "Allegoric Alaskans",
                   "Blithering Badgers",
                   "Courageous Californians",
                   "Devastating Donkeys"
                 ),
                 MP = c(3, 2, 2, 1),
                 W = c(2, 1, 0, 0),
                 D = c(0, 1, 1, 0),
                 L = c(1, 0, 1, 1),
                 P = c(6, 4, 1, 0)
               ))
})

test_that("ties broken alphabetically", {
  input <- c(
    "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"
  )
  expect_equal(tournament(input),
               data.frame(
                 Team = c(
                   "Allegoric Alaskans",
                   "Courageous Californians",
                   "Blithering Badgers",
                   "Devastating Donkeys"
                 ),
                 MP = c(3, 3, 3, 3),
                 W = c(2, 2, 0, 0),
                 D = c(1, 1, 1, 1),
                 L = c(0, 0, 2, 2),
                 P = c(7, 7, 1, 1)
               ))
})

test_that("an empty line", {
  input <- c(
    "Allegoric Alaskans;Blithering Badgers;loss",
    "Devastating Donkeys;Allegoric Alaskans;loss",
    "",
    "Courageous Californians;Blithering Badgers;draw",
    "Allegoric Alaskans;Courageous Californians;win"
  )
  expect_equal(tournament(input),
               data.frame(
                 Team = c(
                   "Allegoric Alaskans",
                   "Blithering Badgers",
                   "Courageous Californians",
                   "Devastating Donkeys"
                 ),
                 MP = c(3, 2, 2, 1),
                 W = c(2, 1, 0, 0),
                 D = c(0, 1, 1, 0),
                 L = c(1, 0, 1, 1),
                 P = c(6, 4, 1, 0)
               ))
})

test_that("wrong separator used", {
  input <- c(
    "Allegoric Alaskans;Blithering Badgers;loss",
    "Devastating Donkeys;Allegoric Alaskans;loss",
    "Courageous Californians;Blithering Badgers;draw",
    "Devastating Donkeys@Courageous Californians;draw",
    "Allegoric Alaskans;Courageous Californians;win"
  )
  expect_equal(tournament(input),
               data.frame(
                 Team = c(
                   "Allegoric Alaskans",
                   "Blithering Badgers",
                   "Courageous Californians",
                   "Devastating Donkeys"
                 ),
                 MP = c(3, 2, 2, 1),
                 W = c(2, 1, 0, 0),
                 D = c(0, 1, 1, 0),
                 L = c(1, 0, 1, 1),
                 P = c(6, 4, 1, 0)
               ))
})

test_that("too many separators", {
  input <- c(
    "Allegoric Alaskans;Blithering Badgers;loss",
    "Devastating Donkeys;Courageous Californians;draw;5",
    "Devastating Donkeys;Allegoric Alaskans;loss",
    "Courageous Californians;Blithering Badgers;draw",
    "Allegoric Alaskans;Courageous Californians;win"
  )
  expect_equal(tournament(input),
               data.frame(
                 Team = c(
                   "Allegoric Alaskans",
                   "Blithering Badgers",
                   "Courageous Californians",
                   "Devastating Donkeys"
                 ),
                 MP = c(3, 2, 2, 1),
                 W = c(2, 1, 0, 0),
                 D = c(0, 1, 1, 0),
                 L = c(1, 0, 1, 1),
                 P = c(6, 4, 1, 0)
               ))
})

test_that("invalid match result", {
  input <- c(
    "Allegoric Alaskans;Blithering Badgers;loss",
    "Devastating Donkeys;Allegoric Alaskans;loss",
    "Courageous Californians;Blithering Badgers;draw",
    "Allegoric Alaskans;Courageous Californians;win",
    "Devastating Donkeys;Allegoric Alaskans;dra"
  )
  expect_equal(tournament(input),
               data.frame(
                 Team = c(
                   "Allegoric Alaskans",
                   "Blithering Badgers",
                   "Courageous Californians",
                   "Devastating Donkeys"
                 ),
                 MP = c(3, 2, 2, 1),
                 W = c(2, 1, 0, 0),
                 D = c(0, 1, 1, 0),
                 L = c(1, 0, 1, 1),
                 P = c(6, 4, 1, 0)
               ))
})

message("All tests passed for exercise: tournament")
library(dplyr)
library(magrittr)

tournament <- function(input) {

  # clean input data (oust empty rows) & parse
  input[lapply(input, nchar) > 0] %>%  
    stringi::stri_split_fixed(";") ->
    input
  
  # oust lines with incorrect number of cells
  input <- input[lapply(input, length) == 3]
  
  df <- data.frame()
  for (r in 1:length(input))
    for (c in 1:length(input[[r]]))
      df[r, c] <- input[[r]][c]
  names(df) <- c("Team", "Team2", "Result")
  
  # separate team pairs, marking invalid result strings
  df$Result %>% 
    purrr::map_chr(function(x) case_when(x == "loss" ~ "win",
                                     x == "win" ~ "loss",
                                     x == "draw" ~ "draw",
                                     x != "draw" ~ "NA")) %>% 
    data.frame(df$Team2, .) -> 
    df2
  names(df2) <- c("Team", "Result")
  
  # oust rows with invalid results/cells
  df2 <- df2[df2$Result != "NA",]
  
  # calculate values & output data frame
  df$Team2 <- NULL
  df %>% 
    rbind(df2) %>% 
    mutate(W = ifelse(Result == "win", 1, 0),
           D = ifelse(Result == "draw", 1, 0),
           L = ifelse(Result == "loss", 1, 0),
           MP = W + D + L,
           P = 3 * W + D) %>% 
    select(-Result) %>% 
    group_by(Team) %>% 
    summarise_all(sum) %>% 
    select(Team, MP, W:P) %>% 
    arrange(desc(P))
}

Community comments

Find this solution interesting? Ask the author a question to learn more.

What can you learn from this solution?

A huge amount can be learned from reading other people’s code. This is why we wanted to give exercism users the option of making their solutions public.

Here are some questions to help you reflect on this solution and learn the most from it.

  • What compromises have been made?
  • Are there new concepts here that you could read more about to improve your understanding?