Skip to content

Instantly share code, notes, and snippets.

@mctrafik
Created December 19, 2023 19:48
Show Gist options
  • Save mctrafik/2b07626303edb4d47d16951d4a35b993 to your computer and use it in GitHub Desktop.
Save mctrafik/2b07626303edb4d47d16951d4a35b993 to your computer and use it in GitHub Desktop.
AOC 2023: Problem 19
type Flow =
| { type: 'go'; dest: string }
| { type: 'gt'; var: Key; value: number; dest: string }
| { type: 'lt'; var: Key; value: number; dest: string };
const rule: Record<string, Flow[]> = {};
const [rules, parts] = parsed;
for (const ruleLine of rules.split('\n')) {
const [name, rulePart] = ruleLine.split('{');
rule[name] = rulePart
.substring(0, rulePart.length - 1)
.split(',')
.map((rule) => {
if (rule.includes('>')) {
const [, variable, value, dest] = rule.match(/^(\w+)>(\d+):(\w+)$/)!;
return {
type: 'gt',
value: Number(value),
var: variable as Key,
dest,
};
}
if (rule.includes('<')) {
const [, variable, value, dest] = rule.match(/^(\w+)<(\d+):(\w+)$/)!;
return {
type: 'lt',
value: Number(value),
var: variable as Key,
dest,
};
}
return {
type: 'go',
dest: rule,
};
});
}
let answer2 = 0;
type State = {
name: string;
mins: Record<Key, number>;
maxs: Record<Key, number>;
};
graphSearch<State>({
initial: [
{
name: 'in',
mins: { x: 1, m: 1, a: 1, s: 1 },
maxs: { x: 4e3, m: 4e3, a: 4e3, s: 4e3 },
},
],
newStates: function (state: State, onNewState: (state: State) => void): void {
if (state.name === 'R') return;
if (state.name === 'A') {
console.log(`Accepted:`, state);
let perms = 1;
for (let v of 'xmas'.split('') as Key[]) {
perms *= state.maxs[v] - state.mins[v] + 1;
}
answer2 += perms;
return;
}
for (const r of rule[state.name]) {
switch (r.type) {
case 'go': {
onNewState({
name: r.dest,
maxs: clone(state.maxs),
mins: clone(state.mins),
});
return;
}
case 'gt': {
// Can never meet condition
if (state.maxs[r.var] <= r.value) {
continue;
}
// Else explore if condition is met.
onNewState({
name: r.dest,
maxs: clone(state.maxs),
mins: { ...state.mins, [r.var]: r.value + 1 },
});
// Continue as-if condition couldn't be met.
state.maxs[r.var] = r.value;
continue;
}
case 'lt': {
// Can never meet condition.
if (state.mins[r.var] >= r.value) {
continue;
}
// Else explore if condition is met.
onNewState({
name: r.dest,
mins: clone(state.mins),
maxs: { ...state.maxs, [r.var]: r.value - 1 },
});
// Continue as-if condition couldn't be met.
state.mins[r.var] = r.value;
continue;
}
}
}
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment