Mercurial > lbo > hg > juliaplay
changeset 27:668adaf0313f
three-sum
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Sat, 04 Mar 2023 12:08:16 +0100 |
parents | 015fe10a59cd |
children | 743af1962848 |
files | julia/arrays.jl |
diffstat | 1 files changed, 80 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/julia/arrays.jl Sat Mar 04 11:31:42 2023 +0100 +++ b/julia/arrays.jl Sat Mar 04 12:08:16 2023 +0100 @@ -76,6 +76,86 @@ nothing end +# About 11x faster than without memoization for input set of n = 11 +# MUCH MUCH faster for larger input sets +function threesum_memoize(a::AbstractVector{<:Integer}, s, i=1, running::Tuple=(), triplets=Set{Tuple}(), badstarts=Set{Tuple}()) + markbad(t) = if length(t) < 3 push!(badstarts, t) end + isbad(t) = t in badstarts + + if i > length(a) && length(running) < 3 + return 0 + end + if length(running) == 3 + if sum(running) == s + push!(triplets, running) + return 1 + end + return 0 + elseif length(running) == 2 + current = a[i] + # incl/excl/new + possibilities = [running, (running..., current), (running[1], current), (running[2], current), ()] + for p = possibilities + if !isbad(p) && 0 == threesum_memoize(a, s, i+1, p, triplets, badstarts) + markbad(p) + end + end + elseif length(running) == 1 + current = a[i] + possibilities = [(running[1], current), running, ()] + # incl/excl current element + for p = possibilities + if !isbad(p) && 0 == threesum_memoize(a, s, i+1, p, triplets, badstarts) + markbad(p) + end + end + elseif length(running) == 0 + current = a[i] + if !isbad((current,)) && 0 == threesum_memoize(a, s, i+1, (current,), triplets, badstarts) + markbad((current,)) + end + if !isbad(running) && 0 == threesum_memoize(a, s, i+1, running, triplets, badstarts) + markbad(running) + end + end + if i == 1 + @show badstarts + return triplets + end +end + +function threesum(a::AbstractVector{<:Integer}, s, i=1, running::Tuple=(), triplets=Set{Tuple}()) + if i > length(a) && length(running) < 3 + return + end + if length(running) == 3 + if sum(running) == s + push!(triplets, running) + end + elseif length(running) == 2 + current = a[i] + # incl/excl/new + threesum(a, s, i+1, running, triplets) + threesum(a, s, i+1, (running..., current), triplets) + threesum(a, s, i+1, (running[1], current), triplets) + threesum(a, s, i+1, (running[2], current), triplets) + threesum(a, s, i+1, (), triplets) + elseif length(running) == 1 + current = a[i] + # incl/excl current element + threesum(a, s, i+1, (running[1], current), triplets) + threesum(a, s, i+1, running, triplets) + threesum(a, s, i+1, (), triplets) + elseif length(running) == 0 + current = a[i] + threesum(a, s, i+1, (current,), triplets) + threesum(a, s, i+1, running, triplets) + end + if i == 1 + return triplets + end +end + function watercontainer(a::Vector{Int}) maxvol = 0 best = (0,0)