Avatar of TASHBOLOTOFF

TASHBOLOTOFF's solution

to Tournament in the Java Track

Published at May 08 2019 · 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.

Setup

Go through the setup instructions for Java to install the necessary dependencies:

https://exercism.io/tracks/java/installation

Running the tests

You can run all the tests for an exercise by entering the following in your terminal:

$ gradle test

Use gradlew.bat if you're on Windows

In the test suites all tests but the first have been skipped.

Once you get a test passing, you can enable the next one by removing the @Ignore("Remove to run test") annotation.

Submitting Incomplete Solutions

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

TournamentTest.java

import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class TournamentTest {

    private Tournament tournament;

    @Before
    public void setUp() {
        tournament = new Tournament();
    }

    @Test
    public void justTheHeaderIfNoInput() {
        assertEquals("Team                           | MP |  W |  D |  L |  P\n", tournament.printTable());
    }

    @Ignore("Remove to run test")
    @Test
    public void aWinIsThreePointsALossIsZeroPoints() {
        tournament.applyResults("Allegoric Alaskans;Blithering Badgers;win");
        assertEquals(
                "Team                           | MP |  W |  D |  L |  P\n" +
                "Allegoric Alaskans             |  1 |  1 |  0 |  0 |  3\n" +
                "Blithering Badgers             |  1 |  0 |  0 |  1 |  0\n",
                tournament.printTable());
    }

    @Ignore("Remove to run test")
    @Test
    public void aWinCanAlsoBeExpressedAsALoss() {
        tournament.applyResults("Blithering Badgers;Allegoric Alaskans;loss");
        assertEquals(
                "Team                           | MP |  W |  D |  L |  P\n" +
                "Allegoric Alaskans             |  1 |  1 |  0 |  0 |  3\n" +
                "Blithering Badgers             |  1 |  0 |  0 |  1 |  0\n",
                tournament.printTable());
    }

    @Ignore("Remove to run test")
    @Test
    public void aDifferentTeamCanWin() {
        tournament.applyResults("Blithering Badgers;Allegoric Alaskans;win");
        assertEquals(
                "Team                           | MP |  W |  D |  L |  P\n" +
                "Blithering Badgers             |  1 |  1 |  0 |  0 |  3\n" +
                "Allegoric Alaskans             |  1 |  0 |  0 |  1 |  0\n",
                tournament.printTable());
    }

    @Ignore("Remove to run test")
    @Test
    public void aDrawIsOnePointEach() {
        tournament.applyResults("Allegoric Alaskans;Blithering Badgers;draw");
        assertEquals(
                "Team                           | MP |  W |  D |  L |  P\n" +
                "Allegoric Alaskans             |  1 |  0 |  1 |  0 |  1\n" +
                "Blithering Badgers             |  1 |  0 |  1 |  0 |  1\n",
                tournament.printTable());
    }

    @Ignore("Remove to run test")
    @Test
    public void thereCanBeMoreThanOneMatch() {
        tournament.applyResults(
                "Allegoric Alaskans;Blithering Badgers;win\n" +
                "Allegoric Alaskans;Blithering Badgers;win");
        assertEquals(
                "Team                           | MP |  W |  D |  L |  P\n" +
                "Allegoric Alaskans             |  2 |  2 |  0 |  0 |  6\n" +
                "Blithering Badgers             |  2 |  0 |  0 |  2 |  0\n",
                tournament.printTable());
    }

    @Ignore("Remove to run test")
    @Test
    public void thereCanBeMoreThanOneWinner() {
        tournament.applyResults(
                "Allegoric Alaskans;Blithering Badgers;loss\n" +
                "Allegoric Alaskans;Blithering Badgers;win");
        assertEquals(
                "Team                           | MP |  W |  D |  L |  P\n" +
                "Allegoric Alaskans             |  2 |  1 |  0 |  1 |  3\n" +
                "Blithering Badgers             |  2 |  1 |  0 |  1 |  3\n",
                tournament.printTable());
    }

    @Ignore("Remove to run test")
    @Test
    public void thereCanBeMoreThanTwoTeams() {
        tournament.applyResults(
                "Allegoric Alaskans;Blithering Badgers;win\n" +
                "Blithering Badgers;Courageous Californians;win\n" +
                "Courageous Californians;Allegoric Alaskans;loss");
        assertEquals(
                "Team                           | MP |  W |  D |  L |  P\n" +
                "Allegoric Alaskans             |  2 |  2 |  0 |  0 |  6\n" +
                "Blithering Badgers             |  2 |  1 |  0 |  1 |  3\n" +
                "Courageous Californians        |  2 |  0 |  0 |  2 |  0\n",
                tournament.printTable());
    }

    @Ignore("Remove to run test")
    @Test
    public void typicalInput() {
        tournament.applyResults(
                "Allegoric Alaskans;Blithering Badgers;win\n" +
                "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");
        assertEquals(
                "Team                           | MP |  W |  D |  L |  P\n" +
                "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\n",
                tournament.printTable());
    }

    @Ignore("Remove to run test")
    @Test
    public void incompleteCompetition() {
        tournament.applyResults(
                "Allegoric Alaskans;Blithering Badgers;loss\n" +
                "Devastating Donkeys;Allegoric Alaskans;loss\n" +
                "Courageous Californians;Blithering Badgers;draw\n" +
                "Allegoric Alaskans;Courageous Californians;win");
        assertEquals(
                "Team                           | MP |  W |  D |  L |  P\n" +
                "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\n",
                tournament.printTable());
    }

    @Ignore("Remove to run test")
    @Test
    public void tiesBrokenAlphabetically() {
        tournament.applyResults(
                "Courageous Californians;Devastating Donkeys;win\n" +
                "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");
        assertEquals(
                "Team                           | MP |  W |  D |  L |  P\n" +
                "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\n",
                tournament.printTable());
    }
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class Tournament {
    private final static String HEADER = "Team                           | MP |  W |  D |  L |  P\n";
    private List<Team> teams = new ArrayList<>();

    void applyResults(String results) {
        Arrays.stream(results.split("\n")).forEach(this::applyResult);
    }

    private void applyResult(String result) {
        String[] parts = result.split(";");
        if (parts.length != 3) {
            throw new IllegalArgumentException();
        }
        Team firstTeam = getTeam(parts[0]);
        Team secondTeam = getTeam(parts[1]);
        switch (parts[2]) {
            case "win":
                firstTeam.wins++;
                secondTeam.losses++;
                break;
            case "draw":
                firstTeam.draws++;
                secondTeam.draws++;
                break;
            case "loss":
                firstTeam.losses++;
                secondTeam.wins++;
                break;
        }
    }

    private Team getTeam(String name) {
        Team team = teams.stream().filter(t -> t.name.equals(name)).findFirst().orElse(new Team(name));
        if (!teams.contains(team)) {
            teams.add(team);
        }
        return team;
    }

    String printTable() {
        return HEADER + teams.stream().sorted().map(Team::printRow).collect(Collectors.joining());
    }

    private class Team implements Comparable<Team> {
        private String name;
        private int wins;
        private int draws;
        private int losses;

        private Team(String name) {
            this.name = name;
            wins = draws = losses = 0;
        }

        private int getPoints() {
            return 3 * wins + draws;
        }

        private String printRow() {
            String name = this.name + String.join("", Collections.nCopies(30 - this.name.length(), " "));
            int matches = wins + draws + losses;
            return String.format("%2$s%1$s%3$s%1$s%4$s%1$s%5$s%1$s%6$s%1$s%7$s\n",
                    " |  ", name, matches, wins, draws, losses, getPoints());
        }

        @Override
        public int compareTo(Team team) {
            int diff = team.getPoints() - getPoints();
            return diff == 0 ? name.compareTo(team.name) : diff;
        }

        @Override
        public boolean equals(Object obj) {
            return obj != null && (this == obj || this.name.equals(((Team) obj).name));
        }

        @Override
        public int hashCode() {
            return name.hashCode();
        }
    }
}

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?