This code below is running very very slow must be due to the ridiculous number of memory allocations.
input = "1113222113"
function lookandsay(s::AbstractString)::AbstractString
result = ""
i = 1
while i <= length(s)
c = 1
while i < length(s) && s[i+1] == s[i]
c += 1
i += 1
end
result *= string(c)*s[i]
i += 1
end
return result
end
function solve(s::AbstractString)
for i in 1:50
s = lookandsay(s)
end
println(length(s))
end
solve(input)
Can someone help me to identify and rectify the problem here?
function lookandsay(s)
result = similar(s, 0)
sizehint!(result, 2*length(s))
i = 1
while i <= length(s)
c = 1
while i < length(s) && s[i+1] == s[i]
c += 1
i += 1
end
if c < 10
push!(result, c)
else
append!(result, reverse(digits(c)))
end
push!(result, s[i])
i += 1
end
return result
end
function sol(s, n)
for i in 1:n
s = lookandsay(s)
end
length(s)
end
julia> using BenchmarkTools
julia> @btime sol(parse.(Int, collect(input)), 50)
278.920 ms (106 allocations: 179.90 MiB)
3579328
sizehint! suggests that result should reserve enough memory for 2*length(s) entries (you can think of it as a preallocation). I picked this number as a heuristic, and I noted it gives a minor improvement.
Not sure off the top of my head, but my guess is that it’s because similar(s) allocates a vector of size length(s), and then starts pushing/appending to it. Next iteration that will be the input, so the length of this vector doubles every iteration. As the iteration count gets large, maybe it’s failing to allocate the vector, or to push/append to it, and this is causing the crash.