156 lines
3.4 KiB
Go
156 lines
3.4 KiB
Go
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
|
|
}
|
|
|
|
//fmt.Println("startPos = ", startPos)
|
|
//fmt.Println("steps(k) = ", k)
|
|
|
|
totalLength := fruits[len(fruits)-1][0] + 1
|
|
//fmt.Println("totalLength = ", totalLength)
|
|
|
|
if startPos >= totalLength {
|
|
totalLength = startPos + 1
|
|
}
|
|
|
|
fruitySlice := make([]int, totalLength)
|
|
fruityPrefix := make([]int, totalLength)
|
|
|
|
for _, fruit := range fruits {
|
|
fruitySlice[fruit[0]] = fruit[1]
|
|
}
|
|
//fmt.Println("fruitySlice = ", fruitySlice)
|
|
|
|
if k == 0 {
|
|
return fruitySlice[startPos]
|
|
}
|
|
|
|
prefixSum := 0
|
|
for i, fruit := range fruitySlice {
|
|
prefixSum += fruit
|
|
fruityPrefix[i] = prefixSum
|
|
}
|
|
//fmt.Println("fruityPrefix = ", fruityPrefix)
|
|
|
|
leftLimit := startPos - k
|
|
if leftLimit < 0 {
|
|
leftLimit = 0
|
|
}
|
|
//fmt.Println("leftLimit = ", leftLimit)
|
|
|
|
rightLimit := startPos + k
|
|
if rightLimit >= totalLength {
|
|
rightLimit = totalLength - 1
|
|
}
|
|
//fmt.Println("rightLimit = ", rightLimit)
|
|
|
|
maxFruits := 0
|
|
|
|
wg := new(sync.WaitGroup)
|
|
wg.Add(1)
|
|
|
|
go fromRightToLeft(fruityPrefix, startPos, k, leftLimit, rightLimit, wg, &maxFruits)
|
|
alternativeMaxFruits := fromLeftToRight(fruityPrefix, startPos, k, leftLimit, rightLimit)
|
|
|
|
wg.Wait()
|
|
|
|
if maxFruits > alternativeMaxFruits {
|
|
return maxFruits
|
|
}
|
|
|
|
return alternativeMaxFruits
|
|
}
|