mirror of
https://github.com/kalmarek/Groups.jl.git
synced 2024-12-25 18:15:29 +01:00
find and replace, finally
This commit is contained in:
parent
afa0988ebc
commit
2196b7d256
184
src/Groups.jl
184
src/Groups.jl
@ -21,6 +21,7 @@ include("words.jl")
|
|||||||
include("hashing.jl")
|
include("hashing.jl")
|
||||||
include("freereduce.jl")
|
include("freereduce.jl")
|
||||||
include("arithmetic.jl")
|
include("arithmetic.jl")
|
||||||
|
include("findreplace.jl")
|
||||||
|
|
||||||
include("FreeGroup.jl")
|
include("FreeGroup.jl")
|
||||||
include("FPGroups.jl")
|
include("FPGroups.jl")
|
||||||
@ -70,189 +71,6 @@ end
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# Replacement of symbols / sub-words
|
|
||||||
#
|
|
||||||
|
|
||||||
issubsymbol(s::GSymbol, t::GSymbol) =
|
|
||||||
s.id == t.id && (0 ≤ s.pow ≤ t.pow || 0 ≥ s.pow ≥ t.pow)
|
|
||||||
|
|
||||||
function issubsymbol(s::FreeSymbol, w::GWord, sindex::Integer)
|
|
||||||
@boundscheck 1 ≤ sindex ≤ syllablelength(w) || throw(BoundsError(w, sindex))
|
|
||||||
return issubsymbol(s, syllables(w)[sindex])
|
|
||||||
end
|
|
||||||
|
|
||||||
function issubword(z::GWord, w::GWord, sindex::Integer)
|
|
||||||
isempty(z) && return true
|
|
||||||
@boundscheck 1 ≤ sindex ≤ syllablelength(w) || throw(BoundsError(w, sindex))
|
|
||||||
n = syllablelength(z)
|
|
||||||
n == 1 && return issubsymbol(first(syllables(z)), syllables(w)[sindex])
|
|
||||||
|
|
||||||
lastindex = sindex + n - 1
|
|
||||||
lastindex > syllablelength(w) && return false
|
|
||||||
|
|
||||||
issubsymbol(first(z), syllables(w)[sindex]) || return false
|
|
||||||
issubsymbol(syllables(z)[end], syllables(w)[lastindex]) || return false
|
|
||||||
for (zidx, widx) in zip(2:n-1, sindex+1:lastindex-1)
|
|
||||||
syllables(z)[zidx] == syllables(w)[widx] || return false
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
"""doc
|
|
||||||
Find the first syllable index k>=i such that Z < syllables(W)[k:k+syllablelength(Z)-1]
|
|
||||||
"""
|
|
||||||
function findnext(subword::GWord, word::GWord, start::Integer)
|
|
||||||
@boundscheck 1 ≤ start ≤ syllablelength(word) || throw(BoundsError(word, start))
|
|
||||||
isempty(subword) && return start
|
|
||||||
stop = syllablelength(word) - syllablelength(subword) +1
|
|
||||||
|
|
||||||
for idx in start:1:stop
|
|
||||||
issubword(subword, word, idx) && return idx
|
|
||||||
end
|
|
||||||
return nothing
|
|
||||||
end
|
|
||||||
|
|
||||||
function findnext(s::FreeSymbol, word::GWord, start::Integer)
|
|
||||||
@boundscheck 1 ≤ start ≤ syllablelength(word) || throw(BoundsError(word, start))
|
|
||||||
isone(s) && return start
|
|
||||||
stop = syllablelength(word)
|
|
||||||
|
|
||||||
for idx in start:1:stop
|
|
||||||
issubsymbol(s, word, idx) && return idx
|
|
||||||
end
|
|
||||||
return nothing
|
|
||||||
end
|
|
||||||
|
|
||||||
function findprev(subword::GWord, word::GWord, start::Integer)
|
|
||||||
@boundscheck 1 ≤ start ≤ syllablelength(word) || throw(BoundsError(word, start))
|
|
||||||
isempty(subword) && return start
|
|
||||||
stop = 1
|
|
||||||
|
|
||||||
for idx in start:-1:1
|
|
||||||
issubword(subword, word, idx) && return idx
|
|
||||||
end
|
|
||||||
return nothing
|
|
||||||
end
|
|
||||||
|
|
||||||
function findprev(s::FreeSymbol, word::GWord, start::Integer)
|
|
||||||
@boundscheck 1 ≤ start ≤ syllablelength(word) || throw(BoundsError(word, start))
|
|
||||||
isone(s) && return start
|
|
||||||
stop = 1
|
|
||||||
|
|
||||||
for idx in start:-1:stop
|
|
||||||
issubsymbol(s, word, idx) && return idx
|
|
||||||
end
|
|
||||||
return nothing
|
|
||||||
end
|
|
||||||
|
|
||||||
findfirst(subword::GWord, word::GWord) = findnext(subword, word, 1)
|
|
||||||
findlast(subword::GWord, word::GWord) =
|
|
||||||
findprev(subword, word, syllablelength(word)-syllablelength(subword)+1)
|
|
||||||
|
|
||||||
function replace!(out::GW, W::GW, lhs_rhs::Pair{GS, T}; count::Integer=typemax(Int)) where
|
|
||||||
{GS<:GSymbol, T<:GWord, GW<:GWord}
|
|
||||||
(count == 0 || isempty(W)) && return W
|
|
||||||
count < 0 && throw(DomainError(count, "`count` must be non-negative."))
|
|
||||||
|
|
||||||
lhs, rhs = lhs_rhs
|
|
||||||
|
|
||||||
sW = syllables(W)
|
|
||||||
sW_idx = 1
|
|
||||||
r = something(findnext(lhs, W, sW_idx), 0)
|
|
||||||
|
|
||||||
sout = syllables(out)
|
|
||||||
resize!(sout, 0)
|
|
||||||
sizehint!(sout, syllablelength(W))
|
|
||||||
|
|
||||||
c = 0
|
|
||||||
|
|
||||||
while !iszero(r)
|
|
||||||
append!(sout, view(sW, sW_idx:r-1))
|
|
||||||
a, b = divrem(sW[r].pow, lhs.pow)
|
|
||||||
|
|
||||||
if b != 0
|
|
||||||
push!(sout, change_pow(sW[r], b))
|
|
||||||
end
|
|
||||||
|
|
||||||
append!(sout, repeat(syllables(rhs), a))
|
|
||||||
|
|
||||||
sW_idx = r+1
|
|
||||||
sW_idx > syllablelength(W) && break
|
|
||||||
|
|
||||||
r = something(findnext(lhs, W, sW_idx), 0)
|
|
||||||
c += 1
|
|
||||||
c == count && break
|
|
||||||
end
|
|
||||||
append!(sout, sW[sW_idx:end])
|
|
||||||
return freereduce!(out)
|
|
||||||
end
|
|
||||||
|
|
||||||
function replace!(out::GW, W::GW, lhs_rhs::Pair{T, T}; count::Integer=typemax(Int)) where
|
|
||||||
{GW<:GWord, T <: GWord}
|
|
||||||
(count == 0 || isempty(W)) && return W
|
|
||||||
count < 0 && throw(DomainError(count, "`count` must be non-negative."))
|
|
||||||
|
|
||||||
lhs, rhs = lhs_rhs
|
|
||||||
lhs_slen = syllablelength(lhs)
|
|
||||||
lhs_slen == 1 && return replace!(out, W, first(syllables(lhs))=>rhs; count=count)
|
|
||||||
|
|
||||||
sW = syllables(W)
|
|
||||||
sW_idx = 1
|
|
||||||
r = something(findnext(lhs, W, sW_idx), 0)
|
|
||||||
|
|
||||||
sout = syllables(out)
|
|
||||||
resize!(sout, 0)
|
|
||||||
sizehint!(sout, syllablelength(W))
|
|
||||||
|
|
||||||
c = 0
|
|
||||||
|
|
||||||
while !iszero(r)
|
|
||||||
append!(sout, view(sW, sW_idx:r-1))
|
|
||||||
|
|
||||||
exp = sW[r].pow - first(syllables(lhs)).pow
|
|
||||||
if exp != 0
|
|
||||||
push!(sout, change_pow(sW[r], exp))
|
|
||||||
end
|
|
||||||
|
|
||||||
append!(sout, syllables(rhs))
|
|
||||||
|
|
||||||
exp = sW[r+lhs_slen-1].pow - last(syllables(lhs)).pow
|
|
||||||
if exp != 0
|
|
||||||
push!(sout, change_pow(sW[r+lhs_slen-1], exp))
|
|
||||||
end
|
|
||||||
|
|
||||||
sW_idx = r+lhs_slen
|
|
||||||
sW_idx > syllablelength(W) && break
|
|
||||||
|
|
||||||
r = something(findnext(lhs, W, sW_idx), 0)
|
|
||||||
c += 1
|
|
||||||
c == count && break
|
|
||||||
end
|
|
||||||
|
|
||||||
# copy the rest
|
|
||||||
append!(sout, sW[sW_idx:end])
|
|
||||||
return freereduce!(out)
|
|
||||||
end
|
|
||||||
|
|
||||||
function replace(W::GW, lhs_rhs::Pair{T, T}; count::Integer=typemax(Int)) where
|
|
||||||
{GW<:GWord, T <: GWord}
|
|
||||||
return replace!(one(W), W, lhs_rhs; count=count)
|
|
||||||
end
|
|
||||||
|
|
||||||
function replace(W::GW, subst_dict::Dict{T,T}) where {GW<:GWord, T<:GWord}
|
|
||||||
out = W
|
|
||||||
for toreplace in reverse!(sort!(collect(keys(subst_dict)), by=length))
|
|
||||||
replacement = subst_dict[toreplace]
|
|
||||||
if length(toreplace) > length(out)
|
|
||||||
continue
|
|
||||||
end
|
|
||||||
out = replace(out, toreplace=>replacement)
|
|
||||||
end
|
|
||||||
return out
|
|
||||||
end
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
#
|
#
|
||||||
# Misc
|
# Misc
|
||||||
|
182
src/findreplace.jl
Normal file
182
src/findreplace.jl
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
###############################################################################
|
||||||
|
#
|
||||||
|
# Replacement of symbols / sub-words
|
||||||
|
#
|
||||||
|
|
||||||
|
issubsymbol(s::GSymbol, t::GSymbol) =
|
||||||
|
s.id == t.id && (0 ≤ s.pow ≤ t.pow || 0 ≥ s.pow ≥ t.pow)
|
||||||
|
|
||||||
|
function issubsymbol(s::FreeSymbol, w::GWord, sindex::Integer)
|
||||||
|
@boundscheck 1 ≤ sindex ≤ syllablelength(w) || throw(BoundsError(w, sindex))
|
||||||
|
return issubsymbol(s, syllables(w)[sindex])
|
||||||
|
end
|
||||||
|
|
||||||
|
function issubword(z::GWord, w::GWord, sindex::Integer)
|
||||||
|
isempty(z) && return true
|
||||||
|
@boundscheck 1 ≤ sindex ≤ syllablelength(w) || throw(BoundsError(w, sindex))
|
||||||
|
n = syllablelength(z)
|
||||||
|
n == 1 && return issubsymbol(first(syllables(z)), syllables(w)[sindex])
|
||||||
|
|
||||||
|
lastindex = sindex + n - 1
|
||||||
|
lastindex > syllablelength(w) && return false
|
||||||
|
|
||||||
|
issubsymbol(first(z), syllables(w)[sindex]) || return false
|
||||||
|
issubsymbol(syllables(z)[end], syllables(w)[lastindex]) || return false
|
||||||
|
for (zidx, widx) in zip(2:n-1, sindex+1:lastindex-1)
|
||||||
|
syllables(z)[zidx] == syllables(w)[widx] || return false
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
"""doc
|
||||||
|
Find the first syllable index k>=i such that Z < syllables(W)[k:k+syllablelength(Z)-1]
|
||||||
|
"""
|
||||||
|
function findnext(subword::GWord, word::GWord, start::Integer)
|
||||||
|
@boundscheck 1 ≤ start ≤ syllablelength(word) || throw(BoundsError(word, start))
|
||||||
|
isempty(subword) && return start
|
||||||
|
stop = syllablelength(word) - syllablelength(subword) +1
|
||||||
|
|
||||||
|
for idx in start:1:stop
|
||||||
|
issubword(subword, word, idx) && return idx
|
||||||
|
end
|
||||||
|
return nothing
|
||||||
|
end
|
||||||
|
|
||||||
|
function findnext(s::FreeSymbol, word::GWord, start::Integer)
|
||||||
|
@boundscheck 1 ≤ start ≤ syllablelength(word) || throw(BoundsError(word, start))
|
||||||
|
isone(s) && return start
|
||||||
|
stop = syllablelength(word)
|
||||||
|
|
||||||
|
for idx in start:1:stop
|
||||||
|
issubsymbol(s, word, idx) && return idx
|
||||||
|
end
|
||||||
|
return nothing
|
||||||
|
end
|
||||||
|
|
||||||
|
function findprev(subword::GWord, word::GWord, start::Integer)
|
||||||
|
@boundscheck 1 ≤ start ≤ syllablelength(word) || throw(BoundsError(word, start))
|
||||||
|
isempty(subword) && return start
|
||||||
|
stop = 1
|
||||||
|
|
||||||
|
for idx in start:-1:1
|
||||||
|
issubword(subword, word, idx) && return idx
|
||||||
|
end
|
||||||
|
return nothing
|
||||||
|
end
|
||||||
|
|
||||||
|
function findprev(s::FreeSymbol, word::GWord, start::Integer)
|
||||||
|
@boundscheck 1 ≤ start ≤ syllablelength(word) || throw(BoundsError(word, start))
|
||||||
|
isone(s) && return start
|
||||||
|
stop = 1
|
||||||
|
|
||||||
|
for idx in start:-1:stop
|
||||||
|
issubsymbol(s, word, idx) && return idx
|
||||||
|
end
|
||||||
|
return nothing
|
||||||
|
end
|
||||||
|
|
||||||
|
findfirst(subword::GWord, word::GWord) = findnext(subword, word, 1)
|
||||||
|
findlast(subword::GWord, word::GWord) =
|
||||||
|
findprev(subword, word, syllablelength(word)-syllablelength(subword)+1)
|
||||||
|
|
||||||
|
function replace!(out::GW, W::GW, lhs_rhs::Pair{GS, T}; count::Integer=typemax(Int)) where
|
||||||
|
{GS<:GSymbol, T<:GWord, GW<:GWord}
|
||||||
|
(count == 0 || isempty(W)) && return W
|
||||||
|
count < 0 && throw(DomainError(count, "`count` must be non-negative."))
|
||||||
|
|
||||||
|
lhs, rhs = lhs_rhs
|
||||||
|
|
||||||
|
sW = syllables(W)
|
||||||
|
sW_idx = 1
|
||||||
|
r = something(findnext(lhs, W, sW_idx), 0)
|
||||||
|
|
||||||
|
sout = syllables(out)
|
||||||
|
resize!(sout, 0)
|
||||||
|
sizehint!(sout, syllablelength(W))
|
||||||
|
|
||||||
|
c = 0
|
||||||
|
|
||||||
|
while !iszero(r)
|
||||||
|
append!(sout, view(sW, sW_idx:r-1))
|
||||||
|
a, b = divrem(sW[r].pow, lhs.pow)
|
||||||
|
|
||||||
|
if b != 0
|
||||||
|
push!(sout, change_pow(sW[r], b))
|
||||||
|
end
|
||||||
|
|
||||||
|
append!(sout, repeat(syllables(rhs), a))
|
||||||
|
|
||||||
|
sW_idx = r+1
|
||||||
|
sW_idx > syllablelength(W) && break
|
||||||
|
|
||||||
|
r = something(findnext(lhs, W, sW_idx), 0)
|
||||||
|
c += 1
|
||||||
|
c == count && break
|
||||||
|
end
|
||||||
|
append!(sout, sW[sW_idx:end])
|
||||||
|
return freereduce!(out)
|
||||||
|
end
|
||||||
|
|
||||||
|
function replace!(out::GW, W::GW, lhs_rhs::Pair{T, T}; count::Integer=typemax(Int)) where
|
||||||
|
{GW<:GWord, T <: GWord}
|
||||||
|
(count == 0 || isempty(W)) && return W
|
||||||
|
count < 0 && throw(DomainError(count, "`count` must be non-negative."))
|
||||||
|
|
||||||
|
lhs, rhs = lhs_rhs
|
||||||
|
lhs_slen = syllablelength(lhs)
|
||||||
|
lhs_slen == 1 && return replace!(out, W, first(syllables(lhs))=>rhs; count=count)
|
||||||
|
|
||||||
|
sW = syllables(W)
|
||||||
|
sW_idx = 1
|
||||||
|
r = something(findnext(lhs, W, sW_idx), 0)
|
||||||
|
|
||||||
|
sout = syllables(out)
|
||||||
|
resize!(sout, 0)
|
||||||
|
sizehint!(sout, syllablelength(W))
|
||||||
|
|
||||||
|
c = 0
|
||||||
|
|
||||||
|
while !iszero(r)
|
||||||
|
append!(sout, view(sW, sW_idx:r-1))
|
||||||
|
|
||||||
|
exp = sW[r].pow - first(syllables(lhs)).pow
|
||||||
|
if exp != 0
|
||||||
|
push!(sout, change_pow(sW[r], exp))
|
||||||
|
end
|
||||||
|
|
||||||
|
append!(sout, syllables(rhs))
|
||||||
|
|
||||||
|
exp = sW[r+lhs_slen-1].pow - last(syllables(lhs)).pow
|
||||||
|
if exp != 0
|
||||||
|
push!(sout, change_pow(sW[r+lhs_slen-1], exp))
|
||||||
|
end
|
||||||
|
|
||||||
|
sW_idx = r+lhs_slen
|
||||||
|
sW_idx > syllablelength(W) && break
|
||||||
|
|
||||||
|
r = something(findnext(lhs, W, sW_idx), 0)
|
||||||
|
c += 1
|
||||||
|
c == count && break
|
||||||
|
end
|
||||||
|
|
||||||
|
# copy the rest
|
||||||
|
append!(sout, sW[sW_idx:end])
|
||||||
|
return freereduce!(out)
|
||||||
|
end
|
||||||
|
|
||||||
|
function replace(W::GW, lhs_rhs::Pair{T, T}; count::Integer=typemax(Int)) where
|
||||||
|
{GW<:GWord, T <: GWord}
|
||||||
|
return replace!(one(W), W, lhs_rhs; count=count)
|
||||||
|
end
|
||||||
|
|
||||||
|
function replace(W::GW, subst_dict::Dict{T,T}) where {GW<:GWord, T<:GWord}
|
||||||
|
out = W
|
||||||
|
for toreplace in reverse!(sort!(collect(keys(subst_dict)), by=length))
|
||||||
|
replacement = subst_dict[toreplace]
|
||||||
|
if length(toreplace) > length(out)
|
||||||
|
continue
|
||||||
|
end
|
||||||
|
out = replace(out, toreplace=>replacement)
|
||||||
|
end
|
||||||
|
return out
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user