diff --git a/Project.toml b/Project.toml index 8384c28..da3b071 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "PatternFolds" uuid = "c18a7f1d-76ad-4ce4-950d-5419b888513b" authors = ["Jean-Francois Baffier"] -version = "0.1.2" +version = "0.1.3" [deps] Lazy = "50d2b5c4-7a5e-59d5-8109-a42b560f39c0" diff --git a/src/PatternFolds.jl b/src/PatternFolds.jl index 3609fb0..eb0f613 100644 --- a/src/PatternFolds.jl +++ b/src/PatternFolds.jl @@ -7,9 +7,9 @@ using Lazy export PatternFold export IVectorFold, VectorFold export Interval, IntervalsFold -export pattern, gap, folds +export pattern, gap, folds, check_pattern export length -export unfold +export fold, unfold export value # includes diff --git a/src/common.jl b/src/common.jl index 68e2d99..e78d3fc 100644 --- a/src/common.jl +++ b/src/common.jl @@ -60,3 +60,29 @@ end Reset the *unfolded* pattern to the first fold. """ reset_pattern!(mvf) = set_fold!(mvf, 1) + +""" + fold(v::V, depth = 0) +returns a suitable `VectorFold`, which when unfolded gives the Vector V. +""" +function fold(v::V, depth = 0; kind = :mutable) where {T <: Real, V <: AbstractVector{T}} + l = length(v) + for i in 1:(l รท 2) + gap = v[i + 1] - v[1] + fold, r = divrem(l, i) + if r == 0 && check_pattern(v, i, gap, fold) + # return VectorFold(fold(v[1:i], depth + 1), gap, fold) + return make_vector_fold(v[1:i], gap, fold, kind) + end + end + if depth == 0 + @warn "No non-degenerate patterns have been found" v + return make_vector_fold(v, zero(T), 1, kind) + else + return v + end +end + +function make_vector_fold(pattern, gap, fold, kind = :mutable) + return make_vector_fold(pattern, gap, fold, Val(kind)) +end diff --git a/src/immutable_vector.jl b/src/immutable_vector.jl index e3c13b8..c96ce49 100644 --- a/src/immutable_vector.jl +++ b/src/immutable_vector.jl @@ -71,3 +71,17 @@ function Base.iterate(r_iter::Base.Iterators.Reverse{IVectorFold{T,V}}, return elem, next_state end + +# Folding a vector to give a suitable VectorFold +check_pattern(v, w, gap) = all(i -> i == gap, w - v) + +function check_pattern(v, i, gap, fold) + for j in 1:(fold -1) + v_start, v_end = (j - 1) * i + 1, j * i + w_start, w_end = j * i + 1, (j + 1) * i + !check_pattern(v[v_start:v_end], v[w_start:w_end], gap) && return false + end + return true +end + +make_vector_fold(pattern, gap, fold, ::Val{:immutable}) = IVectorFold(pattern, gap, fold) diff --git a/src/vector.jl b/src/vector.jl index 10d593f..9dd563d 100644 --- a/src/vector.jl +++ b/src/vector.jl @@ -93,3 +93,5 @@ function unfold(mvf::VectorFold; from=1, to=folds(mvf)) end return v end + +make_vector_fold(pattern, gap, fold, ::Val{:mutable}) = VectorFold(pattern, gap, fold) diff --git a/test/vector.jl b/test/vector.jl index 994f4b5..6a3991a 100644 --- a/test/vector.jl +++ b/test/vector.jl @@ -31,4 +31,16 @@ end @test isempty(IVectorFold(Vector(),1,1)) @test isempty(VectorFold(Vector(),1,1)) + + v1 = VectorFold([42,3,45,6],13,4) + w1 = unfold(v1) + v11 = fold(w1) + + @test unfold(v11) == w1 + + v2 = VectorFold([34,34,43,43],10,3) + w2 = unfold(v2) + v22 = fold(w2) + + @test unfold(v22) == w2 end