Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Maximum Nesting Depth + Julia #9

Open
mcabbott opened this issue Nov 17, 2022 · 4 comments
Open

Maximum Nesting Depth + Julia #9

mcabbott opened this issue Nov 17, 2022 · 4 comments

Comments

@mcabbott
Copy link

I came across this page https://github.com/codereport/array-language-comparisons/blob/main/comparisons/leetcode/P1614_Max_Paren_Depth.md

For Julia, I'm not too sure what "no row-wise minus reduction" means, but it sounds like you are looking for maximum(cumsum(..., something like this:

julia> str = "(1)+((2))+(((3)))";

julia> maximum(cumsum([(c=='(')-(c==')') for c in str]))
3

julia> maximum(Iterators.accumulate(+, (c=='(')-(c==')') for c in str))  # lazy version
3

julia> foldl(str; init=(0,0)) do (i,maxi), c
         c=='(' && return i+1, max(i+1,maxi)
         c==')' && return i-1, maxi
         i, maxi
       end[2]
3
@codereport
Copy link
Owner

@mcabbott
Similar to the other solutions, I am trying to do an outer_product in Julia via broadcasting, something like:

matrix = reshape(collect("()"), (1, :)) .== collect("(1+(2*3)+((8)/4))+1")
19×2 BitMatrix:
 1  0
 0  0
 0  0
 1  0
 0  0
 0  0
 0  0
 0  1
 0  0
 1  0
 1  0
 0  0
 0  1
 0  0
 0  0
 0  1
 0  1
 0  0
 0  0

and then a row-wise minus reduce or minus leftFold. However, that doesn't work in Julia:

julia> reduce(-, matrix, dims=1)
ERROR: MethodError: no method matching reducedim_init(::typeof(identity), ::typeof(-), ::BitMatrix, ::Int64)
Closest candidates are:
  reducedim_init(::Any, ::typeof(min), ::AbstractArray, ::Any) at reducedim.jl:128
  reducedim_init(::Any, ::typeof(max), ::AbstractArray, ::Any) at reducedim.jl:128
  reducedim_init(::Any, ::typeof(&), ::Union{Base.AbstractBroadcasted, AbstractArray}, ::Any) at reducedim.jl:206
  ...
Stacktrace:
 [1] _mapreduce_dim(f::Function, op::Function, #unused#::Base._InitialValue, A::BitMatrix, dims::Int64)
   @ Base ./reducedim.jl:371
 [2] #mapreduce#765
   @ ./reducedim.jl:357 [inlined]
 [3] #reduce#767
   @ ./reducedim.jl:406 [inlined]
 [4] top-level scope
   @ REPL[72]:1

@mcabbott
Copy link
Author

I believe the error is trying to say that it doesn't know the neutral element for reducing over -, which it would infer for +. You could provide this but (1) the reduction order isn't guaranteed and (2) I think this is the wrong thing:

julia> reduce(-, matrix, dims=1, init=0)
1×2 Matrix{Int64}:
 -4  -4

This is closer:

julia> reduce(-, matrix, dims=2, init=0)
19×1 Matrix{Int64}:
 -1
  0
  0
 -1
  0
  0
  0
 -1
  0
 -1
 -1
  0
 -1
  0
  0
 -1
 -1
  0
  0

but that always uses init, whereas you want to subtract the second column from the first. It's a little strange now that I think about it that the dims method forbids this.

julia> reduce(-, [1, 0])
1

julia> reduce(-, [1, 0], init=0)
-1

The first is probably ill-defined due to relying on the order. It should be foldl but that doesn't take dims. You can do mapslices(row -> foldl(-, row), matrix, dims=2), or else foldl.(-, eachrow(matrix)).

You could also literally subtract the whole columns, -(eachcol(matrix)...) |> cumsum |> maximum.

@codereport
Copy link
Owner

Yea, I found foldl when trying to solve this problem which is what I wanted but that doesn't take a dims argument. Is there some reason for that?

@mcabbott
Copy link
Author

I think foldl sort-of belongs to the iteration protocol? While accumulate was only for arrays until fairly recently. It is a bit weird, now that you point it out.

Easy to define versions (of sub-optimal efficiency):

fold1(f, x::AbstractArray; dims, kw...) = mapslices(y -> foldl(f, y; kw...), x; dims);
fold2(f, x::AbstractArray; dims, kw...) = accumulate(f, x; dims, kw...)[_last(x, dims)...];

_last(x, dims) = ntuple(d -> d in dims ? (lastindex(x,d):lastindex(x,d)) : (:), ndims(x))

fold1(-, ones(Int, 2,2), dims=1)
fold2(-, ones(Int, 2,2), dims=1)  # both [0 0]

fold1(-, ones(Int, 2,2), dims=1, init=0)  # instead [-2 -2]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants