diff --git a/2106-max-fruits-harvested-in-k-steps.go b/2106-max-fruits-harvested-in-k-steps.go index 88eb34a..289bc38 100644 --- a/2106-max-fruits-harvested-in-k-steps.go +++ b/2106-max-fruits-harvested-in-k-steps.go @@ -1,5 +1,96 @@ package main +import "sync" + +func fromRightToLeft(fruityPrefix []int, startPos int, k int, leftLimit int, rightLimit int, pwg *sync.WaitGroup, presult *int) { + calcFruitySliceSum := func(begin int, end int) int { + begin-- + if begin < 0 { + return fruityPrefix[end] + } + + return fruityPrefix[end] - fruityPrefix[begin] + } + + windowSize := k / 2 + maxFruits := calcFruitySliceSum(startPos, rightLimit) + + delta := k - windowSize*2 + windowBegin := + startPos - delta // in case number of steps cannot be fully divided by 2, start position is shifted 1 position to the left + windowEnd := + windowBegin + windowSize + delta // for odd numbers of k we need to adjust wnd sz +1 + + if windowEnd > rightLimit { + windowBegin -= 2 * (windowEnd - rightLimit) + windowEnd = rightLimit + windowSize = windowEnd - windowBegin - delta + } + + endCycle := false + for !endCycle { + if windowBegin <= leftLimit { + windowBegin = leftLimit + endCycle = true + } + + localMaxFruits := calcFruitySliceSum(windowBegin, windowEnd) + if localMaxFruits > maxFruits { + maxFruits = localMaxFruits + } + + windowSize++ + windowEnd-- + windowBegin = windowEnd - windowSize - delta + } + + *presult = maxFruits + pwg.Done() +} + +func fromLeftToRight(fruityPrefix []int, startPos int, k int, leftLimit int, rightLimit int) int { + calcFruitySliceSum := func(begin int, end int) int { + begin-- + if begin < 0 { + return fruityPrefix[end] + } + + return fruityPrefix[end] - fruityPrefix[begin] + } + + maxFruits := calcFruitySliceSum(leftLimit, startPos) + + windowSize := k / 2 + delta := k - windowSize*2 + windowEnd := startPos + delta + windowBegin := windowEnd - windowSize - delta + + if windowBegin < leftLimit { + windowEnd += 2 * (leftLimit - windowBegin) + windowBegin = leftLimit + windowSize = windowEnd - delta - windowBegin + } + + endCycle := false + for !endCycle { + if windowEnd >= rightLimit { + windowEnd = rightLimit + endCycle = true + } + + localMaxFruits := calcFruitySliceSum(windowBegin, windowEnd) + if localMaxFruits > maxFruits { + maxFruits = localMaxFruits + } + + windowSize++ + windowBegin++ + windowEnd = windowBegin + windowSize + delta + } + + return maxFruits +} + func MaxTotalFruits(fruits [][]int, startPos int, k int) int { if len(fruits) == 0 || k < 0 { return 0 @@ -46,79 +137,19 @@ func MaxTotalFruits(fruits [][]int, startPos int, k int) int { } //fmt.Println("rightLimit = ", rightLimit) - windowSize := k / 2 + maxFruits := 0 - calcFruitySliceSum := func(begin int, end int) int { - begin-- - if begin < 0 { - return fruityPrefix[end] - } + wg := new(sync.WaitGroup) + wg.Add(1) - return fruityPrefix[end] - fruityPrefix[begin] + go fromRightToLeft(fruityPrefix, startPos, k, leftLimit, rightLimit, wg, &maxFruits) + alternativeMaxFruits := fromLeftToRight(fruityPrefix, startPos, k, leftLimit, rightLimit) + + wg.Wait() + + if maxFruits > alternativeMaxFruits { + return maxFruits } - maxFruits := calcFruitySliceSum(startPos, rightLimit) - - delta := k - windowSize*2 - windowBegin := - startPos - delta // in case number of steps cannot be fully divided by 2, start position is shifted 1 position to the left - windowEnd := - windowBegin + windowSize + (k - windowSize*2) // for odd numbers of k we need to adjust wnd sz +1 - - if windowEnd > rightLimit { - windowBegin -= 2 * (windowEnd - rightLimit) - windowEnd = rightLimit - windowSize = windowEnd - windowBegin - (k - windowSize*2) - } - - endCycle := false - for !endCycle { - if windowBegin <= leftLimit { - windowBegin = leftLimit - endCycle = true - } - - localMaxFruits := calcFruitySliceSum(windowBegin, windowEnd) - if localMaxFruits > maxFruits { - maxFruits = localMaxFruits - } - - windowSize++ - windowEnd-- - windowBegin = windowEnd - windowSize - delta - } - - alternativeMaxFruits := calcFruitySliceSum(leftLimit, startPos) - if alternativeMaxFruits > maxFruits { - maxFruits = alternativeMaxFruits - } - - windowSize = k / 2 - windowEnd = startPos + (k - windowSize*2) - windowBegin = windowEnd - windowSize - (k - windowSize*2) - - if windowBegin < leftLimit { - windowEnd += 2 * (leftLimit - windowBegin) - windowBegin = leftLimit - windowSize = windowEnd - (k - windowSize*2) - windowBegin - } - - endCycle = false - for !endCycle { - if windowEnd >= rightLimit { - windowEnd = rightLimit - endCycle = true - } - - localMaxFruits := calcFruitySliceSum(windowBegin, windowEnd) - if localMaxFruits > maxFruits { - maxFruits = localMaxFruits - } - - windowSize++ - windowBegin++ - windowEnd = windowBegin + windowSize + delta - } - - return maxFruits + return alternativeMaxFruits }