Advent of Code - Day 6 and 7

And so it begins - the Advent of Code has begun to royally kick my butt. While these two challenges weren't necessarily killers, the amount of time I need to solve them is slowly growing. Let's start with day 6.

Day 6

The first challenge asked you to find the most common character in a column of input. So given this:

art
boo
aot

"a" would be the most common charcter in the first column, "o" in the second, and "t" in the third. My solution creaates an array of arrays to store each column of input. I then loop over the columns and create an object containing each letter and a count. I can then simply iterate over that and find the letter with the highest count.


const fs = require('fs');
const input = fs.readFileSync('./input.txt','utf8');


let cols = [];
let lines = input.split('\n');

lines.forEach(function(line) {
    for(let i=0;i<line.length;i++) {
        let char = line.substr(i,1);
        if(!cols[i]) cols[i] = [];
        cols[i].push(char);
    }
});

//console.log(cols);

let solution = '';

// Now go through each col and count
for(let i=0;i<cols.length;i++) {
    let count = {};
    for(let j=0;j<cols[i].length;j++) {
        let letter = cols[i][j];
        if(!count[letter]) count[letter] = 0;
        count[letter]++;
    }
    var highest = -1;
    var selected = '';
    for(var key in count) {
        if(count[key] > highest) {
            selected = key;
            highest = count[key];
        }
    }
    solution += selected;
}

console.log(solution);

Not too difficult. The second part simply reversed the target and asked you to find the least likely letter:


// stuff removed for space...

let solution = '';

// Now go through each col and count
for(let i=0;i<cols.length;i++) {
    let count = {};
    for(let j=0;j<cols[i].length;j++) {
        let letter = cols[i][j];
        if(!count[letter]) count[letter] = 0;
        count[letter]++;
    }
    var highest = -1;
    var selected = '';
    for(var key in count) {
        if(count[key] > highest) {
            selected = key;
            highest = count[key];
        }
    }
    solution += selected;
}

console.log(solution);

I feel kinda bad that I didn't rename highest, but I got over it.

Day 7

This puzzle was one of those I felt like could be solved with one regex, but I'm just not quite that much of a regex master to figure it out myself. The first part involved looking for a string of the form ABBA, where you have two matching characters on the 'outside' of a set of 4 and 2 matching characters on the inside. You needed to see if an ABBA existed in the input string, but also see if an ABBA existing inside any brackets. If it did, that negates it being a good string. So basically, "No ABBA in brackets, ABBA outside."


const fs = require('fs');
const input = fs.readFileSync('./input.txt','utf8');

let good = 0;
let lines = input.split('\n');
lines.forEach(function(line) {
    if(supportsTSL(line)) good++;
});
console.log('Answer: '+good);

function hasABBA(s) {
    //prev1 is 3 behind
    let prev1 = '';
    //prev2 is 2 behind
    let prev2 = '';
    //prev3 is 1 behind
    let prev3 = '';
    let curr = '';
    for(let i=0;i<s.length;i++) {
        curr = s.substr(i,1);
        if(i > 0) prev3 = s.substr(i-1,1);
        if(i > 1) prev2 = s.substr(i-2,1);
        if(i > 2) prev1 = s.substr(i-3,1);
        //check for abba if we have gone far enough
        if(i >= 3) {
            //console.log('abba? '+prev1+prev2+prev3+curr);
            //console.log('does prev3 === prev2 '+(prev3===prev2));
            //if(prev3 === prev2) return false;
            //console.log('does prev1 eq curr? '+(prev1===curr));
            //console.log('does prev3 eq prev2? '+(prev2===prev3));
            if(prev1 === curr && prev2 === prev3 && prev1 !== prev2) return true;
        }
    }
    return false;
}

function supportsTSL(s) {

    //must have a string of the form xyyx (x cannot be y) (ABBA)
    //must NOT have such a thing inside sq brackets
    //so first, get all the blocks INSIDE [], and see if they have ABBA, if so, FALSE
    //then look at the rest  

    let matches = s.match(/\[.*?\]/g);
    for(let i=0;i<matches.length;i++) {
        let match = matches[i].replace(/[\[\]]/g, '');
//        console.log('check ABBA for '+match + '='+hasABBA(match));
        if(hasABBA(match)) return false;
        s = s.replace(matches[i], ' ');
    }
//    console.log('pass bracket, now we have '+s);
    return hasABBA(s);
}

Not elegant at all, but it worked. Part 2 switched to a "ABA", a pair of characters around another character, outside of any bracket, with a corresponding opposite "BAB" inside brackets. Here is my solution.


const fs = require('fs');
const input = fs.readFileSync('./input.txt','utf8');

let good = 0;
let lines = input.split('\n');
lines.forEach(function(line) {
    if(supportsSSL(line)) good++;
});
//259 is too high
console.log('Answer: '+good);


function findABA(s) {
    let results = [];
    //prev1 is 2 behind
    let prev1 = '';
    //prev2 is 1 behind
    let prev2 = '';
    let curr = '';

    for(let i=0;i<s.length;i++) {
        curr = s.substr(i,1);
        if(i > 0) prev2 = s.substr(i-1,1);
        if(i > 1) prev1 = s.substr(i-2,1);

        //check for aba if we have gone far enough
        if(i >= 2) {
            //console.log('does prev3 === prev2 '+(prev3===prev2));
            //if(prev3 === prev2) return false;
            //console.log('does prev1 eq curr? '+(prev1===curr));
            //console.log('does prev3 eq prev2? '+(prev2===prev3));
            if(curr !== ' ' && prev1 !== ' ' && prev2 != ' ' && curr !== prev2 && curr === prev1) results.push(prev1+prev2+curr);
        }
    }
    return results;
}

function supportsSSL(s) {

    /*
    first, get all the ABAs from s minus brackets
    */
    let matches = s.match(/\[.*?\]/g);
    for(let i=0;i<matches.length;i++) {
        s = s.replace(matches[i], ' ');
    }
    //now we have a clean string and bracket crap to check later
    let abas = findABA(s);

    //leave early
    if(abas.length === 0) return false;
    //now we are true if we can match the opposite of aba in brackets
    let bracketText = matches.join(' ').replace(/[\[\]]/g,'');
    for(let i=0;i<abas.length;i++) {
        let aba = abas[i];
        let bab = aba.substr(1,1) + aba.substr(0,1) + aba.substr(1,1);
//        console.log('bab is '+bab);
//        console.log('bracketText is '+bracketText+ ' idx of '+bracketText.indexOf(bab));
        if(bracketText.indexOf(bab) >= 0) return true;
    };
    return false;
}

This one caused me a lot of trouble just because I kept screwing up my findABA logic. My choice of variable names didn't help either. But - it worked. Again, roughly.

As a warning, my solutions will only get uglier as we go further...

You can find my repo of solutions here: https://github.com/cfjedimaster/adventofcode

Like This?

If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can also subscribe to the email feed to get notified of new posts.

Want to read more like this?