Skip to content

Commit

Permalink
Day 1 part 2 perf update (#114)
Browse files Browse the repository at this point in the history
  • Loading branch information
evqna committed Dec 9, 2018
1 parent 9319957 commit 326a012
Showing 1 changed file with 63 additions and 12 deletions.
75 changes: 63 additions & 12 deletions day-01/part-2/evqna.cpp
@@ -1,7 +1,9 @@
#include <algorithm>
#include <iostream>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <vector>

using namespace std;
Expand All @@ -15,21 +17,70 @@ vector<int> parse_input(const string& in) {
return vec;
}

struct Val {
int value;
int index; // The index of this value in the accumulation table

bool operator<(const Val& b) const {
return this->value < b.value;
}
};

int mod(int n, int d) {
int r = n % d;
if (r < 0) r += d;
return r;
}

int run(const string& in) {
auto commands = parse_input(in);

int freq = 0;
set<int> cache;

size_t i = 0;
do {
cache.insert(freq);
freq += commands[i++];
if (i == commands.size())
i = 0;
} while (cache.find(freq) == cache.end());

return freq;
// Iterate once over input and build frequency table
set<int> seen = {0};
vector<int> accumulator = {0};
for (int i = 0; i < commands.size(); i++) {
int freq = accumulator[i] + commands[i];
// Check if freq is repeated during first iteration
if (seen.find(freq) != seen.end())
return freq;
accumulator.push_back(freq);
seen.insert(freq);
}

// On every following iteration, the frequency table is translated by this delta
int runDelta = accumulator.back();
if (runDelta == 0)
return 0;

accumulator.pop_back();

unordered_map<int, vector<Val>> freqByModulus;
for (int i = 0; i < accumulator.size(); i++)
freqByModulus[mod(accumulator[i], runDelta)].push_back({accumulator[i], i});

// Find frequencies in the same group with minimal difference
int minDelta = -1, minIndex = -1, minFreq = -1;
for (auto& pair : freqByModulus) {
auto& values = pair.second;
if (values.size() > 1) {
// Sort the frequencies by value to find minimal delta in linear time
sort(values.begin(), values.end());
for (int i = 1; i < values.size(); i++) {
int delta = values[i].value - values[i-1].value;
// If mod is positive v[i-1] -> v[i]
// If mod is negative v[i-1] <- v[i]
int index = runDelta > 0 ? values[i-1].index : values[i].index;
int freq = runDelta > 0 ? values[i].value : values[i-1].value;
if (minDelta < 0 || delta < minDelta || (delta == minDelta && (minIndex < 0 || index < minIndex))) {
minDelta = delta;
minIndex = index;
minFreq = freq;
}
}
}
}

return minFreq;
}

int main(int argc, char **argv) {
Expand Down

0 comments on commit 326a012

Please sign in to comment.