Mercurial > lbo > hg > juliaplay
changeset 8:809f7d058647
Some more dp problems
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Sun, 19 Feb 2023 15:17:09 +0100 |
parents | 1ecfe01af17e |
children | 33a23228ef5c |
files | julia/longest_common_subsequence.jl python/dp.py |
diffstat | 2 files changed, 128 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/julia/longest_common_subsequence.jl Sun Feb 19 12:50:51 2023 +0100 +++ b/julia/longest_common_subsequence.jl Sun Feb 19 15:17:09 2023 +0100 @@ -1,3 +1,49 @@ +function lcss_len(x::Vector{T}, y::Vector{T}, i=1, j=1, a=nothing) where {T} + a = isnothing(a) ? zeros(T, min(length(x), length(y))) : a + if i > length(x) || j > length(y) + 0 + elseif x[i] == y[j] + n = 1 + lcss_len(x, y, i+1, j+1, a) + a[n] = x[i] + n + else + max(lcss_len(x, y, i+1, j, a), lcss_len(x, y, i, j+1, a)) + end +end + +function lcss_diff(x::Vector{T}, y::Vector{T}) where {T} + lcss = longest_common_subsequence(x, y) + i, j, k = 1, 1, 1 + while i <= length(lcss) && j <= length(x) && k <= length(y) + if x[j] == lcss[i] && y[k] == lcss[i] + i += 1 + j += 1 + k += 1 + elseif x[j] == lcss[i] && y[k] != lcss[i] + println("Added: $i $(y[k])") + k += 1 + elseif y[k] == lcss[i] && x[j] != lcss[i] + println("Removed: $i $(x[j])") + j += 1 + else + println("Changed: $(x[j]) -> $(y[k])") + j += 1 + k += 1 + end + end +end + +function lrss_len(x::Vector{T}, i=1, j=1) where {T} + if max(i, j) > length(x) + 0 + elseif x[i] == x[j] && i != j + 1 + lrss_len(x, i+1, j+1) + else + max(lrss_len(x, i+1, j), lrss_len(x, i, j+1)) + end +end + +# This has a bug: e.g. [1,2,3,4,5,6] vs [1,2,4,5,6]. Sequences need to have same length 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)
--- a/python/dp.py Sun Feb 19 12:50:51 2023 +0100 +++ b/python/dp.py Sun Feb 19 15:17:09 2023 +0100 @@ -1,4 +1,4 @@ - +import numpy as np from functools import cache @@ -42,3 +42,84 @@ right = n - 2 - left N += 1 + circle_chords(left) * circle_chords(right) return N + +def subset_sum(s, n, tot): + if tot == 0: + return True + if n < 0 or tot < 0: + return False + + incl = subset_sum(s, n-1, tot-s[n]) + + if incl: + return True + + excl = subset_sum(s, n-1, tot) + return excl + +def equal_partitions(s): + S = sum(s) + if len(s) == 0 or S % 2 == 1: + return False + return subset_sum(s, len(s)-1, S/2) + +def find_min_matrix_path(mat, i=0, j=0, mem=dict()): + # Find min-cost path from (0,0) to mat.shape - (1,1) + if (i+1, j+1) == mat.shape: + return mat[i, j] + if (i,j) in mem: + return mem[i,j] + if i < mat.shape[0]-1: + via_right = find_min_matrix_path(mat, i+1, j, mem) + else: + via_right = 1e6 + if j < mat.shape[1]-1: + via_down = find_min_matrix_path(mat, i, j+1, mem) + else: + via_down = 1e6 + if via_right < via_down: + mem[i,j] = mat[i,j] + via_right + return mem[i,j] + else: + mem[i,j] = mat[i,j] + via_down + return mem[i,j] + + +def count_matrix_paths_with_cost(mat, cost, i=0, j=0): + # Dest. is implicitly bottom right corner + + # Base case: + if (i+1,j+1) == mat.shape: + return cost == mat[i,j], [[(i,j)]] + + if i < mat.shape[0]-1: + via_right, rp = count_matrix_paths_with_cost(mat, cost - mat[i,j], i+1, j) + else: + via_right, rp = 0, [] + if j < mat.shape[1]-1: + via_down, dp = count_matrix_paths_with_cost(mat, cost - mat[i,j], i, j+1) + else: + via_down, dp = 0, [] + paths = [] + if via_down+via_right > 0: + paths = [[(i,j)] + p for p in rp+dp] + return (via_down + via_right, paths) + +def min_sum_partition(s, n, S1=0, S2=0): + if n < 0: + return S1, S2 + s11, s21 = min_sum_partition(s, n-1, S1+s[n], S2) + s12, s22 = min_sum_partition(s, n-1, S1, S2+s[n]) + + if abs(s11-s21) < abs(s12-s22): + print(f"{s[n]} in S1") + return s11, s21 + else: + print(f"{s[n]} in S2") + return s12, s22 + +def rodcut(L, lengths, prices): + if L < min(lengths): + return 0 + return max(p+rodcut(L-l, lengths, prices) for (l, p) in zip(lengths, prices) if L-l >= 0) +