-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathday04.cpp
More file actions
151 lines (120 loc) · 4.3 KB
/
day04.cpp
File metadata and controls
151 lines (120 loc) · 4.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include "day04.h"
#include <fstream>
#include <iostream>
#include <cmath>
#include <numeric>
#include <string>
#include <sstream>
#include <vector>
namespace day04
{
int solvePart1(std::ifstream& file);
int solvePart2(std::ifstream& file);
void run_day(bool example)
{
std::cout << "Running day 04 \n";
const std::string fileName{ example ? "inputs/day04_example.txt" : "inputs/day04_real.txt" };
std::ifstream file{ fileName };
int sum{ solvePart1(file) };
std::cout << "Part 1 answer: " << sum << '\n';
file.close();
file.open(fileName);
sum = solvePart2(file);
std::cout << "Part 2 answer: " << sum << '\n';
}
std::vector<std::pair<std::vector<bool>, std::vector<int>>> parseInput(std::ifstream& file)
{
// Input parsing uses fact that nrs are all <100 to create 100-long array to hold bools marking
// winning numbers.
// For nr of numbers per game, look at first line
std::string line;
std::getline(file, line);
const size_t nrOfNumbers{ (line.size() - line.find('|') - 1) / 3 };
// For nr of lines loop over lines and count:
size_t nrOfLines{1};
while (std::getline(file, line))
{
nrOfLines++;
}
// Create outer vector
std::vector<std::pair<std::vector<bool>, std::vector<int>>> input(nrOfLines);
// Reset file stream
file.clear();
file.seekg(0);
// Read in each line of file
unsigned int currentLineIndex{};
while (std::getline(file, line))
{
std::vector<bool> winningForLine(100, false);
std::vector<int> numbersForLine(nrOfNumbers);
std::stringstream lineStream;
std::string placeHolder{};
lineStream << line;
// Could also be constant removal of start of string, but let's stick to stream manipulation
lineStream >> placeHolder >> placeHolder;
unsigned int nextNr;
lineStream >> nextNr; // Resharper seems to think this is invalid...
while (!lineStream.fail())
{
winningForLine[nextNr] = true;
lineStream >> nextNr;
}
lineStream.clear();
unsigned int index{ 0 };
lineStream >> placeHolder;
lineStream >> nextNr;
while (!lineStream.fail())
{
numbersForLine[index] = static_cast<int>(nextNr);
lineStream >> nextNr;
index++;
}
const std::pair linePair{ winningForLine, numbersForLine };
input[currentLineIndex] = linePair;
currentLineIndex++;
}
return input;
}
int solvePart1(std::ifstream& file)
{
const auto input = parseInput(file);
int sum{ 0 };
for (auto& line : input)
{
// Count nr of wins on line.
int lineWinning{ 0 };
for (int number : line.second)
if (line.first[static_cast<unsigned int>(number)])
lineWinning++;
// Calculate line score (=2^(n-1)).
if (lineWinning > 0)
sum += static_cast<int>(std::pow(2, lineWinning - 1));
}
return sum;
}
int solvePart2(std::ifstream& file)
{
const auto input = parseInput(file);
// Start out with 1 of each scratchCard.
std::vector<int> nrOfEachCard(input.size(), 1);
unsigned int lineIndex{ 0 };
for (auto& line : input)
{
int lineWinning{ 0 };
for (const int number : line.second)
if (line.first[static_cast<unsigned int>(number)])
lineWinning++;
// Up all upcoming cards based on nr of wins this line, each goes up by nr of current line.
for (int i = 1; i <= lineWinning; i++)
{
if (lineIndex + i >= input.size())
// Going past last card
break;
nrOfEachCard[lineIndex + i] += nrOfEachCard[lineIndex];
}
lineIndex++;
}
// Return sum of count of each card.
return std::accumulate(nrOfEachCard.begin(), nrOfEachCard.end(), 0);
}
}