findFields = input => {
const { rules, nearby, myTicket } = parse(input);
const validTickets = nearby.filter(ticket =>
ticket.every(n => Object.values(rules).some(rule => rule(n)))
);
let availableRules = Object.keys(rules);
const numRules = Object.keys(rules).length;
const validRules = Array.apply(null, { length: numRules }).map(i => []);
do {
for (let i = 0; i < numRules; i++) {
if (validRules[i] && validRules[i].length === 1) continue;
validRules[i] = availableRules.filter(name =>
validTickets.every(ticket => rules[name](ticket[i]))
);
if (validRules[i].length === 1) {
availableRules = availableRules.filter(
name => name !== validRules[i][0]
);
}
}
} while (availableRules.length > 0);
return _.zip(validRules.flat(), myTicket)
.filter(f => f[0].startsWith('departure'))
.reduce((acc, field) => acc * field[1], 1);
}