Skip to content

watmough/Advent-of-Code-2017

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Advent-of-Code-2017

See also my in-conclusion washup.

Rank: 436 / 391

Recreate the Turing machine and save the computer! What is the diagnostic checksum it produces once it's working again?

// Advent of Code 2016
// Day 25 - The Halting Problem

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <tuple>
#include <algorithm>
#include <map>
using namespace std;


int main()
{
    int state = 0;
    int slot = 0;
    int curval = 0;
    map<int,int> tape;

    int steps = 12459852;
    do {
        switch(state) {         // state A
        case 0: if (tape[slot]==0) {
            tape[slot]=1;
            slot++;
            state='b'-'a';
        } else if (tape[slot]==1) {
            tape[slot]=1;
            slot--;
            state = 'e'-'a';
        }
        break;
        case 1: if (tape[slot]==0) {    // B
            tape[slot]=1;
            slot++;
            state='c'-'a';
        } else if (tape[slot]==1) {
            tape[slot]=1;
            slot++;
            state = 'f'-'a';
        }
        break;
        case 2: if (tape[slot]==0) {    // C
            tape[slot]=1;
            slot--;
            state='d'-'a';
        } else if (tape[slot]==1) {
            tape[slot]=0; 
            slot++;
            state = 'b'-'a';
        }
        break;
        case 3: if (tape[slot]==0) {    // D
            tape[slot]=1;
            slot++;
            state='e'-'a';
        } else if (tape[slot]==1) {
            tape[slot]=0; 
            slot--;
            state = 'c'-'a';
        }
        break;
        case 4: if (tape[slot]==0) {    // E
            tape[slot]=1;
            slot--;
            state='a'-'a';
        } else if (tape[slot]==1) {
            tape[slot]=0;
            slot++;
            state = 'd'-'a';
        }
        break;
        case 5: if (tape[slot]==0) {    // F
            tape[slot]=1;
            slot++;
            state='a'-'a';
        } else if (tape[slot]==1) {
            tape[slot]=1;
            slot++;
            state = 'c'-'a';
        }
        break;

        }
    } while (--steps>0);
    int tot = 0;
    for (auto p : tape) {
        if (p.second==1) tot++;
    }
    cout << tot << endl;
}

Rank: 2240 / 2221

Part 1: What is the strength of the strongest bridge you can make with the components you have available?

Part 2: What is the strength of the longest bridge you can make? If you can make multiple bridges of the longest length, pick the strongest one.

// Advent of Code 2016
// Day 24 - Electromagnetic Moat

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <tuple>
#include <algorithm>
using namespace std;

// parse input
void parse(vector<pair<int,int>>& parts)
{
    auto row{""s};
    auto p1{0},p2{0};
    ifstream data("day_24.inp");
    while (getline(data,row)) {
        stringstream line(row);
        line >> p1; line.get();
        line >> p2;
        parts.push_back(pair<int,int>(p1,p2));
    }
}

bool not_used(vector<int> used, int part_num)
{
    return find(begin(used),end(used),part_num)==end(used);
}

bool can_use(pair<int,int> part, int port)
{
    return part.first==port || part.second==port;
}

vector<int> get_moves(vector<pair<int,int>>& parts, vector<int> used,int port)    // components matching port that have not been used
{
    vector<int> moves;
    for (int i=0;i<parts.size();++i) {
        if (not_used(used,i) && can_use(parts[i],port)) {
            moves.push_back(i);
        }
    }
    return moves;
}

// Part 1 - Just solve for best strength
tuple<int,vector<int>> solve_strength(vector<pair<int,int>>& parts, vector<int> used, int port, int strength)
{
    vector<int> moves = get_moves(parts,used,port);
    auto best_strength = strength;
    vector<int> best_path = used;
    for (auto m : moves) {
        used.push_back(m);
        auto new_port = parts[m].first==port ? parts[m].second : parts[m].first;
        auto new_strength = strength+parts[m].first+parts[m].second;
        auto solution = solve_strength(parts,used,new_port,new_strength);
        if (get<0>(solution)>best_strength) {
            best_strength = get<0>(solution);
            best_path = get<1>(solution);
        }
        used.pop_back();
    }
    return make_tuple(best_strength,best_path);
}

// Part 2 - Solve for longest path
tuple<int,int,vector<int>> solve_length(vector<pair<int,int>>& parts, vector<int> used, int port, int strength,int length)
{
    vector<int> moves = get_moves(parts,used,port);
    auto best_length = length;
    auto best_strength = strength;
    vector<int> best_path = used;
    for (auto m : moves) {
        used.push_back(m);
        auto new_port = parts[m].first==port ? parts[m].second : parts[m].first;
        auto new_strength = strength+parts[m].first+parts[m].second;
        auto new_length = length+1;
        auto solution = solve_length(parts,used,new_port,new_strength,new_length);
        if (get<0>(solution)>best_length || (get<0>(solution)==best_length && get<1>(solution)>best_strength)) {
            best_length = get<0>(solution);
            best_strength = get<1>(solution);
            best_path = get<2>(solution);
        }
        used.pop_back();
    }
    return make_tuple(best_length,best_strength,best_path);
}

int main()
{
    vector<pair<int,int>> parts;
    parse(parts);

    auto solution_strength = solve_strength(parts,vector<int>{},0,0);
    cout << "Part 1: " << get<0>(solution_strength) << endl;

    auto solution_length = solve_length(parts,vector<int>{},0,0,0);
    cout << "Part 2: " << get<1>(solution_length) << endl;

    return 0;
}

Output:

Part 1: 1906
Part 2: 1824

Rank: 345 / ---

Part 1 was a pretty simple hack of Day 18 - Duet.

// Advent of Code 2017
// Day 23 - Coprocessor Conflagration

#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <chrono>
using namespace std;

long mul = 0;

bool step(const vector<string>& iv,const vector<string>& xv,const vector<string>& yv,
          map<string,long long>& reg,
          vector<long long>& send, long long& sentcount,
          vector<long long>& recv)
{
    string tok = iv[reg["pc"]];
    string opx = xv[reg["pc"]];
    string opy = yv[reg["pc"]];
//    cout << tok << " " << opx << " " << opy << endl;
    if (tok=="snd") {
        send.push_back(opx[0]<'a' ? stoi(opx) : reg[opx]);
        sentcount++;
    }
    if (tok=="rcv" && recv.size()==0) {
        return false;
    }
    if (tok=="rcv" && recv.size()>0) {
        reg[opx] = recv.front();
        recv.erase(begin(recv));
    }
    const long long opyval = opy.length()==0 ? 0 : (opy[0]<'a' ? stoi(opy) : reg[opy]);
    if (tok=="set") reg[opx] = opyval;
    if (tok=="sub") reg[opx] -= opyval;
    if (tok=="mul") {mul++; reg[opx] *= opyval;}
    if (tok=="mod") reg[opx] %= opyval;
    if (tok=="jnz" && ((opx[0]<'a' && stoi(opx)!=0)||reg[opx]!=0)) reg["pc"] += opyval;
    else reg["pc"]++;
    if (reg["pc"]<0||reg["pc"]>=iv.size()-1) return false;
    return true;
}

main()
{
    vector<string> iv,xv,yv;
    string tok,opx,opy;
    map<string,long long> reg0;
    map<string,long long> reg1;
    vector<long long> mbox0,mbox1;
    long long sent0{0ll},sent1{0ll},ins_count{0ll};
    while (cin >> tok >> opx) {
        if (!(tok=="snd"||tok=="rcv")) 
            cin >> opy;
        else 
            opy = "";
        cout << "Listing: " << tok << " " << opx << " " << opy << endl;
        iv.push_back(tok);
        xv.push_back(opx);
        yv.push_back(opy); 
    }

    // simulate two programs
    reg0["p"] = 0; reg1["p"] = 1;
//    reg0["a"] = 1;            // debug
    auto start = std::chrono::high_resolution_clock::now();
    while (1) {
        bool stepped0 = step(iv,xv,yv,reg0,mbox1,sent0,mbox0);
//        bool stepped1 = step(iv,xv,yv,reg1,mbox0,sent1,mbox1);
        ins_count+=2;
        if (!stepped0) break;
//        if (!stepped0 && !stepped1)
//            break;
    }
    cout << "Mul: " << mul << endl;
//    cout << "program 1 sent: " << sent1 << " messages." << endl;
    auto end = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> elapsed_seconds = end - start;
    cout << "Instruction count: " << ins_count << " in " << 
             elapsed_seconds.count()*1000 << " msec " <<
             ins_count / elapsed_seconds.count() / 1000000 << " MIPs" << endl;
    return 0;    
}

Part 2 asked us to optimize the Duet assembly language and run it to completion with the answer being the contents of the h register.

The code below is just barely C++ code!

// Advent of Code 2017
// Day 23 Part 2 - Coprocessor Conflagration

#include <iostream>
using namespace std;

int main()
{
    long long a,b,c,d,e,f,g,h,i;
    a=1; b=c=d=e=f=g=h=0;

    b=93;                                           // set b 93
    c= b;                                           // set c b
    if (a!=0) goto l5;                              // jnz a 2
    goto l9;                                        // jnz 1 5
l5: b*=100;                                         // mul b 100
    b+=100000;              // b = 109300           // sub b -100000
    c=b;                                            // set c b
    c+=17000;               // c = b + 17000        // sub c -17000

    while (b!=c) {
    l9: f=1;                    // set flag             // set f 1
        d=2;                    // set trial multipland // set d 2

        // replace the following with:
        for (int factor=2;factor<b/2;++factor) {
            if (b%factor==0) {
                f=0;
                break;
            }
        }

/*      while (d!=b && f==1) {      // is_prime
        l11:e=2;                    // find                 // set e 2

            while (e!=b && f==1) {      // is_prime
            l12:g=d;                                            // set g d
                g*=e;                   // g = d*e              // mul g e
                g-=b;                   // if (d*e!=b)          // sub g b
                if(g!=0) goto l17;      //     f = 0            // jnz g 2
                f=0;                    // clear f if divisor   // set f 0
                                        // f = isprime
            l17:e++;                                            // sub e -1
                g=e;                    // g = e + 1            // set g e
                g-=b;                   // g = g - b            // sub g b
  //            if(g!=0) goto l12;                              // jnz g -8
            }

            d++;                                            // sub d -1
            g=d;                                            // set g d
            g-=b;                                           // sub g b
//          if(g!=0) goto l11;                              // jnz g -13
        }*/

        if(f!=0) goto l27;      // if (!is_prime)       // jnz f 2
        h++;                    //     h = h + 1        // sub h -1
    l27:g=b;                    // endif                // set g b
        g-=c;                   // if (b==c)            // sub g c
        if(g!=0) goto l31;      //     break            // jnz g 2
        goto done;              // quit if we get here  // jnz 1 3
    l31:b+=17;                                          // sub b -17
        goto l9;                                        // jnz 1 -23
    }

done:
    cout << h << endl;
    return 0;
}

I was a few hours late starting with this one.

Rank: 1608 / 1534

// Advent of Code 2017
// Day 22 - Sporifica Virus

#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <algorithm>
using namespace std;

typedef enum {u=0,l,d,r} direction;
typedef enum {c=0,w,i,f} state;
state next_state[] = {w,i,f,c};

int main()
{
    // state 
    map<int,map<int,state>> world;

    // next move table
    map<state,map<direction,direction>> next_move;
    next_move[c][u] = l; next_move[c][l] = d; next_move[c][d] = r; next_move[c][r] = u;
    next_move[w][u] = u; next_move[w][l] = l; next_move[w][d] = d; next_move[w][r] = r;
    next_move[i][u] = r; next_move[i][l] = u; next_move[i][d] = l; next_move[i][r] = d;
    next_move[f][u] = d; next_move[f][l] = r; next_move[f][d] = u; next_move[f][r] = l;

    // read input
    string row;
    int cxy = 0, x=0,y=-1000;
    while (getline(cin,row)) {
        cout << row << " len: " << row.length() << endl;
        int ll = row.length();
        y = (y==-1000) ? 0-ll/2 : y;
        x = 0-ll/2;
        for(auto it=begin(row);it!=end(row);++it) {
            cout << x << " " << y << ((*it)=='#' ? " #" : " .");
            world[x++][y] = (*it)=='#' ? i : c;
        }
        cout << endl;
        y++;
    }

    // state
    vector<int> pos = {0,0};
    direction dir = u;
    map<direction,pair<int,int>> move;
    move[u] = pair<int,int>(0,-1);
    move[l] = pair<int,int>(-1,0);
    move[d] = pair<int,int>(0,1);
    move[r] = pair<int,int>(1,0);

    // step
    int infect = 0;
    int steps = 10000000;
    x = 0; y = 0;
    while (steps>0) {
        state cell = world[x][y];
        dir = next_move[cell][dir];
        world[x][y] = next_state[cell];
        infect += (world[x][y]==i ? 1 : 0);
        x += move[dir].first;
        y += move[dir].second;
        steps--;
    }
    cout << "infect: " << infect << endl;
}

Day 21 - Fractal Art

Rank: 2579 / 2509

Finally bashed out the code for Fractal Art. It was a bit worrying as I wasn't entirely convinced that my strategy would work. Does work though!

--- Part One --- Thus, after 2 iterations, the grid contains 12 pixels that are on. How many pixels stay on after 5 iterations?

--- Part Two --- How many pixels stay on after 18 iterations?

// Advent of Code 2017
// Day 21 - Fractal Art

#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <vector>
#include <algorithm>
#include <cassert>
using namespace std;

string input = ".#...####";

/* Example input
../.# => ##./#../...
.#./..#/### => #..#/..../..../#..#
*/

void parse_input(vector<pair<string,string>>& rawrules)
{
    string line;
    while (getline(cin,line)) {
        string input(""), output("");
        auto it=begin(line);
        for (;it!=end(line);++it) {
            if ((*it)=='.') input+=".";
            if ((*it)=='#') input+="#";
            if ((*it)==' ') break;
        }
        for (;it!=end(line);++it) {
            if ((*it)=='.') output+=".";
            if ((*it)=='#') output+="#";
            if ((*it)=='\n'||(*it)=='\r') break;
        }
        // got the input output pairs
        //cout << input << "~" << output << endl;
        rawrules.push_back(pair<string,string>(input,output));
    }
}

void hash_rules(string in, string out, map<int,string>& rules)
{
    static int o2[8][4] = {{0,1,2,3},{2,3,0,1},{1,0,3,2},{3,2,1,0},{1,3,0,2},{2,0,3,1},
                           {0,2,1,3},{3,1,2,0}};
    if (in.length()==4) {
        for (int o=0;o<8;++o) {
            int hash=0;
            for (int b=0;b<4;++b) {
                hash+=(in[o2[o][b]]=='#'?(1<<b):0);
            }
            //cout << in << " hashes " << hex << hash << endl;
            rules[hash] = out;
        }
    }
    static int o3[8][9] = {{0,1,2,3,4,5,6,7,8},{2,1,0,5,4,3,8,7,6},{6,7,8,3,4,5,0,1,2},
                           {6,3,0,7,4,1,8,5,2},{8,7,6,5,4,3,2,1,0},{2,5,8,1,4,7,0,3,6},
                           {0,3,6,1,4,7,2,5,8},{8,5,2,7,4,1,6,3,0}};
    if (in.length()==9) {
        for (int o=0;o<8;++o) {
            int hash=0;
            for (int b=0;b<9;++b) {
                hash+=(in[o3[o][b]]=='#'?(1<<b):0);
            }
            //cout << in << " hashes " << hex << hash << dec << endl;
            rules[hash] = out;
        }
    }
}

int isqrt(int n,int s=1) { while(s*s<n) s++; return s;}

vector<int> split_and_hash(string input)
{
    vector<int> hashes;
    int llen = input.length();
    if (llen%2==0) {
        int side=isqrt(llen);
        for (int i=0;i<side/2;++i) {
            for (int j=0;j<side/2;++j) {
                int hash=0, bit=0;
                for (int r=0;r<2;++r) {
                    for (int c=0;c<2;++c) {
                        hash+=(input[(i*2+r)*side+2*j+c]=='#'?(1<<bit):0); bit++;
                    }
                }
                //cout << input << " 2x2-> " << hex << hash << dec << endl;
                hashes.push_back(hash);
            }
        }
    }
    else if (llen%3==0) {
        int blk=3;
        int side=isqrt(llen);
        int grd=side/blk;
        for (int s=0;s<llen/9;++s) {
            int hash=0, bit=0;
            for (int i=0;i<9;++i) {
                int y = s/grd*blk+i/blk;
                int x = s%grd*blk+i%blk;
                hash+=(input[y*side+x]=='#'?(1<<bit):0); bit++;
            }
            //cout << input << " 3x3-> " << hex << hash << dec << endl;
            hashes.push_back(hash);
        }
    }
    return hashes;
}

string unify(vector<int>& hashes, map<int,string>& rules)
{
    //cout << "unify " << hashes.size() << " hashes " << rules.size() << endl;
    vector<string> outs;
    int area = 0;
    for (auto h : hashes) {
        string o = rules[h]; area+=o.length();
        //cout << "\'" << o << "\'" << endl;
        outs.push_back(o);
    }
    //cout << " area is " << dec << area << endl;
    assert(isqrt(area)*isqrt(area)==area);

    // 'print' the output strings to a grid
    int hashcount = 0;
    int blk  = isqrt(outs[0].length());  // e.g. 2 or 3
    int side = isqrt(area);              // grid side e.g 4, 6 etc
    int grd  = side/blk;                  // rows and columns count
    string grid(area,' ');
    for (int s=0;s<outs.size();++s) {
        string str = outs[s];
        for (int i=0;i<str.length();++i) {
            int y = s/grd*blk+i/blk;
            int x = s%grd*blk+i%blk;
            //cout << "x: " << x << " y: " << y << " <- " << str[i] << endl;
            grid[y*side+x] = str[i];
            hashcount += (str[i]=='#'?1:0);
        }
    }
    cout << "Hashcount: " << hashcount << endl;
    return grid;
}

int main()
{
    vector<pair<string,string>> rawrules;
    parse_input(rawrules);

    map<int, string> rules2x2;
    map<int, string> rules3x3;
    for( auto rule : rawrules) {
        hash_rules(rule.first,rule.second, ((rule.first.length()%2)==0)?rules2x2:rules3x3);
    }

    string grid = input;
    for (int count=18;count>0;--count) {
        vector<int> split = split_and_hash(grid);
        grid = (grid.length()%2==0) ? unify(split,rules2x2) : unify(split,rules3x3);
    }
}

I started this one in F#, couldn't get part 2 to work, so rewrote in C++ and realized my mistake eventually.

Rank: 4341 / 4342

Which particle will stay closest to position <0,0,0> in the long term?

How many particles are left after all collisions are resolved?

// Advent of Code 2017
// Day 20 - Particle Swarm

#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;

typedef struct particle {
    int num;
    vector<int64_t> pos{0,0,0};
    int64_t vel[3];
    int64_t acc[3];
} particle;

int read_particles(vector<particle>& state)
{
    int64_t x,y,z,vx,vy,vz,ax,ay,az;
    int num = 0;
    while (cin >> x >> y >> z >> vx >> vy >> vz >> ax >> ay >> az) {
        particle p;
        p.num = num++;      // particles are 0 - num-1
        p.pos[0] = x;  p.pos[1] = y;  p.pos[2] = z; 
        p.vel[0] = vx; p.vel[1] = vy; p.vel[2] = vz; 
        p.acc[0] = ax; p.acc[1] = ay; p.acc[2] = az; 
        state.push_back(p);
    }
    return num;
}

void step(particle& p)
{
    p.vel[0] += p.acc[0]; p.vel[1] += p.acc[1]; p.vel[2] += p.acc[2]; 
    p.pos[0] += p.vel[0]; p.pos[1] += p.vel[1]; p.pos[2] += p.vel[2]; 
}

int main()
{
    // read in particles
    vector<particle> state;
    int num_particles = read_particles(state);
    // loop
    int ucount = state.size();
    int generations = 0;
    while (1)
    {
        // sort by position and eliminate dupes
        map<vector<int64_t>,int> dupes;
        for (auto it=begin(state);it!=end(state);++it) {
            dupes[((*it).pos)]++;
        }

        // filter dupes so only includes collision locations
        for (auto it=begin(dupes);it!=end(dupes);) {
            if ((*it).second>1) {
                cout << "dupe at pos " << (*it).first[0] << "," << (*it).first[1] << "," << (*it).first[2] << endl;
                it++;
            } else {
                it = dupes.erase(it++);
            }
        }

        // remove collided particles
        state.erase(remove_if(begin(state),end(state),[&](particle p)->bool{if (dupes.find(p.pos)!=end(dupes)) return true; else return false;}),end(state));
        cout << "Duplicates: " << dupes.size() << " particles: " << state.size() << " gen: " << generations++ << endl;

        // step time
        for (auto it=begin(state);it!=end(state);++it) {
            step(*it);
        }
    }
}

Rank: 631 / 628

The little packet looks up at you, hoping you can help it find the way. What letters will it see (in the order it would see them) if it follows the path? (The routing diagram is very wide; make sure you view it without line wrapping.)

How many steps does the packet need to go?

// Advent of Code 2017
// http://adventofcode.com/
// Day 19 - A Series of Tubes

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;

typedef enum direction {nomove,u,d,l,r} direction;

direction next_move(vector<string>& lines, int row, int col,direction dir)
{
    switch(dir) {       // preferred direction
    case u: if (dir!=d && row>0 && lines[row-1][col]!=' ') return u;
    case d: if (dir!=u && row<lines.size()-1 && lines[row+1][col]!=' ') return d;
    case r: if (dir!=l && col<lines[row].length()-1 && lines[row][col+1]!=' ') return r;
    case l: if (dir!=r && col>0 && lines[row][col-1]!=' ') return l;
            if (dir!=d && row>0 && lines[row-1][col]!=' ') return u;        // mop up any corners
            if (dir!=u && row<lines.size()-1 && lines[row+1][col]!=' ') return d;
            if (dir!=l && col<lines[row].length()-1 && lines[row][col+1]!=' ') return r;
    }
    return nomove;
}

string follow(vector<string>& lines, int& steps)
{
    string letters;
    int row=0,col=0;
    while (lines[row][col]!='|') col++;         // find starting position
    direction dir = d;
    while (dir != nomove) {
        steps++, dir = next_move(lines,row,col,dir);
        switch(dir) {
            case d: row++; break;
            case u: row--; break;
            case r: col++; break;
            case l: col--; break;
            case nomove:
                cout << "STUCK!! at " << row << " " << col << " " << steps << endl;
        }
        if (lines[row][col]>='A' && lines[row][col]<='Z' && dir!=nomove)
            letters+=lines[row][col];
    }
    return letters;
}

int main()
{
    vector<string> lines;
    ifstream ifs("day_19.ts2",ifstream::in);
    string l;
    while (getline(ifs,l)) {
        lines.push_back(l);
        cout << l << endl;
    }
    int steps = 0;
    string letters = follow(lines,steps);
    cout << letters << " " << steps << endl;
    return 0;
}

Day 18 - Duet

Rank: 999 / 566

What is the value of the recovered frequency (the value of the most recently played sound) the first time a rcv instruction is executed with a non-zero value?

Once both of your programs have terminated (regardless of what caused them to do so), how many times did program 1 send a value?

// Advent of Code 2017
// Day 18 - Duet

#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <chrono>
using namespace std;

bool step(const vector<string>& iv,const vector<string>& xv,const vector<string>& yv,
          map<string,long long>& reg,
          vector<long long>& send, long long& sentcount,
          vector<long long>& recv)
{
    string tok = iv[reg["pc"]];
    string opx = xv[reg["pc"]];
    string opy = yv[reg["pc"]];
    if (tok=="snd") {
        send.push_back(opx[0]<'a' ? stoi(opx) : reg[opx]);
        sentcount++;
    }
    if (tok=="rcv" && recv.size()==0) {
        return false;
    }
    if (tok=="rcv" && recv.size()>0) {
        reg[opx] = recv.front();
        recv.erase(begin(recv));
    }
    const long long opyval = opy.length()==0 ? 0 : (opy[0]<'a' ? stoi(opy) : reg[opy]);
    if (tok=="set") reg[opx] = opyval;
    if (tok=="add") reg[opx] += opyval;
    if (tok=="mul") reg[opx] *= opyval;
    if (tok=="mod") reg[opx] %= opyval;
    if (tok=="jgz" && ((opx[0]<'a' && stoi(opx)>0)||reg[opx]>0)) reg["pc"] += opyval;
    else reg["pc"]++;
    return true;
}

main()
{
    vector<string> iv,xv,yv;
    string tok,opx,opy;
    map<string,long long> reg0;
    map<string,long long> reg1;
    vector<long long> mbox0,mbox1;
    long long sent0{0ll},sent1{0ll},ins_count{0ll};
    while (cin >> tok >> opx) {
        if (!(tok=="snd"||tok=="rcv")) 
            cin >> opy;
        else 
            opy = "";
        cout << "Listing: " << tok << " " << opx << " " << opy << endl;
        iv.push_back(tok);
        xv.push_back(opx);
        yv.push_back(opy); 
    }

    // simulate two programs
    reg0["p"] = 0; reg1["p"] = 1;
    auto start = std::chrono::high_resolution_clock::now();
    while (1) {
        bool stepped0 = step(iv,xv,yv,reg0,mbox1,sent0,mbox0);
        bool stepped1 = step(iv,xv,yv,reg1,mbox0,sent1,mbox1);
        ins_count+=2;
        if (!stepped0 && !stepped1)
            break;
    }
    cout << "program 1 sent: " << sent1 << " messages." << endl;
    auto end = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> elapsed_seconds = end - start;
    cout << "Instruction count: " << ins_count << " in " << 
             elapsed_seconds.count()*1000 << " msec " <<
             ins_count / elapsed_seconds.count() / 1000000 << " MIPs" << endl;
    return 0;    
}

Output:

PS C:\Workarea\Advent-of-Code-2017> type day_18.ts2 | .\a.exe
Listing: set a 1
Listing: mul p 17
Listing: jgz p p
Listing: mul a 2
Listing: add i -1
Listing: jgz i -2
Listing: add a -1
Listing: set i 127
Listing: set p 680
Listing: mul p 8505
Listing: mod p a
Listing: mul p 129749
Listing: add p 12345
Listing: mod p a
Listing: set b p
Listing: mod b 10000
Listing: snd b
Listing: add i -1
Listing: jgz i -9
Listing: jgz a 3
Listing: rcv b
Listing: jgz b -1
Listing: set f 0
Listing: set i 126
Listing: rcv a
Listing: rcv b
Listing: set p a
Listing: mul p -1
Listing: add p b
Listing: jgz p 4
Listing: snd a
Listing: set a b
Listing: jgz 1 3
Listing: snd b
Listing: set f 1
Listing: add i -1
Listing: jgz i -11
Listing: snd a
Listing: jgz f -16
Listing: jgz a -19
program 1 sent: 7112 messages.
Instruction count: 140280 in 93.075 msec 1.50717 MIPs
PS C:\Workarea\Advent-of-Code-2017>

Day 17 - Spinlock

Rank: 414 / 928

// Advent of Code 2017
// Day 17 - Spinlock

#include <iostream>
#include <vector>
#include <cassert>
using namespace std;

int main()
{
    vector<int> buffer;
    int step{335};
    buffer.push_back(0);
    auto pos = 0u;
    for (auto i=1;i<=2017;++i) {
        pos = (pos + step) % buffer.size();
        buffer.insert(begin(buffer)+pos+1,i);
        pos++;
    }
    cout << "Part 1: " << buffer[(pos+1)%buffer.size()] << endl;
    
    buffer.erase(begin(buffer),end(buffer));
    buffer.insert(begin(buffer),0);
    pos = 0u;
    auto sz = 1u;
    for (auto i=1;i<=50000000;++i) {
        pos = (pos + step) % sz;
        if (pos==0)
            buffer.insert(begin(buffer)+pos+1,i);
        sz++;
        pos++;
    }    
    cout << "Part 2: " << buffer[1] << endl;   
    return 0;
}

Rank: 959 / 580

You watch the dance for a while and record their dance moves (your puzzle input). In what order are the programs standing after their dance?

In what order are the programs standing after their billion dances?

// Advent of Code 2017
// Day 16 - Permutation Promenade

#include <iostream>
#include <sstream>
#include <algorithm>
#include <fstream>
#include <map>
using namespace std;

int main()
{
    // test inputs
/*  string input = "s1, x3/4, pe/b"; // a spin of size 1: eabcd.*/

    int n,n1,n2;
    string ins;
    char ch;
    map<string,uint> seq;            // cycle?
    string p = "abcdefghijklmnop";

    for(int i=0;i<1000000000%60;++i)
    {
        ifstream in("day_16.txt");
        while(in >> ch) {
            if (ch==',' || ch<'0' || ch=='/' || ch==' ')
                continue;
            if (ch=='s') {
                in >> n;
                string temp(p);
                copy(end(p)-n,end(p),temp.begin());
                copy(begin(p),end(p)-n,temp.begin()+n);
                p=temp;
            }
            if (ch=='x') {
                in >> n1;
                if(in.peek()=='/') in.get();
                in >> n2;
                swap(p[n1],p[n2]);
            }
            if (ch=='p') {
                string sw;
                char ch;
                while (in.peek()!=',' && in >> ch) 
                    sw.push_back(ch);
                auto slash = find_if(sw.begin(),sw.end(),[](int c)->bool{return c=='/';});
                string t1(sw.begin(),slash);
                string t2(slash+1,sw.end());
                auto it1 = p.find(t1);
                auto it2 = p.find(t2);
                copy(t1.begin(),t1.end(),p.begin()+it2);
                copy(t2.begin(),t2.end(),p.begin()+it1);
            }
        }
        if (seq.find(p)!=seq.end()) {
            cout << "Found a repeat of " << p << " at " << i << endl;
        }
        seq[p] = i;
    }
    cout << p << endl;
}

Rank: 576 / 498

To get a significant sample, the judge would like to consider 40 million pairs. (In the example above, the judge would eventually find a total of 588 pairs that match in their lowest 16 bits.) After 40 million pairs, what is the judge's final count?

After 5 million pairs, but using this new generator logic, what is the judge's final count?

// Advent of Code 2017
// Day 15 - Dueling Generators

#include "stdafx.h"
#include <iostream>
using namespace std;

int main()
{
    //unsigned long long int a{ 65 }, b{ 8921 };
    unsigned long long int a{ 699 }, b{ 124 };
    int match{ 0 };
    for (auto i{ 0 }; i < 40000000; ++i) {
        a = (a * 16807ll) % 2147483647ll;
        b = (b * 48271ll) % 2147483647ll;
        if ((a&0xffff) == (b&0xffff))
            match++;
    }
    cout << "Part 1: " << match << " matches." << endl;
    a = 699, b = 124, match = 0;
    for (auto i{ 0 }; i < 5000000; ++i) {
        do a = (a * 16807ll) % 2147483647ll; while (a % 4);
        do b = (b * 48271ll) % 2147483647ll; while (b % 8);
        if ((a & 0xffff) == (b & 0xffff))
            match++;
    }
    cout << "Part 2: " << match << " matches." << endl;
    return 0;
}

Output:

OS X:
Jonathans-Pro:Advent-of-Code-2017 jonathan$ clang day\ 15.cpp -std=c++14 -stdlib=libc++ -lc++ -O3 -march=native
Jonathans-Pro:Advent-of-Code-2017 jonathan$ ./a.out
Part 1: 600 matches.
Ran in 283.792 msec
Part 2: 313 matches.
Ran in 411.678 msec
Jonathans-Pro:Advent-of-Code-2017 jonathan$ 

Windows 10:
PS C:\Workarea\AOC2017\day 15\x64\Release> & '.\day 15.exe'
Part 1: 600 matches.
Ran in 241.696 msec
Part 2: 313 matches.
Ran in 373.521 msec
PS C:\Workarea\AOC2017\day 15\x64\Release>

Windows 10 GCC (defaults)

PS C:\Workarea\Advent-of-Code-2017> .\a.exe
Part 1: 600 matches.
Ran in 891.216 msec
Part 2: 313 matches.
Ran in 1096.93 msec
PS C:\Workarea\Advent-of-Code-2017>


Rank: 304 / 334

Given your actual key string, how many squares are used?

How many regions are present given your key string?

// Advent of Code 2017
// Day 14 - Disk Defragmentation

#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <map>
#include <algorithm>
#include <numeric>
#include <vector>
#include <set>
#include <cassert>
#include <bitset>
using namespace std;

void reverse(vector<int>& numbers, int start, int length)
{
    for (auto pos{ 0 }; pos < length / 2; ++pos)
        swap(numbers[(start + pos) % 256], numbers[(start + length - 1 - pos) % 256]);
}

int writeg(int* g, int row, int col, int hashchar)
{
    g += 128 * row + col * 8;
    for (auto i{ 0 }; i < 8; ++i) {
        *(g + i) = (hashchar & 1 << (7 - i)) ? -1 : 0;
    }
    return 0;
}

void floodfill(int *g, int i, int c)
{
    g[i] = c;
    if (i / 128 > 0 && g[i - 128] == -1) floodfill(g, i - 128, c);
    if (i / 128 <127  && g[i + 128] == -1) floodfill(g, i + 128, c);
    if (i % 128 > 0 && g[i - 1] == -1) floodfill(g, i - 1, c);
    if (i % 128 < 127  && g[i + 1] == -1) floodfill(g, i + 1, c);
}

int main()
{
    vector<int> numbers(256);
    vector<int> lengths = { 192, 69, 168, 160, 78, 1, 166, 28, 0, 83, 198, 2, 254, 255, 41, 12 };
    string seed = "ffayrhll";
    vector<int> trailing{ 17, 31, 73, 47, 23 };
    vector<int> hash(16);

/*  cout << "Part 1: ";
    iota(numbers.begin(), numbers.end(), 0);
    for (auto l{ 0 }, start{ 0 }, skip{ 0 }; l < lengths.size(); start += lengths[l] + l++, ++skip) {
        reverse(numbers, start %= 256, lengths[l]);
    }
    cout << numbers[0] * numbers[1] << endl;*/
    
    cout << "Part 1: ";
    int bitcount{ 0 };
    int g[128 * 128];
    for (int row{ 0 }; row < 128; ++row) { 
        string input(seed);
        input += "-";
        input += to_string(row);
        iota(numbers.begin(), numbers.end(), 0);
        lengths.resize(input.size() + trailing.size());
        copy(input.begin(), input.end(), lengths.begin());
        copy(trailing.begin(), trailing.end(), lengths.end() - trailing.size());
        auto start{ 0 }, skip{ 0 };
        for (int r = 0; r < 64; ++r) {
            for (auto l{ 0 }; l < lengths.size(); start += lengths[l] + skip++, l++) {
                reverse(numbers, start %= 256, lengths[l]);
            }
        }

        for (int i{ 0 }, hashchar{ 0 }; i < 256; ++i) {
            hashchar = i % 16 == 0 ? numbers[i] : hashchar ^ numbers[i];
//          i % 16 == 15 && cout << setw(2) << setfill('0') << hex << hashchar << endl;
            i % 16 == 15 && (bitcount += std::bitset<8>(hashchar).count());
            i % 16 == 15 && (writeg(g,row,i/16,hashchar));
        }
    }
    cout << bitcount << endl;

    int regions{ 0 };
    for (auto i{ 0 }; i < 128 * 128; ++i) {
        if (g[i] == -1) {
            floodfill(g, i, ++regions);
        }
    }

    cout << regions << endl;
    return 0;
}

Rank: 3945 / 5082

Given the details of the firewall you've recorded, if you leave immediately, what is the severity of your whole trip?

What is the fewest number of picoseconds that you need to delay the packet to pass through the firewall without being caught?

// Advent of Code 2017
// Day 13 - Packet Scanners

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <algorithm>
#include <chrono>
using namespace std;

int main(int argc, char* argv[])
{
    int depth, range;
    vector<int> depths, ranges;
    while (cin >> depth) {
        if (cin.peek() == ':') cin.get();
        cin >> range;
        depths.push_back(depth);
        ranges.push_back(range);
    }

    int severity{ 0 };
    for (int step = 0; step<depths.size(); ++step) {
        severity += (depths[step] % ((ranges[step] - 1) * 2))==0 ? (depths[step]*ranges[step]) : 0;
    }
    cout << "Part 1: " << severity << endl;

    auto start = std::chrono::high_resolution_clock::now();
    auto delay{ 0 }, fail{ 0 };
    for (;; ++delay) {
        fail = 0;
        for (auto step{ 0 }; fail == 0 && step < depths.size(); ++step)
            fail = !((depths[step] + delay) % ((ranges[step] - 1) * 2));
        if (fail == 0) break;
    }
    auto end = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> elapsed_seconds = end - start;
    cout << "Part 2: " << delay << " in " << elapsed_seconds.count()*1000 << " msec" << endl;
    return 0;
}

/*
Output:
Part 1: 1640
Part 2: 3960702 in 49.2783 msec
*/

Output:

Part 1: 1640
Part 2: 3960702

Rank: 1341 / 2225 Live-streamed.

How many programs are in the group that contains program ID 0?

How many groups are there in total?

// Advent of Code 2017
// http://adventofcode.com/
// Day 12 - Digital Plumber

#include "stdafx.h"
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <algorithm>
#include <numeric>
#include <vector>
#include <set>
#include <cassert>
using namespace std;


void mergeprogram(int program, map<int, set<int>>& groups)
{
    set<int> childs = groups[program];
    for (auto it = begin(childs); it != end(childs); ++it) {
        if (program == *it) continue;
        if (groups.find(*it) != groups.end()) {
            groups[program].insert(begin(groups[*it]), end(groups[*it]));
            groups.erase(*it);
            mergeprogram(program, groups);
        }
    }
}

int main()
{
    string line;
    map<int, set<int>> groups;
    vector<int> inter(2048);
    int program;
    string delim;

    while (getline(cin, line)) {
        set<int> programs;
        stringstream row(line);
        row >> program >> delim;
        int linked;
        programs.insert(program);
        while (row >> linked) {
            programs.insert(linked);
            if (row.peek()==',')
                row.get();
        }
        groups[program] = programs;
    }

    for (auto pr = begin(groups); pr != end(groups); ++pr) {
        mergeprogram((*pr).first, groups);
    }
    cout << "Group 0 is: " << groups[0].size() << endl;
    cout << "There are : " << groups.size() << " groups" << endl;
    return 0;
}

Output:

/*
C:\Workarea\AOC2017\day 12\x64\Debug>"day 12.exe" < input.txt
Group 0 is: 145
There are : 207 groups

C:\Workarea\AOC2017\day 12\x64\Debug>
*/

Day 11 - Hex Ed

Rank: 1035 / 1068

I 'live-streamed' this one, and it slowed me down a bit. I also gave up on the live-stream and was able to get my solution working in about 5 more minutes.

You have the path the child process took. Starting where he started, you need to determine the fewest number of steps required to reach him. (A "step" means to move from the hex you are in to any adjacent hex.)

How many steps away is the furthest he ever got from his starting position?

// Advent of Code 2017
// http://adventofcode.com/
// Day 11 - Hex Ed

#include "stdafx.h"
#include <iostream>
#include <string>
#include <map>
#include <algorithm>
#include <numeric>
using namespace std;


/* Reduction Rules

fwd back
s   n  -> o
se  nw -> o         // fixed typo
ne  sw -> o

l1 l2    r
n  se -> ne
n  sw -> nw
s  ne -> se
s  nw -> sw
ne nw -> n
se sw -> s

*/

void reduce_turn(map<string, int>& path, string l1, string l2, string r)
{
    int reduce_by = min(path[l1], path[l2]);
    path[l1] -= reduce_by;
    path[l2] -= reduce_by;
    path[r] += reduce_by;
}

void reduce_fwd_back(map<string, int>& path, string fwd, string back)
{
    int reduce_by = min(path[fwd], path[back]);
    path[fwd]  -= reduce_by;
    path[back] -= reduce_by;
}

int reduce(map<string, int> path)
{
    reduce_turn(path, "n" , "se", "ne");
    reduce_turn(path, "n" , "sw", "nw");
    reduce_turn(path, "s" , "ne", "se");
    reduce_turn(path, "s" , "nw", "sw");
    reduce_turn(path, "ne", "nw", "n" );
    reduce_turn(path, "se", "sw", "s" );

    reduce_fwd_back(path, "n" , "s" );
    reduce_fwd_back(path, "ne", "sw");
    reduce_fwd_back(path, "nw", "se");
    return accumulate(begin(path), end(path), 0, 
	    [](const int prev, pair<string, int> ent) {return prev + ent.second; });
}

int main(int argc, char* argv[])
{
    map<string,int> path;
    int maxpath{ 0 };
    string dir;
    while (cin >> dir) {
        path[dir]++;
        maxpath = max(maxpath,reduce(path));
    }
    cout << "Path:    " << reduce(path) << endl;
    cout << "Maxpath: " << maxpath << endl;
    return 0;
}

Output:

C:\Workarea\AOC2017\day 11\x64\Release>"day 11.exe" < input.txt
Path:    720
Maxpath: 1485

C:\Workarea\AOC2017\day 11\x64\Release>

Day 10 - Knot Hash

Rank: 257 / 463

Once this process is complete, what is the result of multiplying the first two numbers in the list?

Treating your puzzle input as a string of ASCII characters, what is the Knot Hash of your puzzle input?

// Advent of Code 2017
// Day 10 - Knot Hash

#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <map>
#include <sstream>
#include <algorithm>
#include <numeric>
#include <functional>

using namespace std;

void reverse(vector<int>& numbers, int start, int length)
{
    for (auto pos{ 0 }; pos < length / 2; ++pos)
        swap(numbers[(start + pos) % 256], numbers[(start + length - 1 - pos) % 256]);
}

int main()
{
    vector<int> numbers(256);
    vector<int> lengths = {192, 69, 168, 160, 78, 1, 166, 28, 0, 83, 198, 2, 254, 255, 41, 12};
    string input = "192,69,168,160,78,1,166,28,0,83,198,2,254,255,41,12";
    vector<int> trailing{ 17, 31, 73, 47, 23 };
    vector<int> hash(16);

    cout << "Part 1: ";
    iota(numbers.begin(), numbers.end(), 0);
    for (auto l{ 0 }, start{ 0 }, skip{ 0 }; l < lengths.size(); start+=lengths[l]+l++,++skip) {
        reverse(numbers,start %= 256, lengths[l]);
    }
    cout << numbers[0]*numbers[1] << endl;

    cout << "Part 2: ";
    iota(numbers.begin(), numbers.end(), 0);
    lengths.resize(input.size()+trailing.size());
    copy(input.begin(), input.end(), lengths.begin());
    copy(trailing.begin(),trailing.end(),lengths.end()-trailing.size());
    auto start{ 0 }, skip{ 0 };
    for (int r = 0; r < 64; ++r) {
        for (auto l{ 0 }; l < lengths.size(); start += lengths[l] + skip++, l++) {
            reverse(numbers, start %= 256, lengths[l]);
        }
    }
    for (int i{ 0 }, hashchar{ 0 }; i < 256; ++i) {
        hashchar = i % 16 == 0 ? numbers[i] : hashchar ^ numbers[i];
        i%16==15 && cout << setw(2) << setfill('0') << hex << hashchar;
    }
    return 0;
}

Output:

C:\Workarea\AOC2017\day 10\x64\Debug>"day 10.exe"
Part 1: 48705
Part 2: 1c46642b6f2bc21db2a2149d0aeeae5d
C:\Workarea\AOC2017\day 10\x64\Debug>

Rank: 314 / 256

Count and accumulate a simple nested grammar and skip an almost as simple garbage product. e.g. {{}{}<!>>{<>}}

// Advent of Code 2017 - Day 9 - Stream Processing
#include <iostream>
int main()
{
    int nest = 0, tot = 0, garbage = 0, gc=0;
    char ch;
    for (char ch; std::cin >> ch;) {
        if (!garbage) { switch (ch) {   case '<': garbage=1; break;
                                        case '{': ++nest; break;
                                        case '}': tot += nest--; break; }
        } else {        switch (ch) {   case '!': std::cin.get(); break;
                                        case '>': garbage = 0; break;
                                        default:  gc++; break; }
        }
    }
    std::cout << tot << std::endl;
    std::cout << gc << std::endl;
    return 0;
}

Rank: 931 / 910

What is the largest value in any register after completing the instructions in your puzzle input?

Additionally, to be safe, the CPU also needs to know the highest value held in any register during this process so that it can decide how much memory to allocate to these operations.

// Advent of Code 2017
// http://adventofcode.com/
// Day 08 - I Heard You Like Registers

#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <sstream>
#include <algorithm>
#include <numeric>
#include <functional>

using namespace std;

/*
m n   o p  q r s
b inc 5 if a > 1
a inc 1 if b < 5
c dec -10 if a >= 1
c inc -20 if c == 10
*/

void step(map<string, function<bool(int, int)> > ops, map<string, int>& reg, map<string, int>& regmax, stringstream ins)
{
    string m, n, p, q, r; int o, s;
    ins >> m >> n >> o >> p >> q >> r >> s;
    if (ops[r](reg[q],s))
        reg[m] += o*(n == "inc" ? 1 : -1);
    regmax[m] = max(reg[m], regmax[m]);
}

int main(int argc, char* argv[])
{
    map<string, function<bool(int, int)> > ops;
    ops["<"] =  [](int a, int b)->bool {return a <  b; };
    ops[">"] =  [](int a, int b)->bool {return a >  b; };
    ops["<="] = [](int a, int b)->bool {return a <= b; };
    ops[">="] = [](int a, int b)->bool {return a >= b; };
    ops["=="] = [](int a, int b)->bool {return a == b; };
    ops["!="] = [](int a, int b)->bool {return a != b; };

    map<string, int> reg, regmax;
    string row;
    while (getline(cin, row))
        step(ops, reg, regmax, stringstream(row));
    cout << "Max (final): " << (*max_element(reg.begin(), reg.end(), [](pair<string, int> p1, pair<string, int> p2) {return p1.second < p2.second; })).second << endl;
    cout << "Max (ever ): " << (*max_element(regmax.begin(), regmax.end(), [](pair<string, int> p1, pair<string, int> p2) {return p1.second < p2.second; })).second << endl;
    return 0;
}

Output:

Max (final): 4902
Max (ever ): 7037

Rank: 6625 / 5791

Notes: This has now been cleaned up significantly. The input data is filtered and massaged, which is cheap and simplifies parsing. I have also broken out the fixing up of the nodes into a tree out into a separate piece of code.

What is the name of the bottom program?

Additionally, given that exactly one program is the wrong weight, what would its weight need to be to balance the entire tower?

// Advent of Code 2017
// http://adventofcode.com/

#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <sstream>
#include <algorithm>
#include <numeric>

using namespace std;

struct node;
typedef struct node { string name; vector<node*> children; int size; } node;

void parse(map<string, node*>& nodes, stringstream input)
{
    node *n = new node;
    input >> n->name >> n->size;
    for (string name; input >> name ;) {
        n->children.push_back(new node);
        n->children.back()->name = name;
    }
    nodes[n->name] = n;
}

void fixup(map<string, node*>& nodes)
{
    vector<string> appearaschildren;
    for (auto it = nodes.begin(); it != nodes.end(); ++it)
        for (auto it2 = (*it).second->children.begin(); it2 != (*it).second->children.end(); ++it2) {
            appearaschildren.push_back((*it2)->name);
            *it2 = nodes[(*it2)->name];
        }
    for_each(appearaschildren.begin(), appearaschildren.end(), [&](string n) {nodes.erase(n); });
}

int compute_size(node *n)
{
    int childtot = 0;
    for (auto it = n->children.begin(); it != n->children.end(); ++it)
        childtot += compute_size(*it);
    return n->size += childtot;
}

void find_balance(node * n, int imbalance)
{
    sort(n->children.begin(), n->children.end(), [](node *a, node *b)->bool {return a->size < b->size; });
    size_t last{ n->children.size() - 1 };
    if (n->children[0]->size != n->children[1]->size) 
        find_balance(n->children[0], n->children[1]->size - n->children[0]->size);
    else if (n->children[last]->size != n->children[last - 1]->size)
        find_balance(n->children[last], n->children[last-1]->size - n->children[last]->size);
    else {
        int childtot{ 0 };
        for (auto it = n->children.begin(); it != n->children.end(); ++it)
            childtot += (*it)->size;
        cout << "node: " << n->name << " should be " << n->size <<
            " + " << imbalance << " - " << childtot << " -> " << n->size + imbalance - childtot << endl;
    }
}

int main(int argc, char* argv[])
{
    map<string, node*> nodes;
    string row, name;
    while (getline(cin, row)) {
        row.erase(remove_if(row.begin(), row.end(), [](int i)->bool {return i == '(' || i == ')' || i == ',' || i == '-' || i == '>';}), row.end());
        parse(nodes, stringstream(row));
    }
    fixup(nodes);
    node * n = (*find_if(nodes.begin(), nodes.end(), [](pair<string, node*>p)->bool {return p.second != nullptr; })).second;
    cout << "name: " << n->name << " size: " << n->size << " children: " << n->children.size() << endl;
    compute_size(n);
    find_balance(n, 0);
    return 0;
}

Output is:

C:\Workarea\AOC2017\day 07\x64\Debug>"day 07.exe" < input.txt
name: jovejmr size: 40 children: 0
name: fesmk size: 24 children: 0
...redacted...
name: gynzo size: 86 children: 0
name: wnwzo size: 37 children: 0
nodes count: 1
name: ahnofa size: 7 children: 6

Balancing - Part 2

balance node: ahnofa
...
name: hwezjo size: 69875 children: 3
name: qqqxyrl size: 69875 children: 6
name: luralcy size: 69881 children: 5
balance node: luralcy
...
name: osgijzx size: 13964 children: 4
name: uppcjl size: 13964 children: 3
name: bvrxeo size: 13970 children: 6
balance node: bvrxeo
...
name: vvgyhb size: 1786 children: 3
name: ltleg size: 1792 children: 6
balance node: ltleg
...
name: kzuimi size: 164 children: 2
name: kwlqal size: 164 children: 2
name: lahieha size: 164 children: 4
children are balanced
node: ltleg should be 1792 + -6 - 984 -> 802

C:\Workarea\AOC2017\day 07\x64\Debug>

Rank: 5253 / 5049

Given the initial block counts in your puzzle input, how many redistribution cycles must be completed before a configuration is produced that has been seen before?

Additionally, how many cycles are in the infinite loop that arises from the configuration in your puzzle input?

Cleaned up courtesy of this post on reddit.

// Advent of Code 2017
// http://adventofcode.com/

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <map>

using namespace std;

void reallocate(vector<int>& m)
{
    auto me = max_element(m.begin(),m.end());
    for (auto b{ exchange(*me,0) }; b--; ++*me) {
        if (++me==m.end()) 
            me=m.begin();
    }
}

int main(int argc, char* argv[])
{
    vector<int> m = { 10, 3, 15, 10, 5, 15, 5, 15, 9, 2, 5, 8, 5, 2, 3, 6 }; //vector<int> m = {0,2,7,0};
    map<vector<int>, int> states;
    auto cycles = 0;
    for (auto cycle{ 0 }; states.insert(pair<vector<int>, int>(m, cycles))./*did insert*/second == true; reallocate(m))
        cycles++;
    cout << "Part 1: " << cycles << endl <<
            "Part 2: " << cycles-states[m] << endl;
    return 0;
}

Output is

C:\Workarea\AOC2017\day 06\x64\Release>"day 06.exe"
Part 1: 14029
Part 2: 2765

C:\Workarea\AOC2017\day 06\x64\Release>

Rank: 6932 / 6599

How many steps does it take to reach the exit?

Additionally, now the jumps are even stranger: after each jump, if the offset was three or more, instead decrease it by 1. Otherwise, increase it by 1 as before. How many steps does it now take to reach the exit?

// Advent of Code 2017
// http://adventofcode.com/

#include <iostream>
#include <string>
#include <vector>
#include <iterator>

using namespace std;

int interpret(vector<int> ins,bool part2 = false)
{
    int executioncount{ 0 }, pc{ 0 };
    while (pc>=0 && pc<ins.size())
        executioncount++, pc += (part2 && ins[pc]>2 ? ins[pc]-- : ins[pc]++);
    return executioncount;
}

int main(int argc, char* argv[])
{
    vector<int> ins{ istream_iterator<int>{std::cin},{} };
    cout << "Executed part 1: " << interpret(ins) << endl;
    cout << "Executed part 2: " << interpret(ins,true) << endl;
    return 0;
}

Output is:

C:\Workarea\AOC2017\day 05\x64\Release>"day 05.exe" < input.txt
Executed part 1: 394829
Executed part 2: 31150702

C:\Workarea\AOC2017\day 05\x64\Release>

Rank: 1410 / 1109

The system's full passphrase list is available as your puzzle input. How many passphrases are valid?

Additionally, for added security, yet another system policy has been put in place. Now, a valid passphrase must contain no two words that are anagrams of each other - that is, a passphrase is invalid if any word's letters can be rearranged to form any other word in the passphrase. Under this new system policy, how many passphrases are valid?

// day04.cpp : Defines the entry point for the console application.
// Advent of Code 2017
// http://adventofcode.com/

#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <sstream>
#include <algorithm>


int main(int argc, char* argv[])
{
    int validcount = 0;
    std::string row;
    while (std::getline(std::cin,row) && row.length()>0) {
        std::stringstream str(row);
        std::vector<std::string> words;
        std::string pass;
        bool INVALID = false;
        while (str >> pass) {
            // Uncomment to sort individual words, so we catch 'anagrams'
            //std::sort(pass.begin(),pass.end());
            if (std::find(words.begin(),words.end(),pass)==words.end()) {
                // push back any words we don't already have
                words.push_back(pass);
            } else {
                // we found a repeated word, INVALID
                std::cout << pass << " invalid on " << row << std::endl;
                INVALID=true;
            }
        }
        // 
        if (!INVALID)
            validcount++;
    }
    std::cout << "Valid count is " << validcount << std::endl;
    return 0;
}

Code for Day 03.cpp

I wanted another go at this, as I wan't happy with my spiral generating code.

How many steps are required to carry the data from the square identified in your puzzle input all the way to the access port?

What is the first value written that is larger than your puzzle input?

Here is the code:

// day3_redo.cpp : Defines the entry point for the console application.
// Advent of Code 2017
// http://adventofcode.com/

#include "stdafx.h"
#include <iostream>
#include <string>
#include <limits>
#include <vector>
#include <map>

typedef enum dir {e=0,n,w,s} direction;
direction next_dir[] = {n,w,s,e};
direction d=e;
int x=0, y=0, count=1, done=0;

// generate spiral coords per the puzzle
void next_coord(int& x, int&y)
{
    x += d==e ? 1 : (d==w) ? -1 : 0;        // east or west
    y += d==n ? 1 : (d==s) ? -1 : 0;        // north or south
    if (++done==count) done=0;              // moved required number of spots
    if (!done && (d==n || d==s)) count++;   // bump count on n or s
    if (!done) d = next_dir[d];             // switch direction
}

// get a value and iterate through the spiral, counting the x,y
// distance is then just abs(x)+abs(y)
int main1(int argc, char* argv[])
{
    std::cout << "Enter value (-1 to quit part 1)" << std::endl;
    int val;
    while (1) {
        std::cin >> val;
        if (val==-1) break;
        for (int i=1; i<val; ++i) {
            next_coord(x,y);
        }
        std::cout << "Distance is " << abs(x)+abs(y) << std::endl;
    }
    return 0;
}

// track spiral totals in part 2
std::map<std::string,int> sum;

// x,y -> "x,y" 
std::string idx(int x,int y)
{
    std::string idx = std::to_string((long long)x);
    idx.push_back(',');
    idx.append(std::to_string((long long)y));
    return idx;
}

// lookup a sum at cell x,y
int lookup(int x, int y)
{
    std::string id = idx(x,y);
    if (sum.find(id)!=sum.end())
        return sum[id];
    return 0;
}

// sum the 8 neighbors of x,y and save it
int save_sum(int x,int y)
{
    int tot=lookup(x-1,y-1)+lookup(x,y-1)+lookup(x+1,y-1)+lookup(x-1,y+1)+lookup(x,y+1)+lookup(x+1,y+1)+lookup(x-1,y)+lookup(x+1,y);
    return (sum[idx(x,y)]=tot);
}

int main2(int argc, char* argv[])
{
    sum[idx(0,0)] = 1;

    std::cout << "Enter value (-1 to quit part 2)" << std::endl;
    int val,sum;
    while (1) {
        std::cin >> val;
        if (val==-1) break;

        d=e, x=0, y=0, count=1, done=0;
        do {
            next_coord(x,y);
            sum = save_sum(x,y);
        } while (sum<=val);

        std::cout << "Value is " << sum << std::endl;
    }
    return 0;
}

int main(int argc, char* argv[])
{
    main1(argc,argv);
    main2(argc,argv);
}

Here is the output:

Enter value (-1 to quit part 1)
347991
Distance is 480
-1
Enter value (-1 to quit part 2)
347991
Value is 349975

Rank: 5454 / 3723 (Based on this code, not the rewrite)

How many steps are required to carry the data from the square identified in your puzzle input all the way to the access port?

What is the first value written that is larger than your puzzle input?

Here's the code:

// day3.cpp : Defines the entry point for the console application.
// Advent of Code 2017
// http://adventofcode.com/

#include "stdafx.h"
#include <iostream>
#include <string>
#include <limits>
#include <vector>
#include <map>

// track spiral totals in part 2
std::map<std::string,int> sum;

// x,y -> "x,y" 
std::string idx(int x,int y)
{
    std::string idx = std::to_string((long long)x);
    idx.push_back(',');
    idx.append(std::to_string((long long)y));
    return idx;
}

// lookup a sum at cell x,y
int lookup(int x, int y)
{
    std::string id = idx(x,y);
    if (sum.find(id)!=sum.end())
        return sum[id];
    return 0;
}

// sum the 8 neighbors of x,y and save it
int save_sum(int x,int y)
{
    int tot = 0;
    tot += lookup(x-1,y-1);
    tot += lookup(x,y-1);
    tot += lookup(x+1,y-1);
    tot += lookup(x-1,y+1);
    tot += lookup(x,y+1);
    tot += lookup(x+1,y+1);
    tot += lookup(x-1,y);
    tot += lookup(x+1,y);

    sum[idx(x,y)] = tot;
    std::cout << tot << std::endl;
    return tot;
}

// given a value, do spiral enwwsseeennn... etc. summing the 8 neighbors as we go
// find the first value higher than the problem input
int main2(int argc, char* argv[])
{
    sum[idx(0,0)] = 1;

    std::cout << "Enter a value for part 2" << std::endl;
    int val;
    std::cin >> val;

    int x=0, y=0;
    int count = 0;
    while(1) {
        // move east
        count++;
        for (int i=0;i<count;i++) {
            x++;
            if (val<save_sum(x,y))
                goto done;
        }
        // move north
        for (int i=0;i<count;i++) {
            y++;
            if (val<save_sum(x,y))
                goto done;
        }
        // move west
        count++;
        for (int i=0;i<count;i++) {
            x--;
            if (val<save_sum(x,y))
                goto done;
        }
        // move south
        for (int i=0;i<count;i++) {
            y--;
            if (val<save_sum(x,y))
                goto done;
        }
    }
done:
    std::cin >> val;
    return 0;
}

// part 1 given a spiral starting at 1, calculate the manhattan distance back
// to the center from the problem input.
// I used the following for some clues http://mathforum.org/library/drmath/view/62201.html
// then hack hack hack...
int main1(int argc, char* argv[])
{
    int val;
    std::cout << "Enter a value (or -1 to quit part 1)" << std::endl;
    while (1) {
        std::cin >> val;
        if (val==-1)
            break;
        int side = 1;
        int count = 1;
        int inner = 0;
        int pos = 0;
        int of = 0;
        int dist = 0;
        int rings = 1;

        do {                                    // iterate til we get a big enough ring
            side += 2;
            count = side*side;
            rings++;
        } while (count<val);
        inner = side>1 ? (side-2)*(side-2) : 0; // count of cells inside the ring
        pos = ((val-inner)+side/2)%(side-1);    // distance away from the 12pm 3pm 6pm 9pm positions
        of = (side-1)*(side-1);                 // unused - cells in this ring
        dist = pos + rings-1;                   // total manhattan distance

        std::cout << "Rings " << rings << std::endl;
        std::cout << "Side  " << side << std::endl;
        std::cout << "Pos   " << pos << std::endl;
        std::cout << "Of    " << of << std::endl;
        std::cout << "Dist  " << dist << std::endl;
    };
    return 0;
}

int main(int argc, char* argv[])
{
    main1(argc,argv);
    main2(argc,argv);
}

Here's the output:

Enter a value (or -1 to quit part 1)
347991
Rings 296
Side  591
Pos   185
Of    348100
Dist  480
-1
Enter a value for part 2
347991
...output redacted...
349975

Rank: 6722 / 6018

Part 1

Accumulate the difference between the largest and smallest value on each line.

// Advent of Code 2017
// Day 2 - Corruption Checksum Part 1

#include "stdafx.h"
#include <iostream>
#include <string>
#include <sstream>
#include <limits>
#include <algorithm>

int main(int argc, char* argv[])
{
    std::string row;
    int num = 0;
    int check = 0;
    while (std::getline(std::cin,row) && row.length()>0) {
        std::stringstream str(row);
        int min = INT_MAX;
        int max = INT_MIN;
        while (str >> num) {
            min = std::min(min,num);
            max = std::max(max,num);
        }
        check += max-min;
    }
    std::cout << "Checksum is " << check << std::endl;
    return 0;
}

Part 2

Find the only two evenly divisible numbers on each line and accumulate the result of each division by line.

// Advent of Code 2017
// Day 02 - Corruption Checksum Part 2

#include "stdafx.h"
#include <iostream>
#include <string>
#include <sstream>
#include <limits>
#include <vector>
#include <algorithm>

int main(int argc, char* argv[])
{
    std::string row;
    int num = 0;
    int check = 0;
    std::vector<int> arr;
    while (std::getline(std::cin,row) && row.length()>0) {
        std::stringstream str(row);
        arr.erase(arr.begin(),arr.end());
        while (str >> num)
            arr.push_back(num);
        for (auto it = arr.begin(); it<arr.end(); ++it) {
            for (auto it2 = arr.begin(); it2<arr.end(); ++it2) {
                int di = *it;
                int dv = *it2;
                if (di>dv && di%dv==0) {
                    check += (di/dv);
                }
            }
        }
    }

    std::cout << "Checksum is " << check << std::endl;
    return 0;
}

Rank: 7576 / 6254

Find the sum of all digits that match the next digit in the list.

// Advent of Code 2017 
// Day 1 - Inverse Captcha
#include "stdafx.h"
char * input = "5228833336355848549915459366737982598312959583817455621545976784792489468198365998232722734876612332352376192813552949814275947575774339529811976644361517795586998319242241614813622734255797569571577699238592667287428166398221572885869416419682687759743978434571821267146514338394624525648338739929479912368172669885577319718389278168766844487948761697438722556857882433224393723131298876252626643517236883999115665656935521675772866516185899317132494716723615493476397115627687887665194781746377341468995954554518252916859227397693885254329628812355612487594445522395853551734567498838382248616137969637971369615443599973588326388792893969924855316437952313492551671545714262784738343517166544197194547173515155927244175447296474282154114951181648317875827525814453758846194548872789943372281952995222779173812444186491115426476188672253249744478946863317915136832199132868917891243591195719354721129116229164688256853628339233919671468781913167415624214152793864585332944468428849171876873433621524242289488135675313544498245498637424139153782925723745249728743885493877792648576673196889949568317234125863369187953788611841388353999875519172896329524346527265231767868839696693328273381772726782949166112932954356923757485139367298699922984925977724972944277991686823219295939734313874834861796179591659174726432357533113896212781566659154939419866797488347448551719481632572231632463575591599696388223344219228325134233238538854289437756331848887242423387542214691157226725179683638967415678697625138177633444765126223885478348951332634398291612134852858683942466178329922655822225426534359191696177633167962839847985826676955417426617126288255366123169174674348417932158291334646767637764323226842771523598562429399935789788215958367362467652444854123951972118358417629679454978687337137675495295768451719631999398617828287671937584998697959425845883145736323818225129311845997214987663433375689621746665629187252511643969315283316269222835744532431378945137649959158495714472963839397214332815241141327714672141875129895";
int main(int argc, char* argv[])
{
	char * pos = input;
	unsigned int total = 0;
	unsigned int prevdigit = (*(pos+strlen(input)-1))-'0';
	unsigned int curdigit = 0;
	while (*pos) {
		curdigit = (*pos++)-'0';
		if (curdigit==prevdigit)
			total += curdigit;
		prevdigit = curdigit;
	}

	printf("total = %d\n",total);
	return 0;
}

Part 2

Find the sum of all digits that match the digit halfway further through the list.

// Advent of Code 2017
// Day 1 - Inverse Captcha
#include "stdafx.h"
#include <string.h>
char * input = "5228833336355848549915459366737982598312959583817455621545976784792489468198365998232722734876612332352376192813552949814275947575774339529811976644361517795586998319242241614813622734255797569571577699238592667287428166398221572885869416419682687759743978434571821267146514338394624525648338739929479912368172669885577319718389278168766844487948761697438722556857882433224393723131298876252626643517236883999115665656935521675772866516185899317132494716723615493476397115627687887665194781746377341468995954554518252916859227397693885254329628812355612487594445522395853551734567498838382248616137969637971369615443599973588326388792893969924855316437952313492551671545714262784738343517166544197194547173515155927244175447296474282154114951181648317875827525814453758846194548872789943372281952995222779173812444186491115426476188672253249744478946863317915136832199132868917891243591195719354721129116229164688256853628339233919671468781913167415624214152793864585332944468428849171876873433621524242289488135675313544498245498637424139153782925723745249728743885493877792648576673196889949568317234125863369187953788611841388353999875519172896329524346527265231767868839696693328273381772726782949166112932954356923757485139367298699922984925977724972944277991686823219295939734313874834861796179591659174726432357533113896212781566659154939419866797488347448551719481632572231632463575591599696388223344219228325134233238538854289437756331848887242423387542214691157226725179683638967415678697625138177633444765126223885478348951332634398291612134852858683942466178329922655822225426534359191696177633167962839847985826676955417426617126288255366123169174674348417932158291334646767637764323226842771523598562429399935789788215958367362467652444854123951972118358417629679454978687337137675495295768451719631999398617828287671937584998697959425845883145736323818225129311845997214987663433375689621746665629187252511643969315283316269222835744532431378945137649959158495714472963839397214332815241141327714672141875129895";
int main(int argc, char* argv[])
{
	char * pos = input;
	unsigned int len = strlen(input);
	unsigned int total = 0;
	unsigned int chkdigit = 0;
	unsigned int curdigit = 0;
	while (pos-input<len/2) {
		curdigit = *pos-'0';
		chkdigit = *(pos++ +len/2)-'0';
		if (curdigit==chkdigit)
			total += curdigit+chkdigit;
	}
	printf("total = %d\n",total);
	return 0;
}