Advent of Code 2017 Day 6 (part 2) in Functional Programming (FP)

I wanted to practice functional programming (FP) without using any library but using vanilla JS only. So I took a problem from Advent of Code (the 2nd part of Day 6).

You can only access the 2nd part if you type in the solution for the 1st part: 3156 or look at my solution for part 1.

--- Part Two --- Out of curiosity, the debugger would also like to know the size of the loop: starting from a state that has already been seen, how many block redistribution cycles must be performed before that same state is seen again?

In the example above, 2 4 1 2 is seen again after four cycles, and so the answer in that example would be 4.

How many cycles are in the infinite loop that arises from the configuration in your puzzle input?

This is my FP solution:

/*jshint esversion: 6*/

const banks = 2    8   8   5   4   2   3   1   5   5   1   2   15  13  5   14;
const parse = input => input
.split('\t')
.map(c => parseInt(c));
const copy = input => input.slice();

const INPUT = parse(banks);
const redistribute = (input, index, toBeDistributed) => {
if (!toBeDistributed) return input;
const nextIndex = index + 1;
const nextInput = input;
++nextInput[nextIndex % input.length];
return redistribute(nextInput, nextIndex, --toBeDistributed);
};
const isUnique = toCheck => state => toCheck.toString() !== state.toString();

const solveDaySix = input => {
let banks = copy(input);
const states = [input];
let cycle = 0;
let foundState = [];
while (true) {
++cycle;
const max = Math.max(...banks);
const index = banks.indexOf(max);
banks[index] = 0;
banks = copy(redistribute(banks, index, max));
const stateIsUnique = isUnique(banks);

if (!states.every(stateIsUnique)) {
foundState = copy(banks);
break;
}
states.push(copy(banks));
}
cycle = 0;
while (true) {
++cycle;
const max = Math.max(...banks);
const index = banks.indexOf(max);
banks[index] = 0;
banks = copy(redistribute(banks, index, max));
const stateIsUnique = isUnique(banks);

if (banks.toString() === foundState.toString()) {
break;
}
}
return cycle;
};

console.log("solution ", solveDaySix(INPUT));


I got 2 while loops that are nearly identical. Is there a way to refactor them? I tried to refactor them into one function. But that function takes and returns 4 parameters:

/*jshint esversion: 6*/

const banks = 2    8   8   5   4   2   3   1   5   5   1   2   15  13  5   14;
const parse = input => input
.split('\t')
.map(c => parseInt(c));
const copy = input => input.slice();

const INPUT = parse(banks);
const redistribute = (input, index, toBeDistributed) => {
if (!toBeDistributed) return input;
const nextIndex = index + 1;
const nextInput = input;
++nextInput[nextIndex % input.length];
return redistribute(nextInput, nextIndex, --toBeDistributed);
};
const isUnique = toCheck => state => toCheck.toString() !== state.toString();
const getCycle = (banks, states, foundState, condition) => {
let cycle = 0;
while(true) {
++cycle;
const max = Math.max(...banks);
const index = banks.indexOf(max);
banks[index] = 0;
banks = copy(redistribute(banks, index, max));
const stateIsUnique = isUnique(banks);
if (condition(states, foundState, banks)) {
foundState = copy(banks);
return { banks, states, cycle, foundState };
}
states.push(copy(banks));
}
};

const solveDaySix = input => {
let banks = copy(input);
let states = [input];
let cycle = 0;
let foundState = [];

let {banks: nextBanks, states: nextStates, foundState: nextFoundState } = getCycle(banks, states, [], (s, f, b) => !s.every(isUnique(b)));

let {cycle: secondCycle} = getCycle(nextBanks, nextStates, nextFoundState, (states, nextFoundState, b) => b.toString() === nextFoundState.toString());
return secondCycle;
};

console.log("solution ", solveDaySix(INPUT));


Even though it works, I have a hunch that there is a more elegant way.