I haven't used C++ for quite a while and wanted to practice a bit, so I decided to start simple and work through the Advent of Code 2017.
This is my solution to Part 1 of the Day 1 exercise "Inverse Captcha":
The captcha requires you to review a sequence of digits (your puzzle input) and find the sum of all digits that match the next digit in the list. The list is circular, so the digit after the last digit is the first digit in the list.
For example:
1122
produces a sum of 3 (1 + 2) because the first digit (1) matches the second digit and the third digit (2) matches the fourth digit.1111
produces 4 because each digit (all 1) matches the next.1234
produces 0 because no digit matches the next.91212129
produces 9 because the only digit that matches the next one is the last digit, 9.
My program works as follows:
- Read one line from stdin
- Convert the line character-wise to a vector of decimal digits
- Calculate the sum of matching digits
- Write the result to stdout
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
// Convert the first line of the input stream to a vector of digits.
std::vector<int> read_digits(std::istream& input) {
std::string line;
std::getline(input, line);
std::vector<int> digits(line.size());
std::transform(
std::cbegin(line), std::cend(line), std::begin(digits),
[](char c) { return c - '0'; }
);
return digits;
}
// Return the sum of all digits in the list that match the next digit
// (the first digit is the "next" digit of the last digit).
int reverse_captcha(const std::vector<int>& digits) {
int sum = 0;
for (auto p = std::begin(digits); p != std::end(digits); p++) {
auto next_p =
(std::next(p) == std::end(digits)) ?
std::begin(digits) : std::next(p);
if (*p == *next_p) sum += *p;
}
return sum;
}
int main() {
std::cout << reverse_captcha(read_digits(std::cin)) << '\n';
}
I'm compiling it with clang++-4.0 -std=c++14
. I'm not sure if I actually use features of the newest standard, but I don't want to restrict myself to older versions.
Here are a few things I'm particularly curious about:
How can I separate iterating over the pairs of digits from calculating their sum if the pairs are equal? If I were using Python I would write one or two small generator functions, but I don't know yet if there is an equally simple way to do this in C++, or if this would become overkill.
Is there an elegant way to avoid the extra step of constructing a string
line
before creating the vector of digits?Using
- '0'
for convertingchar
→int
feels like a hack to me, is there really no purpose-built function for this? (I'm used toint('5')
→5
from Python)
return {std::istream_iterator<char>{}, {}};
inread_digits
. If I remember correctly, constructor should not complain. \$\endgroup\$input
(orline
?) and where would I put the conversion fromchar('5')
toint(5)
? \$\endgroup\$char
never skips anything, and reads one character from input stream. \$\endgroup\$