Skip to content

Commit d52e9c3

Browse files
committed
Add Util.with_replacement_permutations()
1 parent c7f58df commit d52e9c3

File tree

1 file changed

+46
-0
lines changed

1 file changed

+46
-0
lines changed

julia/Euler/src/lib/util.jl

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export is_palindrome, is_pandigital, is_pandigital_nz
77
export is_triangular, is_square, is_pentagonal, is_hexagonal
88
export divisors, proper_divisors
99
export get_σ_tbl, get_max_exp, undigits
10+
export with_replacement_permutations
1011

1112
function is_palindrome(num; base=10)
1213
x = num
@@ -134,4 +135,49 @@ function undigits(T::Type{<:Integer}, lst::Vector{U}; base::Integer = 10) where
134135
foldr((x, acc) -> acc * base + x, lst; init = zero(T))
135136
end
136137

138+
struct WithReplacementPermutations{T}
139+
a::T
140+
t::Integer
141+
end
142+
143+
with_replacement_permutations(a, t::Integer) = WithReplacementPermutations(a, t)
144+
145+
function Base.iterate(p::WithReplacementPermutations, st = nothing)
146+
if isnothing(st)
147+
length(p.a) == 0 && p.t > 0 && return nothing
148+
149+
return ([p.a[1] for _ in 1:p.t], ones(Int, p.t))
150+
else
151+
for k = p.t:-1:1
152+
st[k] == length(p.a) && continue
153+
154+
result = Array{eltype(p.a)}(undef, p.t)
155+
for j = 1:k
156+
result[j] = p.a[st[j]]
157+
end
158+
159+
st[k] += 1
160+
idx = st[k]
161+
result[k] = p.a[idx]
162+
for j = (k + 1):p.t
163+
st[j] = 1
164+
result[j] = p.a[1]
165+
end
166+
167+
return (result, st)
168+
end
169+
170+
return nothing
171+
end
172+
end
173+
174+
function Base.length(p::WithReplacementPermutations)
175+
length(p.a) < p.t && return 0
176+
return Int(length(p.a) ^ p.t)
177+
end
178+
179+
Base.eltype(p::WithReplacementPermutations) = Vector{eltype{p.a}}
180+
181+
Base.IteratorSize(p::WithReplacementPermutations) = Base.HasLength()
182+
137183
end #module

0 commit comments

Comments
 (0)