Julia: Unique sets of n elements with replacement - combinatorics

Given a vector v = [1,..,n], I try to compute all unique sets of n elements with replacements in julia.
Since I want to do this for larger values of n, I'm looking for an efficient solution, possibly using iterators.
For example, let's consider v = [1, 2, 3]: This should results in [1,1,1], [1,1,2], [1,1,3], [1,2,2], [1,2,3], [1,3,3], [2,2,2], [2,2,3], [2,3,3], [3,3,3]. With unique, I mean that if [1,1,2] is a solution, any of its permutations [1,2,1], [2,1,1] is not.
My current solution is based on the partitions function, but does not allow me to restrict the computation on the elements [1,..,n]
for i in n:n^2
for j in partitions(i, n)
## ignore sets which exceed the range [1,n]
if maximum(j) <= n
## accept as solution
end
end
end

In julia v0.5.0, combinatorics.jl has a with_replacement_combinations method.
julia> collect(with_replacement_combinations(1:4,3))
20-element Array{Array{Int64,1},1}:
[1,1,1]
[1,1,2]
[1,1,3]
[1,1,4]
[1,2,2]
[1,2,3]
[1,2,4]
[1,3,3]
[1,3,4]
[1,4,4]
[2,2,2]
[2,2,3]
[2,2,4]
[2,3,3]
[2,3,4]
[2,4,4]
[3,3,3]
[3,3,4]
[3,4,4]
[4,4,4]

I guess, it doesn't get shorter than one-line (using Iterators).
using IterTools
import Combinatorics.combinations
n=3
collect(imap(c -> Int[c[k]-k+1 for k=1:length(c)],combinations(1:(2n-1),n)))

I believe you're looking for the product function from the Iterators package. In your case product(v,v,v) should do what's required.

Here is a function to calculate the required collection:
function calcset(n=3)
res = []
for c in combinations([1:(2n-1)],n-1)
c3 = [c,2n].-[0,c]
push!(res,vcat([fill(i,c3[n-i+1]-1) for i=1:n]...))
end
return res
end
calcset(3)
There is probably some better way to code this, but this should be enough.
Notice the result is generated through repeated push!s, so this is easily turned into an iterator, if necessary.

And in iterator form:
import Base: start, next, done, eltype, length
type ImageTypeIterator
inneritr::Base.Combinations{Array{Int64,1}}
n::Int
end
imagetype(n::Int) = ImageTypeIterator(combinations([1:(2n-1)],n-1),n)
eltype(itr::ImageTypeIterator) = Array{Int64,1}
start(itr::ImageTypeIterator) = start(itr.inneritr)
function next(itr::ImageTypeIterator,s)
(c,s) = next(itr.inneritr,s)
c3 = [c,2*itr.n].-[0,c]
(vcat([fill(i,c3[itr.n-i+1]-1) for i=1:itr.n]...),s)
end
done(itr::ImageTypeIterator,s) = done(itr.inneritr,s)
length(itr::ImageTypeIterator) = length(itr.inneritr)
# test with [1,2,3]
for t in imagetype(3) println(t) ; end
The test at the end should print the collection set in the question.
BTW the name ImageTypeIterator is an attempt to characterize the collection as the distinct types of sizes of preimages when looking at a function f : [1:n] -> [1:n]. But a different interpretation might be appropriate. Other names suggestion welcome in comments.
A faster?/clearer? implementation could use:
imagetype(n::Int) = ImageTypeIterator(combinations([1:(2n-1)],n),n)
function next(itr::ImageTypeIterator,s)
(c,s) = next(itr.inneritr,s)
v = Array(Int,itr.n)
j = 1 ; p = 1
for k=1:itr.n
while !(j in c) j += 1 ; p += 1 ; end
v[k] = p
j += 1
end
(v,s)
end
Its the same logic as above, but without too much slicing. The logic takes a subset of 2n-1 and views non-gaps as repeated values and gaps as a trigger to advance to next value.

OK, a simpler version using Iterators.jl:
using Iterators
function ff(c)
v = Array(Int,length(c))
j = 1 ; p = 1
for k=1:length(c)
while !(j in c) j += 1 ; p += 1 ; end
v[k] = p
j += 1
end
v
end
# test
n = 3
for t in imap(ff,combinations([1:(2n-1)],n)) println(t) ; end
This is perhaps the simplest version, although equivalent in methods to the other answers.
And in the spirit of brevity:
using Iterators
ff(c) = begin
j=1;p=1; [(while !(j in c) j+=1;p+=1 ; end ; j+=1 ; p) for k=1:length(c)]
end
n = 3 # test
for t in imap(ff,combinations([1:(2n-1)],n)) println(t) ; end

Related

Need to sum the total of Multiplication without using loops

num = 5
for i in range(1,num):
for j in range(1,num):
print(i * j, end="\t")
print()
I have this multiplication table and i need to sum all of the numbers given without using loops.
can anyone advise?
Mathematics makes any task easier.
Formula is (n(n+1)/2)^2. Just put n = num-1. num-1 because your for loop generates table upto number 4.
Code:
>>> num = 5
>>> sum = ((num*(num-1))/2)**2
>>> print(sum)
100.0
I think you want to sum all resulting multiplication then add few lines in your code.
num = 5
multi_list = []
for i in range(1,num):
for j in range(1,num):
multi_list.append(i*j)
print(sum(multi_list))
#100

How To Generate A List Of Possible Combination From A Set Dictionary

I'm a beginner coder, I have the code below
def PossibleNum(List):
DefaultSymbol = '%'
NumDict = ["0","1","2","3","4","5","6","7","8","9"]
FinishList = []
for Item in List:
for i in range(len(NumDict)):
_item = Item.replace(DefaultSymbol,NumDict[i])
FinishList.append(_item)
return FinishList
List = ["AAAA%%","BBB%%%","CC%%C%"]
print (PossibleNum(List))
I'm trying to get every possible combination from NumDict by Replacing each of "%" into every possible NumDict
Wanted Output : [AAAA00,AAAA01,AAAA02,AAAA03....,AAAA99]
Current Output : [AAAA11,AAAA22,AAAA33,AAAA,44,AAAA55,AAAA66]
You can use str.replace with count parameter set to 1. To obtain the combinations, I used str.format method.
For example:
lst = ["AAAA%%","BBB%%%","CC%%C%"]
output = []
for i in lst:
n = i.count('%')
backup = i
for v in range(10**n):
i = backup
for ch in '{:0{n}}'.format(v, n=n):
i = i.replace('%', ch, 1)
output.append(i)
# pretty print:
from pprint import pprint
pprint(output)
Prints:
['AAAA00',
'AAAA01',
'AAAA02',
'AAAA03',
...all the way to:
'CC99C5',
'CC99C6',
'CC99C7',
'CC99C8',
'CC99C9']
An option using itertools.product to get all the possible inserts:
import itertools
l = ["AAAA%%","BBB%%%","CC%%C%"]
DefaultSymbol = '%'
NumDict = ["0","1","2","3","4","5","6","7","8","9"]
out = []
for s in l:
n = s.count(DefaultSymbol)
prod = itertools.product(NumDict, repeat=n)
for p in prod:
tmp = s
for i in p:
tmp = tmp.replace(DefaultSymbol, i, 1)
out.append(tmp)
Pretty straight forward; for each input list element get the number of replacements (count of '%'), calculate all possible elements to insert using itertools.product, then iterate over all these elements (for p in prod) and do the replacements, one at a time (for i in p, with replace count set to 1).

How to apply multiprocessing in python3.x for the following nested loop

for i in range(1,row):
for j in range(1,col):
if i > j and i != j:
x = Aglo[0][i][0]
y = Aglo[j][0][0]
Aglo[j][i] = offset.myfun(x,y)
Aglo[i][j] = Aglo[j][i]
Aglo[][] is a 2D array, which consists of lists in the first row
offset.myfun() is a function defined elsewhere
This might be a trivial question but i couldn't understand how to use multiprocessing for these nested loops as x,y (used in myfun()) is different for each process(if multiprocessing is used)
Thank you
If I'm reading your code right, you are not overwriting any previously calculated values. If that's true, then you can use multiprocessing. If not, then you can't guarantee that the results from multiprocessing will be in the correct order.
To use something like multiprocessing.Pool, you would need to gather all valid (x, y) pairs to pass to offset.myfun(). Something like this might work (untested):
pairs = [(i, j, Aglo[0][i][0], Aglo[j][0][0]) for i in range(1, row) for j in range(1, col) if i > j and i != j]
# offset.myfun now needs to take a tuple instead of x, y
# it additionally needs to emit i and j in addition to the return value
# e.g. (i, j, result)
p = Pool(4)
results = p.map(offset.myfun, pairs)
# fill in Aglo with the results
for pair in pairs:
i, j, value = pair
Aglo[i][j] = value
Aglo[j][i] = value
You will need to pass in i and j to offset.myfun because otherwise there is no way to know which result goes where. offset.myfun should then return i and j along with the result so you can fill in Aglo appropriately. Hope this helps.

Convert list of integers to a single integer : ValueError

I am trying to convert a list of integers in Python into a single integer say for example [1,2,3,4] to 1234(integer). In my function, I am using following piece of code:
L = [1,2,3,4]
b = int(''.join(map(str, L)))
return b
The compiler throws a ValueError. Why so? How to rectify this issue?
You can do this like this also if that cause problems:
L = [1,2,3,4]
maxR = len(L) -1
res = 0
for n in L:
res += n * 10 ** maxR
maxR -= 1
print(res)
1234
another solution would be
L = [1,2,3,4]
digitsCounter = 1
def digits(num):
global digitsCounter
num *= digitsCounter
digitsCounter *= 10
return num
sum(map(digits, L[::-1]))
the digits() is a non pure function that takes a number and places it on place value depending on the iteration calling digits on each iteration
1. digits(4) = 4 1st iteration
2. digits(4) = 40 2nd iteration
3. digits(4) = 400 3rd iteration
when we sum up the array returned by map from the inverted list L[::-1] we get 1234 since every digit in the array is hoisted to it place value
if we choose not no invert L array to L[::-1] then we would need our digits function to do more to figure out the place value of each number in the list so we use this to take adv of language features

number as an object, or storing properties of a number

in designing an algebraic equation modelling system, I had this dilemma: we cannot associate properties to a number, if I turn the number to a table with a field "value" for example, I can overload arithmetic operators, but not the logic operator since that only works when both operands have same metatable, while my users will compare "x" with numbers frequently.
For example, here is a minimal equation solver system:
x = 0
y = 0
eq1 = {function() return 2*x + 3*y end, rhs = 1 }
eq2 = {function() return 3*x + 2*y end, rhs = 2 }
p = {{x,y},{eq1, eq2}}
solve(p)
The "solve()" will process table "p" to get all coefficients of the equation system and rhs. However, it is essential, a user can associate properties to "x" and "y", for example, lower bound, upper bound. I tries using table,
x = {val=0, lb=0, ub=3}
y = {val=1,lb=3,ub=5}
....
and write metamethods for "x" and "y" such that arithmetic operating will act on x.val and y.val. However, in a scripting environment, we also need to compare "x" with numbers, i.e., "if x>0 then ...". And I stuck here. An ugly solution is to ask users to use x.val, y.val everywhere in modelling the equation and scripting. Does anyone here has similar need to associate properties to a number, and the number can still be used in arithmetic/logic operations?
Something like this could work:
x = {val = 10}
mt = {}
mt.__lt = function (op1, op2)
if (type(op1) == 'table') then a = op1.val else a = op1 end
if (type(op2) == 'table') then b = op2.val else b = op2 end
return a < b
end
setmetatable(x, mt)
print(x < 5) -- prints false
print(x < 15) -- prints true
print(x < x) -- prints false
print(5 < x) -- prints true
Of course, you would write similar methods for the other operators (__add, __mul, __eq and so on).
If you'd rather not use type()/reflection, you can use an even dirtier trick that takes advantage of the fact that unary minus is well, unary:
mt = {}
mt.__unm = function (num) return -(num.val) end
mt.__lt = function (a, b) return -(-a) < -(-b) end
This is rather simple if you have access to the debug library, do you?
debug.setmetatable(0, meta)
meta will be the metatable of ALL numbers. This will solve your logical overloading problem.
However if you would prefer assigning properties to numbers, there is a way you could do this, I wrote a quick example on how one would do so:
local number_props = {
{val="hi"},
{val="hi2"}
}
debug.setmetatable(0,{__index=function(self,k)return number_props[self][k]end})
print((1).val, (2).val)

Resources