308 lines
6.3 KiB
C++
308 lines
6.3 KiB
C++
//Fun/AdventCalendar2020/Day4-2.cpp
|
|
//Matthew Ellison
|
|
// Created: 12-04-20
|
|
//Modified: 12-04-20
|
|
//Validate passport data
|
|
|
|
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <string>
|
|
#include <vector>
|
|
#include "Stopwatch.hpp"
|
|
#include "Algorithms.hpp"
|
|
|
|
|
|
struct passport{
|
|
std::string birthYear;
|
|
std::string issueYear;
|
|
std::string expirationYear;
|
|
std::string height;
|
|
std::string hairColor;
|
|
std::string eyeColor;
|
|
std::string passportId;
|
|
std::string countryId;
|
|
//Returns true if the passport is valid
|
|
bool isValid(){
|
|
if(birthYearIsValid() && issueYearIsValid() && expirationYearIsValid() && heightIsValid() && hairColorIsValid() && eyeColorIsValid() && passportIdIsValid()){
|
|
return true;
|
|
}
|
|
else{
|
|
return false;
|
|
}
|
|
}
|
|
//Returns true if the string is a valid string
|
|
bool validString(std::string str){
|
|
if(!str.empty()){
|
|
return true;
|
|
}
|
|
else{
|
|
return false;
|
|
}
|
|
}
|
|
bool birthYearIsValid(){
|
|
//There must be four digits
|
|
if(birthYear.size() != 4){
|
|
return false;
|
|
}
|
|
//That are all numbers
|
|
for(char ch : birthYear){
|
|
if(!std::isdigit(ch)){
|
|
return false;
|
|
}
|
|
}
|
|
//The number must be 1920 <= x <= 2002
|
|
int num = std::stoi(birthYear);
|
|
if((num < 1920) || (num > 2002)){
|
|
return false;
|
|
}
|
|
|
|
//If none of the other conditions were hit return true;
|
|
return true;
|
|
}
|
|
bool issueYearIsValid(){
|
|
//There must be four digits
|
|
if(issueYear.size() != 4){
|
|
return false;
|
|
}
|
|
//That are all numbers
|
|
for(char ch : issueYear){
|
|
if(!std::isdigit(ch)){
|
|
return false;
|
|
}
|
|
}
|
|
//The number must be 2010 <= x <= 2020
|
|
int num = std::stoi(issueYear);
|
|
if((num < 2010) || (num > 2020)){
|
|
return false;
|
|
}
|
|
|
|
//If none of the other conditions were hit return true;
|
|
return true;
|
|
}
|
|
bool expirationYearIsValid(){
|
|
//There must be four digits
|
|
if(expirationYear.size() != 4){
|
|
return false;
|
|
}
|
|
//That are all numbers
|
|
for(char ch : expirationYear){
|
|
if(!std::isdigit(ch)){
|
|
return false;
|
|
}
|
|
}
|
|
//The number must be 2020<= x <= 2030
|
|
int num = std::stoi(expirationYear);
|
|
if((num < 2020) || (num > 2030)){
|
|
return false;
|
|
}
|
|
|
|
//If none of the other conditions were hit return true;
|
|
return true;
|
|
}
|
|
bool heightIsValid(){
|
|
//It must be a number followed by 2 characters (in or cm)
|
|
//Split the string into digits and suffix
|
|
std::string numStr;
|
|
int num = 0;
|
|
std::string suffix;
|
|
int strLoc = 0;
|
|
for(;strLoc < height.size();++strLoc){
|
|
if(std::isdigit(height[strLoc])){
|
|
numStr += height[strLoc];
|
|
}
|
|
else{
|
|
break;
|
|
}
|
|
}
|
|
if(numStr.size() == 0){
|
|
return false;
|
|
}
|
|
num = std::stoi(numStr);
|
|
for(;strLoc < height.size();++strLoc){
|
|
if(std::isdigit(height[strLoc])){
|
|
return false;
|
|
}
|
|
else{
|
|
suffix += height[strLoc];
|
|
}
|
|
}
|
|
|
|
//If suffix is in 59 <= x <= 76
|
|
if(suffix == "in"){
|
|
if((num < 59) || (num > 76)){
|
|
return false;
|
|
}
|
|
else{
|
|
return true;
|
|
}
|
|
}
|
|
//If suffix is cm 150 <= x <= 193
|
|
else if(suffix == "cm"){
|
|
if((num < 150) || (num > 193)){
|
|
return false;
|
|
}
|
|
else{
|
|
return true;
|
|
}
|
|
}
|
|
else{
|
|
return false;
|
|
}
|
|
|
|
//If none of the other conditions were hit return true;
|
|
return true;
|
|
}
|
|
bool hairColorIsValid(){
|
|
//Contains 7 characters
|
|
if(hairColor.size() != 7){
|
|
return false;
|
|
}
|
|
//Start with #
|
|
if(hairColor[0] != '#'){
|
|
return false;
|
|
}
|
|
//Then 6 hex characters
|
|
for(int cnt = 1;cnt < hairColor.size();++cnt){
|
|
if(!std::isxdigit(hairColor[cnt])){
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//If none of the other conditions were hit return true;
|
|
return true;
|
|
}
|
|
bool eyeColorIsValid(){
|
|
//amb or blu or brn or gry or grn or hzl or oth
|
|
if(eyeColor == "amb"){
|
|
return true;
|
|
}
|
|
else if(eyeColor == "blu"){
|
|
return true;
|
|
}
|
|
else if(eyeColor == "brn"){
|
|
return true;
|
|
}
|
|
else if(eyeColor == "gry"){
|
|
return true;
|
|
}
|
|
else if(eyeColor == "grn"){
|
|
return true;
|
|
}
|
|
else if(eyeColor == "hzl"){
|
|
return true;
|
|
}
|
|
else if(eyeColor == "oth"){
|
|
return true;
|
|
}
|
|
else{
|
|
return false;
|
|
}
|
|
}
|
|
bool passportIdIsValid(){
|
|
//Must be a 9-digit number
|
|
if(passportId.size() != 9){
|
|
return false;
|
|
}
|
|
for(char ch : passportId){
|
|
if(!std::isdigit(ch)){
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//If none of the other conditions were hit return true;
|
|
return true;
|
|
}
|
|
};
|
|
|
|
|
|
std::vector<passport> importData(){
|
|
std::vector<passport> passports;
|
|
std::ifstream inputFile;
|
|
inputFile.open("inputs/Day4.txt"); //Open the file that has the input for the question
|
|
|
|
//Get the input one line at a time because a full blank line is the end of a passport
|
|
while(!inputFile.eof()){
|
|
passport currentPassport;
|
|
std::string currentLine;
|
|
std::getline(inputFile, currentLine);
|
|
while(currentLine != ""){
|
|
//Split the string on [space]
|
|
for(std::string str : mee::split(currentLine, ' ')){
|
|
//Split the string on :
|
|
std::vector<std::string> fields = mee::split(str, ':');
|
|
std::string field = fields[0];
|
|
std::string value = fields[1];
|
|
|
|
//Determine what field you are dealing with and save the data
|
|
if(field == "byr"){
|
|
currentPassport.birthYear = value;
|
|
}
|
|
else if(field == "iyr"){
|
|
currentPassport.issueYear = value;
|
|
}
|
|
else if(field == "eyr"){
|
|
currentPassport.expirationYear = value;
|
|
}
|
|
else if(field == "hgt"){
|
|
currentPassport.height = value;
|
|
}
|
|
else if(field == "hcl"){
|
|
currentPassport.hairColor = value;
|
|
}
|
|
else if(field == "ecl"){
|
|
currentPassport.eyeColor = value;
|
|
}
|
|
else if(field == "pid"){
|
|
currentPassport.passportId = value;
|
|
}
|
|
else if(field == "cid"){
|
|
currentPassport.countryId = value;
|
|
}
|
|
else{
|
|
std::cout << "ERROR!\n" << "field = " << field << "\tValue = " << value << std::endl;
|
|
exit(1);
|
|
}
|
|
}
|
|
std::getline(inputFile, currentLine);
|
|
}
|
|
passports.push_back(currentPassport);
|
|
}
|
|
|
|
return passports;
|
|
}
|
|
|
|
int main(){
|
|
mee::Stopwatch timer;
|
|
int validPassports = 0;
|
|
|
|
//Start the timer
|
|
timer.start();
|
|
|
|
|
|
//Get the passport data
|
|
std::vector<passport> passports = importData();
|
|
|
|
//Count how many are valid
|
|
for(passport pspt : passports){
|
|
if(pspt.isValid()){
|
|
++validPassports;
|
|
}
|
|
}
|
|
|
|
|
|
//Stop the timer
|
|
timer.stop();
|
|
|
|
//Print the results
|
|
std::cout << "There are " << validPassports << " valid passports"
|
|
<< "\nIt took " << timer.getStr() << " to finish this problem" << std::endl;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Results:
|
|
There are 175 valid passports
|
|
It took 1.999 milliseconds to finish this problem
|
|
*/
|