Mercurial > lbo > hg > juliaplay
changeset 3:c1db337c15be
Reorganize files
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Tue, 14 Feb 2023 21:12:06 +0100 |
parents | b7160d5e22cc |
children | 00f57653128a |
files | arrays.jl cb.jl circus.jl coins.jl heap.jl julia/arrays.jl julia/cb.jl julia/circus.jl julia/coins.jl julia/heap.jl julia/longest_common_subsequence.jl julia/longest_increasing_subsequence.jl julia/magicsquare.jl julia/matrixsearch.jl julia/mergesort.jl julia/quicksort.jl julia/recursion.jl julia/strings.jl longest_common_subsequence.jl longest_increasing_subsequence.jl magicsquare.jl matrixsearch.jl mergesort.jl python/sorting.py quicksort.jl recursion.jl strings.jl |
diffstat | 27 files changed, 773 insertions(+), 671 deletions(-) [+] |
line wrap: on
line diff
--- a/arrays.jl Sun Feb 12 21:06:13 2023 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,189 +0,0 @@ -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
--- a/cb.jl Sun Feb 12 21:06:13 2023 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -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 -
--- a/circus.jl Sun Feb 12 21:06:13 2023 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -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
--- a/coins.jl Sun Feb 12 21:06:13 2023 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ - -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 -
--- a/heap.jl Sun Feb 12 21:06:13 2023 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ - -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/julia/arrays.jl Tue Feb 14 21:12:06 2023 +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/julia/cb.jl Tue Feb 14 21:12:06 2023 +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/julia/circus.jl Tue Feb 14 21:12:06 2023 +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/julia/coins.jl Tue Feb 14 21:12:06 2023 +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/julia/heap.jl Tue Feb 14 21:12:06 2023 +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/julia/longest_common_subsequence.jl Tue Feb 14 21:12:06 2023 +0100 @@ -0,0 +1,38 @@ +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/julia/longest_increasing_subsequence.jl Tue Feb 14 21:12:06 2023 +0100 @@ -0,0 +1,34 @@ +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/julia/magicsquare.jl Tue Feb 14 21:12:06 2023 +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/julia/matrixsearch.jl Tue Feb 14 21:12:06 2023 +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/julia/mergesort.jl Tue Feb 14 21:12:06 2023 +0100 @@ -0,0 +1,46 @@ + +function merge!(a::AbstractArray, mid::Int, aux::Union{AbstractArray, Nothing}=nothing) + if length(a) <= 1 + return + end + # Left half: begin:mid + # Right half: mid+1:end + left, right, i = 1, mid+1, 1 + ac = isnothing(aux) ? copy(a) : aux + while i <= length(a) + if left > mid + ac[i] = a[right] + right += 1 + elseif right > length(a) + ac[i] = a[left] + left += 1 + else + if a[left] < a[right] + ac[i] = a[left] + left += 1 + else + ac[i] = a[right] + right += 1 + end + end + i += 1 + end + for i = eachindex(a) + a[i] = ac[i] + end +end + +function mergesort!(a::AbstractArray) + aux = copy(a) + if length(a) <= 1 + return + elseif length(a) == 2 + a[1], a[2] = (a[1] < a[2] ? (a[1],a[2]) : (a[2],a[1])) + return + else + mid = div(1+length(a), 2) + mergesort!(@view a[begin:mid]) + mergesort!(@view a[mid+1:end]) + merge!(a, mid, aux) + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/julia/quicksort.jl Tue Feb 14 21:12:06 2023 +0100 @@ -0,0 +1,49 @@ +function partition(v::Vector{T}, from::Int, to::Int)::Int where {T} + piv = v[to] + i = from-1 + for j = from:to-1 + if v[j] <= piv + i += 1 + v[i], v[j] = v[j], v[i] + end + end + i += 1 + v[i], v[to] = v[to], v[i] + i +end + +function hoare!(v::AbstractArray, from::Int, to::Int)::Int + if from >= to + return from + end + lo, hi = from-1, to+1 + piv = v[div(from+to,2)] + while true + 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 +end + +function quicksort!(v::Vector{T}, from=1, to=-1) where {T} + if to < 0 + to = length(v) + end + if to <= from + return + else + mid = hoare!(v, from, to) + quicksort!(v, from, mid) + quicksort!(v, mid+1, to) + end +end +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/julia/recursion.jl Tue Feb 14 21:12:06 2023 +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/julia/strings.jl Tue Feb 14 21:12:06 2023 +0100 @@ -0,0 +1,41 @@ + +# "(())()" -> 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 + +
--- a/longest_common_subsequence.jl Sun Feb 12 21:06:13 2023 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -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
--- a/longest_increasing_subsequence.jl Sun Feb 12 21:06:13 2023 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -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
--- a/magicsquare.jl Sun Feb 12 21:06:13 2023 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ - -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 -
--- a/matrixsearch.jl Sun Feb 12 21:06:13 2023 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ - -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
--- a/mergesort.jl Sun Feb 12 21:06:13 2023 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ - -function merge!(a::AbstractArray, mid::Int, aux::Union{AbstractArray, Nothing}=nothing) - if length(a) <= 1 - return - end - # Left half: begin:mid - # Right half: mid+1:end - left, right, i = 1, mid+1, 1 - ac = isnothing(aux) ? copy(a) : aux - while i <= length(a) - if left > mid - ac[i] = a[right] - right += 1 - elseif right > length(a) - ac[i] = a[left] - left += 1 - else - if a[left] < a[right] - ac[i] = a[left] - left += 1 - else - ac[i] = a[right] - right += 1 - end - end - i += 1 - end - for i = eachindex(a) - a[i] = ac[i] - end -end - -function mergesort!(a::AbstractArray) - aux = copy(a) - if length(a) <= 1 - return - elseif length(a) == 2 - a[1], a[2] = (a[1] < a[2] ? (a[1],a[2]) : (a[2],a[1])) - return - else - mid = div(1+length(a), 2) - mergesort!(@view a[begin:mid]) - mergesort!(@view a[mid+1:end]) - merge!(a, mid, aux) - end -end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/python/sorting.py Tue Feb 14 21:12:06 2023 +0100 @@ -0,0 +1,102 @@ +import copy + +def partition(a, fro, to): + if fro >= to: + return fro + # Hoare partitioning scheme + mid = (fro+to) // 2 + piv = a[mid] + lo, hi = fro-1, to+1 + while True: + lo += 1 + while a[lo] < piv: + lo += 1 + hi -= 1 + while a[hi] > piv: + hi -= 1 + if lo >= hi: + return hi + a[lo], a[hi] = a[hi], a[lo] + +def quicksort(a, fro=0, to=-1): + if to < 0: + to = len(a) - 1 + if to-fro <= 0: + return + mid = partition(a, fro, to) + quicksort(a, fro, mid) + quicksort(a, mid+1, to) + +def mergehalves(a, lo, mid, hi, aux): + i, l, r = 0, lo, mid + while i <= hi-lo: + if l >= mid: + aux[i] = a[r] + r += 1 + elif r > hi: + aux[i] = a[l] + l += 1 + else: + if a[l] < a[r]: + aux[i] = a[l] + l += 1 + else: + aux[i] = a[r] + r += 1 + i += 1 + print(a[lo:hi+1], aux[0:i]) + a[lo:hi+1] = aux[0:i] + +def mergesort(a, lo=0, hi=-1, aux=None): + aux = aux or copy.copy(a) + hi = hi if hi > 0 else len(a)-1 + if hi == lo: + return + elif hi-lo == 1: + if a[lo] > a[hi]: + a[lo], a[hi] = a[hi], a[lo] + return + else: + mid = (lo+hi)//2 + mergesort(a, lo, mid, aux) + mergesort(a, mid, hi, aux) + mergehalves(a, lo, mid, hi, aux) + +def children(i): + return (2*i, 2*i+1) + +def swap(a, i, j): + a[i], a[j] = a[j], a[i] + + +def sink(a, i, N=-1): + N = N if N >= 0 else len(a) + while 2*i < N: + c1, c2 = children(i) + if c2 >= N: + if a[i] < a[c1]: + swap(a, i, c1) + i = c1 + else: + sm, la = (c1, c2) if a[c1] < a[c2] else (c2, c1) + if a[i] < a[la]: + swap(a, i, la) + i = la + +def buildheap(a): + i = len(a) // 2 + while i > 0: + sink(a, i) + i -= 1 + +def heapsort(a): + a = [0] + a + buildheap(a) + i = len(a)-1 + while i > 0: + swap(a, 1, i) + i -= 1 + sink(a, 1, i) + + return a +
--- a/quicksort.jl Sun Feb 12 21:06:13 2023 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -function partition(v::Vector{T}, from::Int, to::Int)::Int where {T} - piv = v[to] - i = from-1 - for j = from:to-1 - if v[j] <= piv - i += 1 - v[i], v[j] = v[j], v[i] - end - end - i += 1 - v[i], v[to] = v[to], v[i] - i -end - -function hoare!(v::AbstractArray, from::Int, to::Int)::Int - if from >= to - return from - end - lo, hi = from-1, to+1 - piv = v[div(from+to,2)] - while true - 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 -end - -function quicksort!(v::Vector{T}, from=1, to=-1) where {T} - if to < 0 - to = length(v) - end - if to <= from - return - else - mid = hoare!(v, from, to) - quicksort!(v, from, mid) - quicksort!(v, mid+1, to) - end -end -
--- a/recursion.jl Sun Feb 12 21:06:13 2023 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ - -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 -
--- a/strings.jl Sun Feb 12 21:06:13 2023 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ - -# "(())()" -> 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 - -