Rock Paper Scissors
Parsing and comparing strings in C.
Last updated
Parsing and comparing strings in C.
Last updated
The full description can be found in RockPaperScissors.zip
.
You are provided a list of data input.txt that contains a list of Rock Paper Scissors games. Each line contains the enemy's move (A
for Rock, B
for Paper, and C
for Scissors) and our move (X
for Rock, Y
for Paper, and Z
for Scissors).
This game comes in two parts:
The score for a round is the score for the shape you selected (1 for Rock, 2 for Paper, and 3 for Scissors), plus the score of the outcome round (0 if you lose, 3 if you draw, and 6 if you win).
The setup of the game changes. The second column indicates how the round needs to end. X
meaning a loss, Y
meaning a draw, and Z
meaning a win.
Each part's answer will be the total score if everything follows the guidelines. Submit your final answer in the form flag{Part1_Part2}
where Part1
and Part2
are the answers for each part.
If you're still confused on what's going on here, check the full problem description. It runs some sample testing cases for the challenge so you understand how to compute the totals.
For each problem, we'll follow the same template. We'll break it down into the following steps:
Choose our data structure for the challenge based on our end goal.
Open the file and initialize our necessary structures.
Read each line of the file and process the data into the data structure.
Process the data structure to get our answer.
We'll work on each of these in turn.
For this challenge, our end goal is to get the total score across the round. Since each round is independent, we don't need to store each round's score. All we need is a running total score for each round. We can do this with a single (unsigned) integer for each round.
We'll find that when we do this challenge, it's easier to do these parts independently. There's not much comparable information other than reading the file, so we'll handle each part separately.
In this stage, we'll prepare to read the data. We'll do this the same way we do this in CalorieCounting.
Note that this time, we don't need the ssize_t read
variable. We know the size of the data we're reading, so we don't need to store it.
Then, we just need to initialize the total score to 0.
We'll handle this one part at a time.
Part 1
For the first part, we are told the second value is the value the opponent plays. When we compare the two values, it will be easier to convert them to integers first. We can use the offset from A
or X
as the value for each player (meaning every move corresponds to a 0
, 1
, or 2
).
Why do we think to do this?
Numeric comparisons are typically easier to wrap our head around. Rather than making an if
statement with many checks, we can check for patterns with integers.
We can do the same thing for the user score as well. Since the user's move can be seen as 1 + offset
, we can add this offset to the total score.
We'll use the same logic as the previous challenge to loop through each line:
Each line, we can get the self and enemy scores. We'll convert them to integers
We'll add 1 + offset
for our move's portion of the total score.
Then, we need to handle the three cases. Let's think about what these cases are. Let's make a table subtracting the enemy
score from self
.
In this case, we notice the following:
Wins happen when the result is 1
or -2
.
Losses happen when the result is -1
or 2
.
Draws happen when the result is 0
.
We can simplify this into the following checks:
As a sanity check, we should never the code after all three checks. I put a printf("Bad\n");
statement at the end and make sure this doesn't get printed.
Once all the lines are iterated for this part, we can return the total score for that round.
Part 2
For the second part, we are told the second value is the game's outcome. X
is a loss, Y
is a draw, and Z
is a win.
There are many ways to approach this challenge. What made the most sense to me was to differentiate the win, loss, and draw cases. This time, because we're not comparing the two values, converting them into integers doesn't make much sense.
We'll use the same logic as the previous challenge to loop through each line:
Each line, we can get the self and enemy scores. We'll leave them as characters.
Since self
represents the score this time, we can add the score results to the total score. The score is three times the value of the score (since the score is 0
, 1
, or 2
).
Now, we can handle the three cases.
If the result is a loss (X
), and the enemy put A
, we put C
(score of 2
). For B
, we put A
; for C
, we put B
.
If the result is a draw, we can just use their score for ours.
If the result is a win, we'll follow a similar strategy to the loss case.
We shouldn't ever hit the else
case, but we'll put one just in case.
Once we've iterated the lines, we can return the total score.
I chose to make a function for each part. We'll define the main
function to call each part's function and print the result.
If we run this, we'll get the following output:
The full solution is below:
Enemy / Self | 0 | 1 | 2 |
---|---|---|---|
0
0 [D]
1 [W]
2 [L]
1
-1 [L]
0 [D]
1 [W]
2
-2 [W]
-1 [L]
0 [D]