library(testthat)

# Get the index of the largest bank

bank_to_split_loc <- function(x) {

which(x == max(x))[1] # subset to break ties

}

expect_equal(bank_to_split_loc(dat), 3)

# Takes a vector and balances the banks by distributing the largest one over the rest

balance_banks <- function(dat){

loop_amount <- dat[bank_to_split_loc(dat)]

current_bank <- bank_to_split_loc(dat) + 1

dat[bank_to_split_loc(dat)] <- 0

for(i in seq_len(loop_amount)){

if(current_bank > length(dat)) { current_bank <- 1 } # wrap around the boundary

dat[current_bank] <- dat[current_bank] + 1

current_bank <- current_bank + 1

}

list(output = dat) # this is unnecessary, but when I misunderstood the problem I was also passing a counter out of this loop

}

expect_equal(balance_banks(c(0, 2, 7, 0))$output, c(2, 4, 1, 2))

# Takes vector of banks, keeps rebalancing them and checking the resulting vectors until a match is found

# I later added the part 1 or 2 argument to return

go_til_repeat <- function(input, part = 1){

# Initialize results data.frame

results <- data.frame(matrix(ncol = length(input), nrow = 0), stringsAsFactors = FALSE)

results <- rbind(results, input)

last_result <- balance_banks(input)

results <- rbind(results, last_result$output)

# Print every 1000 rebalances, to confirm making progress

# I thought the max bank value would decrease over time; it doesn't really, but still works as a progress indicator

print_counter <- 0

while(sum(duplicated(results)) == 0){

if(print_counter %% 1000 == 0 & print_counter > 0){ print(max(last_result$output)) }

print_counter <- print_counter + 1

last_result <- balance_banks(last_result$output)

results <- rbind(results, last_result$output)

}

if(part == 1){ # how many total cycles

nrow(results)-1

} else if (part == 2){ # how many cycles between duplicated rows

# courtesy of StackOverflow: https://stackoverflow.com/questions/12495345/find-indices-of-duplicated-rows

diff(range(which(duplicated(results) | duplicated(results, fromLast = TRUE))))

}

}

# These commands will take several minutes to run

day_05_input <- c(5, 1, 10, 0, 1, 7, 13, 14, 3, 12, 8, 10, 7, 12, 0, 6)

go_til_repeat(day_05_input, 1)

go_til_repeat(day_05_input, 2)