Mercurial > lbo > hg > juliaplay
changeset 0:d0c890aae379
Initial commit
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Sat, 26 Nov 2022 09:23:14 +0100 |
parents | |
children | ed34696a9d9b |
files | arrays.jl cb.jl circus.jl coins.jl heap.jl magicsquare.jl matrixsearch.jl quicksort.jl recursion.jl strings.jl |
diffstat | 10 files changed, 545 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arrays.jl Sat Nov 26 09:23:14 2022 +0100 @@ -0,0 +1,189 @@ +function _longest_increasing_subsequence(v::Vector{Int})::Vector{Int} + M = zeros(Int, length(v)) + P = zeros(Int, length(v)) + Longest = 0 + for i = eachindex(v) + e = v[i] + # Find element in sequence so far that is smaller than current element e. + lo, hi = 1, Longest+1 + while lo < hi + mid = round(Int, floor((lo+hi)/2)) + if e < v[M[mid]] + hi = mid + else + lo = mid+1 + end + end + @assert lo == hi + P[i] = lo > 1 ? M[lo-1] : -1 + M[lo] = i + + if lo > Longest + Longest = lo + end + end + + @show P, M + # Reconstruct sequence + ixs = zeros(Int, 0) + i = M[Longest] + while i > 0 + push!(ixs, v[i]) + i = P[i] + end + reverse!(ixs) + ixs +end + +function twosum1(a::Vector{Int}, n::Int)::Tuple{Int,Int} + # n² complexity (trivial): + for (i,e1) in enumerate(a) + for (j,e2) in enumerate(a) + if e1+e2 == n + return (i,j) + end + end + end + return (0,0) +end + +function twosum2(a::Vector{Int}, n::Int)::Tuple{Int,Int} + # More clever? + # + # 1. sort array; cut off all elements > n. Start from largest leftover number + # and smallest one; look for a match: + a_ = sort(a) + maxix = 1 + for (i, e) = enumerate(a_) + if e < n + maxix = i + else + break + end + end + + a_ = a_[begin:maxix] + front, back = 1, length(a_) + while front < back + while a_[front]+a_[back] < n + front += 1 + end + if a_[front]+a_[back] == n + return (front, back) + end + back -= 1 + end + nothing +end + +function watercontainer(a::Vector{Int}) + maxvol = 0 + best = (0,0) + for lo = 1:length(a) + for hi = length(a):-1:lo + vol = (hi-lo) * min(a[lo], a[hi]) + if vol > maxvol + best = (lo, hi) + maxvol = vol + end + end + end + best, maxvol +end + +function rainwater(a::Vector{Int}) + lm, rm = 0, 0 + leftmax, rightmax = zeros(Int, length(a)), zeros(Int, length(a)) + for (i,e) in enumerate(a) + if e > lm + lm = e + end + leftmax[i] = lm + end + for (i,e) in enumerate(reverse(a)) + if e > rm + rm = e + end + rightmax[length(rightmax)-(i-1)] = rm + end + + water = 0 + for (i, e) in enumerate(a) + water += min(leftmax[i], rightmax[i]) - e + end + wat +end + +function longest_increasing_subsequence(v::Vector{Int})::Vector{Int} + M = zeros(Int, length(v)) # M[L] stores last index of sequence with length L. + P = zeros(Int, length(v)) # P[i] stores predecessor of element i in longest sequence. + Longest = 0 + for i = eachindex(v) + # Binary search for position in longest-sequence-so-far + lo, hi = 1, Longest+1 + while lo < hi + mid = round(Int, floor((lo+hi)/2)) + if v[i] < v[M[mid]] + hi = mid + else + lo = mid+1 + end + end + @assert lo == hi + # Update predecessor of current index. + P[i] = lo > 1 ? M[lo-1] : -1 + M[lo] = i + + if lo >= Longest + Longest = lo + end + end + + # Reconstruct sequence. + seq = zeros(Int, Longest) + i = M[Longest] + for j = Longest:-1:1 + seq[j] = v[i] + i = P[i] + end + seq +end + +function longest_common_subsequence(x::Vector{T}, y::Vector{T})::Vector{T} where {T} + m, n = length(x), length(y) + C = zeros(Int, m+1, n+1) + # Not necessary: + for i = 1:m + C[i,1] = 0 + end + for j = 1:n + C[1,j] = 0 + end + for i = 1:m + for j = 1:n + if x[i] == y[j] + C[i+1,j+1] = C[i, j] + 1 + else + C[i+1,j+1] = max(C[i, j+1], C[i+1, j]) + end + end + end + + # Reconstruct sequence + i, j = m, n + k = C[m+1, n+1] + seq = Vector{T}(undef, k) + while k > 0 + if C[i,j] + 1 == C[i+1,j+1] + seq[k] = x[i] + k -= 1 + i -= 1 + j -= 1 + elseif C[i,j+1] == C[i+1,j+1] + i -= 1 + elseif C[i+1,j] == C[i+1,j+1] + j -= 1 + end + end + seq +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cb.jl Sat Nov 26 09:23:14 2022 +0100 @@ -0,0 +1,42 @@ +mutable struct CircularBuffer{T} + b::Vector{T} + first::Int + last::Int + count::Int + + function CircularBuffer{T}(capacity::Integer) where {T} + new(Vector{T}(undef, capacity), 1, 0, 0) + end +end + +function Base.push!(cb::CircularBuffer, item; overwrite::Bool=false) + if !overwrite || (overwrite && cb.count < length(cb.b)) + if cb.count >= length(cb.b) + error("buffer is full") + end + cb.last = cb.last%length(cb.b) + 1 + cb.b[cb.last] = item + cb.count += 1 + else + cb.b[cb.first] = item + cb.first = cb.first%length(cb.b) + 1 + end +end + +function Base.popfirst!(cb::CircularBuffer) + if cb.count <= 0 + error("buffer is empty") + end + e = cb.b[cb.first] + #cb.b[cb.first] = undef + cb.first = cb.first%length(cb.b) + 1 + cb.count -= 1 + e +end + +function Base.empty!(cb::CircularBuffer) + cb.count = 0 + cb.first = 1 + cb.last = 0 +end +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/circus.jl Sat Nov 26 09:23:14 2022 +0100 @@ -0,0 +1,23 @@ +function config1()::Vector{Tuple{Int,Int}} + [(65,100), + (70,180), + (56,94), + (75,190), + (60,95), + (68,110)] +end + +function largest_tower(c::Vector{Tuple{Int,Int}})::Tuple{Int, Vector{Tuple{Int,Int}}} + sort!(c; lt=((h1,w1), (h2,w2)) -> !(h1 < h2 || (h1 == h2 && w1 < w2))) + n = 1 + for i in 2:length(c) + h2, w2 = c[i] + h1, w1 = c[i-1] + if h1 > h2 && w1 > w2 + n += 1 + else + break + end + end + n, c +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coins.jl Sat Nov 26 09:23:14 2022 +0100 @@ -0,0 +1,18 @@ + +function best_selection(a::Vector{UInt})::Tuple{Int, Int, Int, Vector{UInt}} + N = length(a) + N_2 = div(N, 2) + left, right = 1, N_2 + current_sum = sum(a[left:right]) + min = current_sum + for i in 1:N_2 + current_sum -= a[i] + current_sum += a[i+N_2] + if current_sum <= min + min = current_sum + left, right = i+1, i+N_2 + end + end + (min, left, right, a[left:right]) +end +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/heap.jl Sat Nov 26 09:23:14 2022 +0100 @@ -0,0 +1,51 @@ + +function heap_parent(ix::Int)::Int + max(1, round(Int, floor(ix/2))) +end + +function heap_children(ix::Int)::Tuple{Int,Int} + (2ix, 2ix+1) +end + +function heap_bubble!(h::Vector{Int}, ix::Int) + if ix == 1 + return + end + hp = heap_parent(ix) + if h[hp] > h[ix] + h[hp], h[ix] = h[ix], h[hp] + end + heap_bubble!(h, hp) +end + +# Min-heap +function heap_insert!(h::Vector{Int}, n::Int) + push!(h, n) + ix = length(h) + heap_bubble!(h, ix) +end + +function heap_pull!(h::Vector{Int}, ix::Int) + l, r = heap_children(ix) + if l <= length(h) && r <= length(h) + if h[l] < h[r] + h[ix], h[l] = h[l], h[ix] + heap_pull!(h, l) + else + h[ix], h[r] = h[r], h[ix] + heap_pull!(h, r) + end + elseif l <= length(h) + @assert l == length(h) + h[ix], h[l] = h[l], h[ix] + popat!(h, length(h)) + else + h[ix] = 10000 + end +end + +function heap_pop!(h::Vector{Int})::Int + e = h[1] + heap_pull!(h, 1) + e +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/magicsquare.jl Sat Nov 26 09:23:14 2022 +0100 @@ -0,0 +1,78 @@ + +function testsquare1()::Matrix{Int} + [1 0 4 0; + 0 2 0 3; + 0 0 3 0; + 0 0 0 4] +end +function testsquare2()::Matrix{Int} + [4 0 0 2; + 0 3 0 0; + 0 0 2 0; + 3 0 0 1] +end + +function neighbors_4x4(m::Matrix{Int}, i::Int, j::Int)::Vector{Int} + q, r = div(i-1, 2), div(j-1, 2) + s = union(Set(m[i,:]), Set(m[:,j]), Set([m[2q+1, 2r+1], m[2q+1, 2r+2], m[2q+2, 2r+1], m[2q+2, 2r+2]])) + pop!(s, 0) + collect(s) +end + +function candidates_4x4(m::Matrix{Int}, i::Int, j::Int)::Vector{Int} + n = neighbors_4x4(m, i, j) + c = setdiff(1:4, n) + collect(c) +end + +function solve_4x4(m::Matrix{Int})::Union{Some{Matrix{Int}}, Nothing} + @assert all(m .<= 4) && all(m .>= 0) + + m = copy(m) + n = 1 + d = Matrix{Union{Some{Vector{Int}}, Nothing}}(nothing, 4, 4) + # 1) Find candidates for all positions. + while n > 0 + n = 0 + for i = 1:4 + for j = 1:4 + if m[i,j] == 0 + d[i,j] = Some(candidates_4x4(m, i, j)) + end + end + end + # 2) Fix those cells where only one candidate matches + for i = 1:4 + for j = 1:4 + if m[i,j] == 0 && length(something(d[i,j])) == 1 + n += 1 + m[i,j] = something(d[i,j])[1] + d[i,j] = nothing + elseif m[i,j] == 0 && length(something(d[i,j])) == 0 + display(m) + error("Unsolveable magic square! at $((i,j))") + end + end + end + end + + if all(m .> 0) + return Some(m) + end + # 3) Backtracking step: Select candidate, try to solve. + for i = 1:4 + for j = 1:4 + if !isnothing(d[i,j]) + for cand in something(d[i,j]) + m[i,j] = cand + m_ = solve_4x4(m) + if !isnothing(m_) + return m_ + end + end + return nothing + end + end + end +end +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/matrixsearch.jl Sat Nov 26 09:23:14 2022 +0100 @@ -0,0 +1,53 @@ + +function generate_sorted_matrix(m, n)::Matrix{Int} + v = abs.(rand(Int, m*n)) .% 1000 + sort!(v) + reshape(v, m, n) +end + +const Option{T} = Union{Some{T}, Nothing} + +function find_in_sorted_array(V::AbstractVector{Int}, n::Int)::Option{Int} + lo, mid, hi = 1, round(Int, length(V)/2), length(V) + while lo < hi + if n < V[mid] + hi = mid-1 + mid = round(Int, (lo+hi)/2) + continue + elseif n > V[mid] + lo = mid+1 + mid = round(Int, (lo+hi)/2) + continue + elseif n == V[mid] + return Some(mid) + end + @assert false "if exhausted" + end + V[mid] == n ? Some(mid) : nothing +end + +function find_in_sorted_matrix(M::Matrix, n::Int)::Option{Tuple{Int, Int}} + r, c = size(M) + # 1. Find column + lo, mid, hi = 1, round(Int, c/2), c + while lo < hi + if n < M[begin, mid] + hi = mid-1 + mid = round(Int, (lo+hi)/2) + continue + elseif n > M[end, mid] + lo = mid+1 + mid = round(Int, (lo+hi)/2) + continue + else + break + end + end + # 2. Find element + in_array = find_in_sorted_array((@view M[:,mid]), n) + if isnothing(in_array) + nothing + else + Some((mid, something(in_array))) + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/quicksort.jl Sat Nov 26 09:23:14 2022 +0100 @@ -0,0 +1,43 @@ + +function partition(v::Vector{T}, from::Int, to::Int)::Int where {T} + if to-from < 1 + return from + end + lo, hi = from-1, to+1 + mid = round(Int, (lo+hi)/2) + piv = v[mid] + while lo < hi + lo += 1 + while v[lo] < piv + lo += 1 + end + hi -= 1 + while v[hi] > piv + hi -= 1 + end + if lo >= hi + return hi + end + v[lo], v[hi] = v[hi], v[lo] + end + lo +end + +function quicksort!(v::Vector{T}, from=1, to=-1) where {T} + if to < 0 + to = length(v) + end + if to-from == 1 + return + else + mid = partition(v, from, to) + @show (from, to, mid) + if from < mid + quicksort!(v, from, mid) + end + if mid+1 < to + quicksort!(v, mid+1, to) + end + end +end +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/recursion.jl Sat Nov 26 09:23:14 2022 +0100 @@ -0,0 +1,9 @@ + +function combinations(n::Int, k::Int)::Vector + if k == 1 + return collect(1:n) + end + lower = combinations(n, k-1) + [(i, l...) for i in 1:n for l in lower] +end +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/strings.jl Sat Nov 26 09:23:14 2022 +0100 @@ -0,0 +1,39 @@ + +# "(())()" -> good; +# "(()" -> bad +function goodparens(s::String)::Bool + nesting = 0 + for c in s + if c == '(' + nesting += 1 + elseif c == ')' + nesting -= 1 + end + if nesting < 0 + return false + end + end + if nesting != 0 + false + else + true + end +end + +# "[()]{}" -> good; "[(])" -> bad +function goodmultiparens(s::String)::Bool + stack::Vector{Char} = [] + for c in s + if c in ['(', '[', '{'] + push!(stack, c) + elseif c in [')', ']', '}'] + o = pop!(stack); + if (c == ')' && o == '(') || (c==']' && o == '[') || (c=='}' && o == '{') + continue + else + return false + end + end + end + length(stack) == 0 +end