Comp 101 March Madness - Part 1

March Madness - Part 1 (Bracket Builder)

In the Bracket Builder section of this problem set, you will be taking a shot at creating the perfect bracket for the Sweet 16 based off of historical data from the 2018 season. You will have access to various statistics about each team in the 2018 Sweet 16, and will use these to determine which teams move forward to the Elite 8, Final 4, National Championship, and who will ultimately take home the title. See how well your algorithm would have predicted the results of the 2018 March Madness Tournament!

Learning Objectives

After completing this part, you should be comfortable:

1. Using for loops to print out elements of an array

2. Creating arrays

3. Storing values in an array

4. Using values in from an array as indices for accessing elements in another array

5. Comparing and operating on values accessed from array

6. Making brackets that don’t get busted

Part 0. Starting the Dev Environment

As with in lecture, begin by opening up VSCode, ensuring your project is still open, and then running the following two commands in the VSCode Integrated Terminal:

 1. npm run pull

 2. npm start

The first command "pulls" the latest files needed for COMP101 into your repo. The second command starts the development environment and will open your web browser to the local server.

You should still see the folder called ps05-march-madness from Part 0. Inside it there will be a file called part1-data.ts. This contains arrays with the statistics you will need in this part of the problem set.

Part 1. Setting up the App

In the same directory used in lecture:

  1. Right click on the ps05-march-madness folder

  2. Select "New File"

  3. Name the new file: 01-bracket-builder-app.ts (Note: capitalization and punctuation are important!)

Part 2. Starting your Code

2.0 Honor Code Header

All problem sets begin with an Honor Code pledge. Notice this header is contained within block comment tags discussed in Lecture 1. You can copy paste the pledge below and fill in your name and ONYEN.

/**
 * Author:
 *
 * ONYEN:
 *
 * UNC Honor Pledge: I certify that no unauthorized assistance has been received
 * or given in the completion of this work. I certify that I understand and
 * could now rewrite on my own, without assistance from course staff,
 * the problem set code I am submitting.
 */

2.1 Imports

The next step after ensuring the honor code header is to import the functions we'll use from the introcs library and the arrays from our data file. The first lines of code to add to your app is the following:

import { print } from "introcs";
import { teamNames, pointsPerGame, turnoversPerGame, reboundsPerGame, assistsPerGame, totalFreeThrowsMade, totalFreeThrowsAttempted } from "./part1-data";

As discussed in lecture, importing allows us to reference variables and other code stored in separate files. Take a moment to open up the part1-data.ts file. You will see that all it contains are several array declarations that store the data we will be using in this assignment. We could have put this code in 01-bracket-builder-app.ts, but we separate it into another file in order to keep our project a little more organized!

2.2 The main Function

Your program's execution will begin in a special function named `main`. Inside this function, you will put all of your code. It will run once main is called (main();).

export let main = async () => {   
// TODO: Put all of your code here
};
main();

Part 3: Sweet 16

What’s the point of basketball without points?

In Part 3, you will be advancing teams from the Sweet 16 to the Elite 8 based on which teams have the higher number of points scored per game this season.

Part 3.0: Print the teams in the Sweet 16

First, print the following string: “==== Teams in Sweet 16 ====”.

Then, write a for loop that prints each string in the array teamNames.

After doing this, you should see “==== Teams in Sweet 16 ====” followed by the names of the 16 teams still in the tournament (each on a separate line).

Part 3.1: Create an array to hold the indices of teams that will be in the Elite 8

The arrays we imported from part1-data.ts each contain 16 elements. Since “Kansas State” is the first element in teamNames, the first element in pointsPerGame is the number of points that Kansas State averages per game as a team. The second element in pointsPerGame is the number of points that Kentucky averages per game because the second element of teamNames is “Kentucky.”

The same pattern applies to the rest of the statistic arrays (i.e. the nth item in an array of stats corresponds to the nth team in the teamNames array).

Therefore, we will be keeping track of the indices of the team names in teamNames when we advance a team to the next round. For example, if Kentucky wins in the Sweet 16, all we need to keep track of is the index of “Kentucky” in teamNames (which happens to be 1).

Create an empty number array named elite8teamIndices. This array will be where we store the indices of the team names for the teams that advance to the Elite 8.

Part 3.2: Create the for loop

Write a for loop that will run while your counter variable (i) is less than 16, but that increments your counter by two after each iteration (instead of one).

We want to do this because we will be deciding whether team 0 or 1 will advance, whether 2 or 3 will advance, and so on. If i is your counter variable, each iteration can be thought of as a game between teams i and i + 1.

In this round, we have 16 teams and 8 games.

Part 3.3: Advance the team with the greater number of points scored per game

Within the for loop you created in Part 3.2, we want to compare the points scored per game for teams i and i + 1 (remember that this is simply referring to the teams whose names are at locations i and i + 1 in the teamNames array), and advance the team with the higher number of points scored per game.

You will do this by storing i in the elite8teamIndices array you created in Part 3.1 if pointsPerGame[i] > pointsPerGame[i + 1], and i + 1 otherwise. However, since the elite8teamIndices array will ultimately contain eight teams, we need to store the index of the team that won at index i / 2 in elite8teamIndices.

If this seems confusing, imagine that i is 6. This means we are determining whether team 6 or 7 will be advancing. This is the fourth game being played (the first three were teams 0/1, 2/3, and 4/5), so the winner should be the fourth element in elite8teamIndices. That is index 3, which is 6 / 2. We never have to worry about i being an odd number because each time through the loop we add 2 to i.

Construct an if-statement that stores i at index i / 2 in the elite8teamIndices array if pointsPerGame[i] > pointsPerGame[i + 1], and that stores i + 1 at index i / 2 otherwise (you can assume there will be no ties).

This process looks like:

 

Part 4: Elite 8

Turnovers = Game Over.

In Part 4 you will be advancing teams from the Elite 8 to the Final 4 based on which teams have the lower number of turnovers per game this season.

Part 4.0: Print the teams in the Elite 8

At this point, elite8teamIndices contains the indices of the teams in the Elite 8. Remember that these indices correspond to the names of the teams in the teamNames array who have advanced to the Elite 8. Additionally, these indices correspond to the indices of these teams’ statistics in the other arrays you imported from “04-sprint-data.ts” (like turnoversPerGame).

Now, print the following string: “==== Teams in Elite 8 ====”.

You know that elite8teamIndices contains the indices of the teams in the Elite 8, which correspond to the names of those teams in the teamNames array. Therefore, writing:

print(teamNames[elite8teamIndices[0]]);

would result in “Kentucky” being printed if Kentucky won the first game in the Sweet 16, because elite8teamIndices[0] would contain the value 1 (the index of “Kentucky” in teamNames), and teamNames[1] is “Kentucky”.

Knowing this, write a for loop that prints the names of all the teams that have advanced to the Elite 8.

After doing this, you should see “==== Teams in Elite 8 ====” followed by the names of the 8 teams still in the tournament (each on a separate line).

Part 4.1: Create an array to hold the indices of teams that will be in the Final 4

Create an empty number array named final4teamIndices. This array will be where we store the indices of the team names for the teams that advance to the Final 4, just like we did with elite8teamIndices in Part 3.

Part 4.2: Create the for loop

Write a for loop that will run while your counter variable is less than 8, but that increments your counter by two after each iteration.

If i is your counter variable, each iteration can be thought of as a game between teams elite8teamIndices[i] and elite8teamIndices[i + 1]. Note that this is different from Part 3 because i and i + 1 are no longer the indices of the teams playing. Since the teams that advanced to the Elite 8 are stored in elite8teamIndices, each iteration is a game between the teams at locations i and i + 1 in the elite8teamIndices array.

In this round, we have 8 teams and 4 games.

Part 4.3: Advance the team with the fewest number of turnovers per game

Within the for loop you created in Part 4.2, we want to compare the turnovers per game for teams elite8teamIndices[i] and elite8teamIndices[i + 1] (remember that this is referring to the teams whose names are at locations elite8teamIndices[i] and elite8teamIndices[i + 1] in the teamNames array), and advance the team with the smaller value.

You will do this by storing elite8teamIndices[i] in the final4teamIndices array you created in Part 4.1 if turnoversPerGame[elite8teamIndices[i]] is less than turnoversPerGame[elite8teamIndices[i + 1]], and elite8teamIndices[i + 1] otherwise. Since the final4teamIndices array will ultimately contain four teams, we need to store the index of the team that won at index i / 2 in final4teamIndices. For this part, there might be instances where teams have an equal number of turnovers per game -- if this is the case, the second team wins (elite8teamIndices[i + 1]).

 

Part 5: Final 4

Assists and rebounds win games.

In Part 5 you will be advancing teams from the Final 4 to the National Championship based on which teams have the higher number of combined assists and rebounds per game this season.

Part 5.0: Print the teams in the Final 4

At this point, final4teamIndices contains the indices of the teams in the Final 4. Remember that these indices correspond to the names of the teams in the teamNames array who have advanced to the Final 4. Additionally, these indices correspond to the indices of these teams’ statistics in the other arrays you imported from “04-sprint-data.ts” (like reboundsPerGame and assistsPerGame).

Now, print the following string: “==== Teams in Final 4 ====”.

You know that final4teamIndices contains the indices of the teams in the Final 4, which correspond to the names of those teams in the teamNames array. Therefore, writing:

print(teamNames[final4teamIndices[0]]);

would result in “Nevada” being printed if Nevada won the first game in the Elite 8, because final4teamIndices[0] would contain the value 3 (the index of “Nevada” in teamNames), and teamNames[3] is “Nevada”.

Now, write a for loop that prints the names of all the teams that have advanced to the Final 4.

After doing this, you should see “==== Teams in Final 4 ====” followed by the names of the 4 teams still in the tournament (each on a separate line).

Part 5.1: Create an array to hold the indices of teams that will be in the National Championship

Create an empty number array named nationalChampionshipTeamIndices. This array will be where we store the indices of the team names for the teams that advance to the National Championship, just like we did with final4teamIndices in Part 4.

Part 5.2: Create the for loop

Write a for loop that will run while your counter variable is less than 4, but that increments your counter by two after each iteration.

If i is your counter variable, each iteration can be thought of as a game between teams final4teamIndices[i] and final4teamIndices[i + 1]. Since the teams that advanced to the Final 4 are stored in final4teamIndices, each iteration is a game between the teams at locations i and i + 1 in the final4teamIndices array.

In this round, we have 4 teams and 2 games.

Part 5.3: Advance the team with the greatest combined rebounds per game and assists per game

Within the for loop you created in Part 5.2, we want to compare the combined rebounds and assists per game for teams final4teamIndices[i] and final4teamIndices[i + 1] (remember that this is referring to the teams whose names are at locations final4teamIndices[i] and final4teamIndices[i + 1] in the teamNames array), and advance the team with the larger value.

You will do this by storing final4teamIndices[i] in the nationalChampionshipTeamIndices array you created in Part 5.1 if the sum of reboundsPerGame[final4teamIndices[i]] and assistsPerGame[final4teamIndices[i]] is larger than the sum of reboundsPerGame[final4teamIndices[i + 1]] and assistsPerGame[final4teamIndices[i + 1]], and final4teamIndices[i + 1] otherwise.

However, since the nationalChampionshipTeamIndices array will ultimately contain two teams, we need to store the index of the team that won at index i / 2 in nationalChampionshipTeamIndices.

 

Part 6: National Championship!

Free throws are HUGE in the last minute of any game.

In Part 6 you will be determining a National Champion based on which teams have the highest free throw percentage for the season.

Part 6.0: Print the teams in the National Championship

At this point, nationalChampionshipTeamIndices contains the indices of the teams in the National Championship. Remember that these indices correspond to the names of the teams in the teamNames array who have advanced to the championship. Additionally, these indices correspond to the indices of these teams’ statistics in the other arrays you imported from “04-sprint-data.ts”.

Now, print the following string: “==== Teams in National Championship ====”.

You know that nationalChampionshipTeamIndices contains the indices of the teams in the National Championship, which correspond to the names of those teams in the teamNames array. Therefore, writing:

print(teamNames[nationalChampionshipTeamIndices[0]]);

would result in “Nevada” being printed if Nevada won the first game in the Final 4 (they might not have), because nationalChampionshipTeamIndices[0] would contain the value 3 (the index of “Nevada” in teamNames), and teamNames[3] is “Nevada”.

Now, write a for loop that prints the names of all the teams that have advanced to the National Championship.

After doing this, you should see “==== Teams in National Championship ====” followed by the names of the 2 teams still in the tournament (each on a separate line).

Part 6.1: Create a number variable to hold the index of the team that will be the National Champion

Create a number variable named nationalChampionIndex. This number will be where we store the index of the team name for the team that wins the National Championship.

Part 6.2: Determine the National Champion based on free throw percentage

We want to compare the percent of free throws made out of free throws attempted for teams nationalChampionshipTeamIndices[0] and nationalChampionshipTeamIndices[1] (remember that this is referring to the teams whose names are at locations nationalChampionshipTeamIndices[0] and nationalChampionshipTeamIndices[1] in the teamNames array), and advance the team with the larger value.

You will do this by storing nationalChampionshipTeamIndices[0] in the nationalChampionIndex variable you created in Part 6.1 if totalFreeThrowsMade[nationalChampionshipTeamIndices[0]] / totalFreeThrowsAttempted[nationalChampionshipTeamIndices[0]] is larger than totalFreeThrowsMade[nationalChampionshipTeamIndices[1]] / totalFreeThrowsAttempted[nationalChampionshipTeamIndices[1]], and nationalChampionshipTeamIndices[1] otherwise.

 

Part 6.3: Print the name of the National Champion team

At this point, nationalChampionIndex contains the index of the team that won the National Championship.

Print “The National Champion is: <name>, where <name> is replaced by the name of the team at location nationalChampionIndex in teamNames.

You should now see the teams in each round printed out, including the National Champion.

You’ve found the National Champion! How accurate was your program's predictions versus the actual results? Can you make any modifications to your program to improve it's performance? (Once you’ve published and submitted for full credit, of course!)

Part 6.4: Publish your app.

With your program running in your web browser, find the green "Publish App" button. If you are not still logged into introcs.com, you will be prompted to log in, and then your app will be bundled and published to the web!

Part 6.5: Submit for grading

Once the grader is available, to submit for grading, first publish your project as per Part 6.4. Then, go to My101 in the top-right right corner of this page and select "Submit" next to the assignment. From here you should see a button that allows you to submit for grading. Your work will be graded through an automated process. If you receive points off, please select the "Report" link to see which tests did not pass. You can resubmit as many times as you'd like without penalty up until the deadline. We want you to keep working toward full credit on problem sets!