Generating unique, ordered Pythagorean triplets - python

This is a program I wrote to calculate Pythagorean triplets. When I run the program it prints each set of triplets twice because of the if statement. Is there any way I can tell the program to only print a new set of triplets once? Thanks.
import math
def main():
for x in range (1, 1000):
for y in range (1, 1000):
for z in range(1, 1000):
if x*x == y*y + z*z:
print y, z, x
print '-'*50
if __name__ == '__main__':
main()

Pythagorean Triples make a good example for claiming "for loops considered harmful", because for loops seduce us into thinking about counting, often the most irrelevant part of a task.
(I'm going to stick with pseudo-code to avoid language biases, and to keep the pseudo-code streamlined, I'll not optimize away multiple calculations of e.g. x * x and y * y.)
Version 1:
for x in 1..N {
for y in 1..N {
for z in 1..N {
if x * x + y * y == z * z then {
// use x, y, z
}
}
}
}
is the worst solution. It generates duplicates, and traverses parts of the space that aren't useful (e.g. whenever z < y). Its time complexity is cubic on N.
Version 2, the first improvement, comes from requiring x < y < z to hold, as in:
for x in 1..N {
for y in x+1..N {
for z in y+1..N {
if x * x + y * y == z * z then {
// use x, y, z
}
}
}
}
which reduces run time and eliminates duplicated solutions. However, it is still cubic on N; the improvement is just a reduction of the co-efficient of N-cubed.
It is pointless to continue examining increasing values of z after z * z < x * x + y * y no longer holds. That fact motivates Version 3, the first step away from brute-force iteration over z:
for x in 1..N {
for y in x+1..N {
z = y + 1
while z * z < x * x + y * y {
z = z + 1
}
if z * z == x * x + y * y and z <= N then {
// use x, y, z
}
}
}
For N of 1000, this is about 5 times faster than Version 2, but it is still cubic on N.
The next insight is that x and y are the only independent variables; z depends on their values, and the last z value considered for the previous value of y is a good starting search value for the next value of y. That leads to Version 4:
for x in 1..N {
y = x+1
z = y+1
while z <= N {
while z * z < x * x + y * y {
z = z + 1
}
if z * z == x * x + y * y and z <= N then {
// use x, y, z
}
y = y + 1
}
}
which allows y and z to "sweep" the values above x only once. Not only is it over 100 times faster for N of 1000, it is quadratic on N, so the speedup increases as N grows.
I've encountered this kind of improvement often enough to be mistrustful of "counting loops" for any but the most trivial uses (e.g. traversing an array).
Update: Apparently I should have pointed out a few things about V4 that are easy to overlook.
Both of the while loops are controlled by the value of z (one directly, the other indirectly through the square of z). The inner while is actually speeding up the outer while, rather than being orthogonal to it. It's important to look at what the loops are doing, not merely to count how many loops there are.
All of the calculations in V4 are strictly integer arithmetic. Conversion to/from floating-point, as well as floating-point calculations, are costly by comparison.
V4 runs in constant memory, requiring only three integer variables. There are no arrays or hash tables to allocate and initialize (and, potentially, to cause an out-of-memory error).
The original question allowed all of x, y, and x to vary over the same range. V1..V4 followed that pattern.
Below is a not-very-scientific set of timings (using Java under Eclipse on my older laptop with other stuff running...), where the "use x, y, z" was implemented by instantiating a Triple object with the three values and putting it in an ArrayList. (For these runs, N was set to 10,000, which produced 12,471 triples in each case.)
Version 4: 46 sec.
using square root: 134 sec.
array and map: 400 sec.
The "array and map" algorithm is essentially:
squares = array of i*i for i in 1 .. N
roots = map of i*i -> i for i in 1 .. N
for x in 1 .. N
for y in x+1 .. N
z = roots[squares[x] + squares[y]]
if z exists use x, y, z
The "using square root" algorithm is essentially:
for x in 1 .. N
for y in x+1 .. N
z = (int) sqrt(x * x + y * y)
if z * z == x * x + y * y then use x, y, z
The actual code for V4 is:
public Collection<Triple> byBetterWhileLoop() {
Collection<Triple> result = new ArrayList<Triple>(limit);
for (int x = 1; x < limit; ++x) {
int xx = x * x;
int y = x + 1;
int z = y + 1;
while (z <= limit) {
int zz = xx + y * y;
while (z * z < zz) {++z;}
if (z * z == zz && z <= limit) {
result.add(new Triple(x, y, z));
}
++y;
}
}
return result;
}
Note that x * x is calculated in the outer loop (although I didn't bother to cache z * z); similar optimizations are done in the other variations.
I'll be glad to provide the Java source code on request for the other variations I timed, in case I've mis-implemented anything.

Substantially faster than any of the solutions so far. Finds triplets via a ternary tree.
Wolfram says:
Hall (1970) and Roberts (1977) prove that (a, b, c) is a primitive Pythagorean triple if and only if
(a,b,c)=(3,4,5)M
where M is a finite product of the matrices U, A, D.
And there we have a formula to generate every primitive triple.
In the above formula, the hypotenuse is ever growing so it's pretty easy to check for a max length.
In Python:
import numpy as np
def gen_prim_pyth_trips(limit=None):
u = np.mat(' 1 2 2; -2 -1 -2; 2 2 3')
a = np.mat(' 1 2 2; 2 1 2; 2 2 3')
d = np.mat('-1 -2 -2; 2 1 2; 2 2 3')
uad = np.array([u, a, d])
m = np.array([3, 4, 5])
while m.size:
m = m.reshape(-1, 3)
if limit:
m = m[m[:, 2] <= limit]
yield from m
m = np.dot(m, uad)
If you'd like all triples and not just the primitives:
def gen_all_pyth_trips(limit):
for prim in gen_prim_pyth_trips(limit):
i = prim
for _ in range(limit//prim[2]):
yield i
i = i + prim
list(gen_prim_pyth_trips(10**4)) took 2.81 milliseconds to come back with 1593 elements while list(gen_all_pyth_trips(10**4)) took 19.8 milliseconds to come back with 12471 elements.
For reference, the accepted answer (in Python) took 38 seconds for 12471 elements.
Just for fun, setting the upper limit to one million list(gen_all_pyth_trips(10**6)) returns in 2.66 seconds with 1980642 elements (almost 2 million triples in 3 seconds). list(gen_all_pyth_trips(10**7)) brings my computer to its knees as the list gets so large it consumes every last bit of RAM. Doing something like sum(1 for _ in gen_all_pyth_trips(10**7)) gets around that limitation and returns in 30 seconds with 23471475 elements.
For more information on the algorithm used, check out the articles on Wolfram and Wikipedia.

You should define x < y < z.
for x in range (1, 1000):
for y in range (x + 1, 1000):
for z in range(y + 1, 1000):
Another good optimization would be to only use x and y and calculate zsqr = x * x + y * y. If zsqr is a square number (or z = sqrt(zsqr) is a whole number), it is a triplet, else not. That way, you need only two loops instead of three (for your example, that's about 1000 times faster).

The previously listed algorithms for generating Pythagorean triplets are all modifications of the naive approach derived from the basic relationship a^2 + b^2 = c^2 where (a, b, c) is a triplet of positive integers. It turns out that Pythagorean triplets satisfy some fairly remarkable relationships that can be used to generate all Pythagorean triplets.
Euclid discovered the first such relationship. He determined that for every Pythagorean triple (a, b, c), possibly after a reordering of a and b there are relatively prime positive integers m and n with m > n, at least one of which is even, and a positive integer k such that
a = k (2mn)
b = k (m^2 - n^2)
c = k (m^2 + n^2)
Then to generate Pythagorean triplets, generate relatively prime positive integers m and n of differing parity, and a positive integer k and apply the above formula.
struct PythagoreanTriple {
public int a { get; private set; }
public int b { get; private set; }
public int c { get; private set; }
public PythagoreanTriple(int a, int b, int c) : this() {
this.a = a < b ? a : b;
this.b = b < a ? a : b;
this.c = c;
}
public override string ToString() {
return String.Format("a = {0}, b = {1}, c = {2}", a, b, c);
}
public static IEnumerable<PythagoreanTriple> GenerateTriples(int max) {
var triples = new List<PythagoreanTriple>();
for (int m = 1; m <= max / 2; m++) {
for (int n = 1 + (m % 2); n < m; n += 2) {
if (m.IsRelativelyPrimeTo(n)) {
for (int k = 1; k <= max / (m * m + n * n); k++) {
triples.Add(EuclidTriple(m, n, k));
}
}
}
}
return triples;
}
private static PythagoreanTriple EuclidTriple(int m, int n, int k) {
int msquared = m * m;
int nsquared = n * n;
return new PythagoreanTriple(k * 2 * m * n, k * (msquared - nsquared), k * (msquared + nsquared));
}
}
public static class IntegerExtensions {
private static int GreatestCommonDivisor(int m, int n) {
return (n == 0 ? m : GreatestCommonDivisor(n, m % n));
}
public static bool IsRelativelyPrimeTo(this int m, int n) {
return GreatestCommonDivisor(m, n) == 1;
}
}
class Program {
static void Main(string[] args) {
PythagoreanTriple.GenerateTriples(1000).ToList().ForEach(t => Console.WriteLine(t));
}
}
The Wikipedia article on Formulas for generating Pythagorean triples contains other such formulae.

Algorithms can be tuned for speed, memory usage, simplicity, and other things.
Here is a pythagore_triplets algorithm tuned for speed, at the cost of memory usage and simplicity. If all you want is speed, this could be the way to go.
Calculation of list(pythagore_triplets(10000)) takes 40 seconds on my computer, versus 63 seconds for ΤΖΩΤΖΙΟΥ's algorithm, and possibly days of calculation for Tafkas's algorithm (and all other algorithms which use 3 embedded loops instead of just 2).
def pythagore_triplets(n=1000):
maxn=int(n*(2**0.5))+1 # max int whose square may be the sum of two squares
squares=[x*x for x in xrange(maxn+1)] # calculate all the squares once
reverse_squares=dict([(squares[i],i) for i in xrange(maxn+1)]) # x*x=>x
for x in xrange(1,n):
x2 = squares[x]
for y in xrange(x,n+1):
y2 = squares[y]
z = reverse_squares.get(x2+y2)
if z != None:
yield x,y,z
>>> print list(pythagore_triplets(20))
[(3, 4, 5), (5, 12, 13), (6, 8, 10), (8, 15, 17), (9, 12, 15), (12, 16, 20)]
Note that if you are going to calculate the first billion triplets, then this algorithm will crash before it even starts, because of an out of memory error. So ΤΖΩΤΖΙΟΥ's algorithm is probably a safer choice for high values of n.
BTW, here is Tafkas's algorithm, translated into python for the purpose of my performance tests. Its flaw is to require 3 loops instead of 2.
def gcd(a, b):
while b != 0:
t = b
b = a%b
a = t
return a
def find_triple(upper_boundary=1000):
for c in xrange(5,upper_boundary+1):
for b in xrange(4,c):
for a in xrange(3,b):
if (a*a + b*b == c*c and gcd(a,b) == 1):
yield a,b,c

def pyth_triplets(n=1000):
"Version 1"
for x in xrange(1, n):
x2= x*x # time saver
for y in xrange(x+1, n): # y > x
z2= x2 + y*y
zs= int(z2**.5)
if zs*zs == z2:
yield x, y, zs
>>> print list(pyth_triplets(20))
[(3, 4, 5), (5, 12, 13), (6, 8, 10), (8, 15, 17), (9, 12, 15), (12, 16, 20)]
V.1 algorithm has monotonically increasing x values.
EDIT
It seems this question is still alive :)
Since I came back and revisited the code, I tried a second approach which is almost 4 times as fast (about 26% of CPU time for N=10000) as my previous suggestion since it avoids lots of unnecessary calculations:
def pyth_triplets(n=1000):
"Version 2"
for z in xrange(5, n+1):
z2= z*z # time saver
x= x2= 1
y= z - 1; y2= y*y
while x < y:
x2_y2= x2 + y2
if x2_y2 == z2:
yield x, y, z
x+= 1; x2= x*x
y-= 1; y2= y*y
elif x2_y2 < z2:
x+= 1; x2= x*x
else:
y-= 1; y2= y*y
>>> print list(pyth_triplets(20))
[(3, 4, 5), (6, 8, 10), (5, 12, 13), (9, 12, 15), (8, 15, 17), (12, 16, 20)]
Note that this algorithm has increasing z values.
If the algorithm was converted to C —where, being closer to the metal, multiplications take more time than additions— one could minimalise the necessary multiplications, given the fact that the step between consecutive squares is:
(x+1)² - x² = (x+1)(x+1) - x² = x² + 2x + 1 - x² = 2x + 1
so all of the inner x2= x*x and y2= y*y would be converted to additions and subtractions like this:
def pyth_triplets(n=1000):
"Version 3"
for z in xrange(5, n+1):
z2= z*z # time saver
x= x2= 1; xstep= 3
y= z - 1; y2= y*y; ystep= 2*y - 1
while x < y:
x2_y2= x2 + y2
if x2_y2 == z2:
yield x, y, z
x+= 1; x2+= xstep; xstep+= 2
y-= 1; y2-= ystep; ystep-= 2
elif x2_y2 < z2:
x+= 1; x2+= xstep; xstep+= 2
else:
y-= 1; y2-= ystep; ystep-= 2
Of course, in Python the extra bytecode produced actually slows down the algorithm compared to version 2, but I would bet (without checking :) that V.3 is faster in C.
Cheers everyone :)

I juste extended Kyle Gullion 's answer so that triples are sorted by hypothenuse, then longest side.
It doesn't use numpy, but requires a SortedCollection (or SortedList) such as this one
def primitive_triples():
""" generates primitive Pythagorean triplets x<y<z
sorted by hypotenuse z, then longest side y
through Berggren's matrices and breadth first traversal of ternary tree
:see: https://en.wikipedia.org/wiki/Tree_of_primitive_Pythagorean_triples
"""
key=lambda x:(x[2],x[1])
triples=SortedCollection(key=key)
triples.insert([3,4,5])
A = [[ 1,-2, 2], [ 2,-1, 2], [ 2,-2, 3]]
B = [[ 1, 2, 2], [ 2, 1, 2], [ 2, 2, 3]]
C = [[-1, 2, 2], [-2, 1, 2], [-2, 2, 3]]
while triples:
(a,b,c) = triples.pop(0)
yield (a,b,c)
# expand this triple to 3 new triples using Berggren's matrices
for X in [A,B,C]:
triple=[sum(x*y for (x,y) in zip([a,b,c],X[i])) for i in range(3)]
if triple[0]>triple[1]: # ensure x<y<z
triple[0],triple[1]=triple[1],triple[0]
triples.insert(triple)
def triples():
""" generates all Pythagorean triplets triplets x<y<z
sorted by hypotenuse z, then longest side y
"""
prim=[] #list of primitive triples up to now
key=lambda x:(x[2],x[1])
samez=SortedCollection(key=key) # temp triplets with same z
buffer=SortedCollection(key=key) # temp for triplets with smaller z
for pt in primitive_triples():
z=pt[2]
if samez and z!=samez[0][2]: #flush samez
while samez:
yield samez.pop(0)
samez.insert(pt)
#build buffer of smaller multiples of the primitives already found
for i,pm in enumerate(prim):
p,m=pm[0:2]
while True:
mz=m*p[2]
if mz < z:
buffer.insert(tuple(m*x for x in p))
elif mz == z:
# we need another buffer because next pt might have
# the same z as the previous one, but a smaller y than
# a multiple of a previous pt ...
samez.insert(tuple(m*x for x in p))
else:
break
m+=1
prim[i][1]=m #update multiplier for next loops
while buffer: #flush buffer
yield buffer.pop(0)
prim.append([pt,2]) #add primitive to the list
the code is available in the math2 module of my Python library. It is tested against some series of the OEIS (code here at the bottom), which just enabled me to find a mistake in A121727 :-)

I wrote that program in Ruby and it similar to the python implementation. The important line is:
if x*x == y*y + z*z && gcd(y,z) == 1:
Then you have to implement a method that return the greatest common divisor (gcd) of two given numbers. A very simple example in Ruby again:
def gcd(a, b)
while b != 0
t = b
b = a%b
a = t
end
return a
end
The full Ruby methon to find the triplets would be:
def find_triple(upper_boundary)
(5..upper_boundary).each {|c|
(4..c-1).each {|b|
(3..b-1).each {|a|
if (a*a + b*b == c*c && gcd(a,b) == 1)
puts "#{a} \t #{b} \t #{c}"
end
}
}
}
end

Old Question, but i'll still input my stuff.
There are two general ways to generate unique pythagorean triples. One Is by Scaling, and the other is by using this archaic formula.
What scaling basically does it take a constant n, then multiply a base triple, lets say 3,4,5 by n. So taking n to be 2, we get 6,8,10 our next triple.
Scaling
def pythagoreanScaled(n):
triplelist = []
for x in range(n):
one = 3*x
two = 4*x
three = 5*x
triple = (one,two,three)
triplelist.append(triple)
return triplelist
The formula method uses the fact the if we take a number x, calculate 2m, m^2+1, and m^2-1, those three will always be a pythagorean triplet.
Formula
def pythagoreantriple(n):
triplelist = []
for x in range(2,n):
double = x*2
minus = x**2-1
plus = x**2+1
triple = (double,minus,plus)
triplelist.append(triple)
return triplelist

Yes, there is.
Okay, now you'll want to know why. Why not just constrain it so that z > y? Try
for z in range (y+1, 1000)

from math import sqrt
from itertools import combinations
#Pythagorean triplet - a^2 + b^2 = c^2 for (a,b) <= (1999,1999)
def gen_pyth(n):
if n >= 2000 :
return
ELEM = [ [ i,j,i*i + j*j ] for i , j in list(combinations(range(1, n + 1 ), 2)) if sqrt(i*i + j*j).is_integer() ]
print (*ELEM , sep = "\n")
gen_pyth(200)

for a in range(1,20):
for b in range(1,20):
for c in range(1,20):
if a>b and c and c>b:
if a**2==b**2+c**2:
print("triplets are:",a,b,c)

in python we can store square of all numbers in another list.
then find permutation of pairs of all number given
square them
finally check if any pair sum of square matches the squared list

Version 5 to Joel Neely.
Since X can be max of 'N-2' and Y can be max of 'N-1' for range of 1..N. Since Z max is N and Y max is N-1, X can be max of Sqrt ( N * N - (N-1) * (N-1) ) = Sqrt ( 2 * N - 1 ) and can start from 3.
MaxX = ( 2 * N - 1 ) ** 0.5
for x in 3..MaxX {
y = x+1
z = y+1
m = x*x + y*y
k = z * z
while z <= N {
while k < m {
z = z + 1
k = k + (2*z) - 1
}
if k == m and z <= N then {
// use x, y, z
}
y = y + 1
m = m + (2 * y) - 1
}
}

Just checking, but I've been using the following code to make pythagorean triples. It's very fast (and I've tried some of the examples here, though I kind of learned them and wrote my own and came back and checked here (2 years ago)). I think this code correctly finds all pythagorean triples up to (name your limit) and fairly quickly too. I used C++ to make it.
ullong is unsigned long long and I created a couple of functions to square and root
my root function basically said if square root of given number (after making it whole number (integral)) squared not equal number give then return -1 because it is not rootable.
_square and _root do as expected as of description above, I know of another way to optimize it but I haven't done nor tested that yet.
generate(vector<Triple>& triplist, ullong limit) {
cout<<"Please wait as triples are being generated."<<endl;
register ullong a, b, c;
register Triple trip;
time_t timer = time(0);
for(a = 1; a <= limit; ++a) {
for(b = a + 1; b <= limit; ++b) {
c = _root(_square(a) + _square(b));
if(c != -1 && c <= limit) {
trip.a = a; trip.b = b; trip.c = c;
triplist.push_back(trip);
} else if(c > limit)
break;
}
}
timer = time(0) - timer;
cout<<"Generated "<<triplist.size()<<" in "<<timer<<" seconds."<<endl;
cin.get();
cin.get();
}
Let me know what you all think. It generates all primitive and non-primitive triples according to the teacher I turned it in for. (she tested it up to 100 if I remember correctly).
The results from the v4 supplied by a previous coder here are
Below is a not-very-scientific set of timings (using Java under Eclipse on my older laptop with other stuff running...), where the "use x, y, z" was implemented by instantiating a Triple object with the three values and putting it in an ArrayList. (For these runs, N was set to 10,000, which produced 12,471 triples in each case.)
Version 4: 46 sec.
using square root: 134 sec.
array and map: 400 sec.
The results from mine is
How many triples to generate: 10000
Please wait as triples are being generated.
Generated 12471 in 2 seconds.
That is before I even start optimizing via the compiler. (I remember previously getting 10000 down to 0 seconds with tons of special options and stuff). My code also generates all the triples with 100,000 as the limit of how high side1,2,hyp can go in 3.2 minutes (I think the 1,000,000 limit takes an hour).
I modified the code a bit and got the 10,000 limit down to 1 second (no optimizations). On top of that, with careful thinking, mine could be broken down into chunks and threaded upon given ranges (for example 100,000 divide into 4 equal chunks for 3 cpu's (1 extra to hopefully consume cpu time just in case) with ranges 1 to 25,000 (start at 1 and limit it to 25,000), 25,000 to 50,000 , 50,000 to 75,000, and 75,000 to end. I may do that and see if it speeds it up any (I will have threads premade and not include them in the actual amount of time to execute the triple function. I'd need a more precise timer and a way to concatenate the vectors. I think that if 1 3.4 GHZ cpu with 8 gb ram at it's disposal can do 10,000 as lim in 1 second then 3 cpus should do that in 1/3 a second (and I round to higher second as is atm).

It should be noted that for a, b, and c you don't need to loop all the way to N.
For a, you only have to loop from 1 to int(sqrt(n**2/2))+1, for b, a+1 to int(sqrt(n**2-a**2))+1, and for c from int(sqrt(a**2+b**2) to int(sqrt(a**2+b**2)+2.

# To find all pythagorean triplets in a range
import math
n = int(input('Enter the upper range of limit'))
for i in range(n+1):
for j in range(1, i):
k = math.sqrt(i*i + j*j)
if k % 1 == 0 and k in range(n+1):
print(i,j,int(k))

U have to use Euclid's proof of Pythagorean triplets. Follow below...
U can choose any arbitrary number greater than zero say m,n
According to Euclid the triplet will be a(m*m-n*n), b(2*m*n), c(m*m+n*n)
Now apply this formula to find out the triplets, say our one value of triplet is 6 then, other two? Ok let’s solve...
a(m*m-n*n), b(2*m*n) , c(m*m+n*n)
It is sure that b(2*m*n) is obviously even. So now
(2*m*n)=6 =>(m*n)=3 =>m*n=3*1 =>m=3,n=1
U can take any other value rather than 3 and 1, but those two values should hold the product of two numbers which is 3 (m*n=3)
Now, when m=3 and n=1 Then,
a(m*m-n*n)=(3*3-1*1)=8 , c(m*m-n*n)=(3*3+1*1)=10
6,8,10 is our triplet for value, this our visualization of how generating triplets.
if given number is odd like (9) then slightly modified here, because b(2*m*n)
will never be odd. so, here we have to take
a(m*m-n*n)=7, (m+n)*(m-n)=7*1, So, (m+n)=7, (m-n)=1
Now find m and n from here, then find the other two values.
If u don’t understand it, read it again carefully.
Do code according this, it will generate distinct triplets efficiently.

A non-numpy version of the Hall/Roberts approach is
def pythag3(limit=None, all=False):
"""generate Pythagorean triples which are primitive (default)
or without restriction (when ``all`` is True). The elements
returned in the tuples are sorted with the smallest first.
Examples
========
>>> list(pythag3(20))
[(3, 4, 5), (8, 15, 17), (5, 12, 13)]
>>> list(pythag3(20, True))
[(3, 4, 5), (6, 8, 10), (9, 12, 15), (12, 16, 20), (8, 15, 17), (5, 12, 13)]
"""
if limit and limit < 5:
return
m = [(3,4,5)] # primitives stored here
while m:
x, y, z = m.pop()
if x > y:
x, y = y, x
yield (x, y, z)
if all:
a, b, c = x, y, z
while 1:
c += z
if c > limit:
break
a += x
b += y
yield a, b, c
# new primitives
a = x - 2*y + 2*z, 2*x - y + 2*z, 2*x - 2*y + 3*z
b = x + 2*y + 2*z, 2*x + y + 2*z, 2*x + 2*y + 3*z
c = -x + 2*y + 2*z, -2*x + y + 2*z, -2*x + 2*y + 3*z
for d in (a, b, c):
if d[2] <= limit:
m.append(d)
It's slower than the numpy-coded version but the primitives with largest element less than or equal to 10^6 are generated on my slow machine in about 1.4 seconds. (And the list m never grew beyond 18 elements.)

In c language -
#include<stdio.h>
int main()
{
int n;
printf("How many triplets needed : \n");
scanf("%d\n",&n);
for(int i=1;i<=2000;i++)
{
for(int j=i;j<=2000;j++)
{
for(int k=j;k<=2000;k++)
{
if((j*j+i*i==k*k) && (n>0))
{
printf("%d %d %d\n",i,j,k);
n=n-1;
}
}
}
}
}

You can try this
triplets=[]
for a in range(1,100):
for b in range(1,100):
for c in range(1,100):
if a**2 + b**2==c**2:
i=[a,b,c]
triplets.append(i)
for i in triplets:
i.sort()
if triplets.count(i)>1:
triplets.remove(i)
print(triplets)

Related

How do I optimise this function that generates pythagorean group of n elements (like triples but with any number of elements) using itertools? [duplicate]

This is a program I wrote to calculate Pythagorean triplets. When I run the program it prints each set of triplets twice because of the if statement. Is there any way I can tell the program to only print a new set of triplets once? Thanks.
import math
def main():
for x in range (1, 1000):
for y in range (1, 1000):
for z in range(1, 1000):
if x*x == y*y + z*z:
print y, z, x
print '-'*50
if __name__ == '__main__':
main()
Pythagorean Triples make a good example for claiming "for loops considered harmful", because for loops seduce us into thinking about counting, often the most irrelevant part of a task.
(I'm going to stick with pseudo-code to avoid language biases, and to keep the pseudo-code streamlined, I'll not optimize away multiple calculations of e.g. x * x and y * y.)
Version 1:
for x in 1..N {
for y in 1..N {
for z in 1..N {
if x * x + y * y == z * z then {
// use x, y, z
}
}
}
}
is the worst solution. It generates duplicates, and traverses parts of the space that aren't useful (e.g. whenever z < y). Its time complexity is cubic on N.
Version 2, the first improvement, comes from requiring x < y < z to hold, as in:
for x in 1..N {
for y in x+1..N {
for z in y+1..N {
if x * x + y * y == z * z then {
// use x, y, z
}
}
}
}
which reduces run time and eliminates duplicated solutions. However, it is still cubic on N; the improvement is just a reduction of the co-efficient of N-cubed.
It is pointless to continue examining increasing values of z after z * z < x * x + y * y no longer holds. That fact motivates Version 3, the first step away from brute-force iteration over z:
for x in 1..N {
for y in x+1..N {
z = y + 1
while z * z < x * x + y * y {
z = z + 1
}
if z * z == x * x + y * y and z <= N then {
// use x, y, z
}
}
}
For N of 1000, this is about 5 times faster than Version 2, but it is still cubic on N.
The next insight is that x and y are the only independent variables; z depends on their values, and the last z value considered for the previous value of y is a good starting search value for the next value of y. That leads to Version 4:
for x in 1..N {
y = x+1
z = y+1
while z <= N {
while z * z < x * x + y * y {
z = z + 1
}
if z * z == x * x + y * y and z <= N then {
// use x, y, z
}
y = y + 1
}
}
which allows y and z to "sweep" the values above x only once. Not only is it over 100 times faster for N of 1000, it is quadratic on N, so the speedup increases as N grows.
I've encountered this kind of improvement often enough to be mistrustful of "counting loops" for any but the most trivial uses (e.g. traversing an array).
Update: Apparently I should have pointed out a few things about V4 that are easy to overlook.
Both of the while loops are controlled by the value of z (one directly, the other indirectly through the square of z). The inner while is actually speeding up the outer while, rather than being orthogonal to it. It's important to look at what the loops are doing, not merely to count how many loops there are.
All of the calculations in V4 are strictly integer arithmetic. Conversion to/from floating-point, as well as floating-point calculations, are costly by comparison.
V4 runs in constant memory, requiring only three integer variables. There are no arrays or hash tables to allocate and initialize (and, potentially, to cause an out-of-memory error).
The original question allowed all of x, y, and x to vary over the same range. V1..V4 followed that pattern.
Below is a not-very-scientific set of timings (using Java under Eclipse on my older laptop with other stuff running...), where the "use x, y, z" was implemented by instantiating a Triple object with the three values and putting it in an ArrayList. (For these runs, N was set to 10,000, which produced 12,471 triples in each case.)
Version 4: 46 sec.
using square root: 134 sec.
array and map: 400 sec.
The "array and map" algorithm is essentially:
squares = array of i*i for i in 1 .. N
roots = map of i*i -> i for i in 1 .. N
for x in 1 .. N
for y in x+1 .. N
z = roots[squares[x] + squares[y]]
if z exists use x, y, z
The "using square root" algorithm is essentially:
for x in 1 .. N
for y in x+1 .. N
z = (int) sqrt(x * x + y * y)
if z * z == x * x + y * y then use x, y, z
The actual code for V4 is:
public Collection<Triple> byBetterWhileLoop() {
Collection<Triple> result = new ArrayList<Triple>(limit);
for (int x = 1; x < limit; ++x) {
int xx = x * x;
int y = x + 1;
int z = y + 1;
while (z <= limit) {
int zz = xx + y * y;
while (z * z < zz) {++z;}
if (z * z == zz && z <= limit) {
result.add(new Triple(x, y, z));
}
++y;
}
}
return result;
}
Note that x * x is calculated in the outer loop (although I didn't bother to cache z * z); similar optimizations are done in the other variations.
I'll be glad to provide the Java source code on request for the other variations I timed, in case I've mis-implemented anything.
Substantially faster than any of the solutions so far. Finds triplets via a ternary tree.
Wolfram says:
Hall (1970) and Roberts (1977) prove that (a, b, c) is a primitive Pythagorean triple if and only if
(a,b,c)=(3,4,5)M
where M is a finite product of the matrices U, A, D.
And there we have a formula to generate every primitive triple.
In the above formula, the hypotenuse is ever growing so it's pretty easy to check for a max length.
In Python:
import numpy as np
def gen_prim_pyth_trips(limit=None):
u = np.mat(' 1 2 2; -2 -1 -2; 2 2 3')
a = np.mat(' 1 2 2; 2 1 2; 2 2 3')
d = np.mat('-1 -2 -2; 2 1 2; 2 2 3')
uad = np.array([u, a, d])
m = np.array([3, 4, 5])
while m.size:
m = m.reshape(-1, 3)
if limit:
m = m[m[:, 2] <= limit]
yield from m
m = np.dot(m, uad)
If you'd like all triples and not just the primitives:
def gen_all_pyth_trips(limit):
for prim in gen_prim_pyth_trips(limit):
i = prim
for _ in range(limit//prim[2]):
yield i
i = i + prim
list(gen_prim_pyth_trips(10**4)) took 2.81 milliseconds to come back with 1593 elements while list(gen_all_pyth_trips(10**4)) took 19.8 milliseconds to come back with 12471 elements.
For reference, the accepted answer (in Python) took 38 seconds for 12471 elements.
Just for fun, setting the upper limit to one million list(gen_all_pyth_trips(10**6)) returns in 2.66 seconds with 1980642 elements (almost 2 million triples in 3 seconds). list(gen_all_pyth_trips(10**7)) brings my computer to its knees as the list gets so large it consumes every last bit of RAM. Doing something like sum(1 for _ in gen_all_pyth_trips(10**7)) gets around that limitation and returns in 30 seconds with 23471475 elements.
For more information on the algorithm used, check out the articles on Wolfram and Wikipedia.
You should define x < y < z.
for x in range (1, 1000):
for y in range (x + 1, 1000):
for z in range(y + 1, 1000):
Another good optimization would be to only use x and y and calculate zsqr = x * x + y * y. If zsqr is a square number (or z = sqrt(zsqr) is a whole number), it is a triplet, else not. That way, you need only two loops instead of three (for your example, that's about 1000 times faster).
The previously listed algorithms for generating Pythagorean triplets are all modifications of the naive approach derived from the basic relationship a^2 + b^2 = c^2 where (a, b, c) is a triplet of positive integers. It turns out that Pythagorean triplets satisfy some fairly remarkable relationships that can be used to generate all Pythagorean triplets.
Euclid discovered the first such relationship. He determined that for every Pythagorean triple (a, b, c), possibly after a reordering of a and b there are relatively prime positive integers m and n with m > n, at least one of which is even, and a positive integer k such that
a = k (2mn)
b = k (m^2 - n^2)
c = k (m^2 + n^2)
Then to generate Pythagorean triplets, generate relatively prime positive integers m and n of differing parity, and a positive integer k and apply the above formula.
struct PythagoreanTriple {
public int a { get; private set; }
public int b { get; private set; }
public int c { get; private set; }
public PythagoreanTriple(int a, int b, int c) : this() {
this.a = a < b ? a : b;
this.b = b < a ? a : b;
this.c = c;
}
public override string ToString() {
return String.Format("a = {0}, b = {1}, c = {2}", a, b, c);
}
public static IEnumerable<PythagoreanTriple> GenerateTriples(int max) {
var triples = new List<PythagoreanTriple>();
for (int m = 1; m <= max / 2; m++) {
for (int n = 1 + (m % 2); n < m; n += 2) {
if (m.IsRelativelyPrimeTo(n)) {
for (int k = 1; k <= max / (m * m + n * n); k++) {
triples.Add(EuclidTriple(m, n, k));
}
}
}
}
return triples;
}
private static PythagoreanTriple EuclidTriple(int m, int n, int k) {
int msquared = m * m;
int nsquared = n * n;
return new PythagoreanTriple(k * 2 * m * n, k * (msquared - nsquared), k * (msquared + nsquared));
}
}
public static class IntegerExtensions {
private static int GreatestCommonDivisor(int m, int n) {
return (n == 0 ? m : GreatestCommonDivisor(n, m % n));
}
public static bool IsRelativelyPrimeTo(this int m, int n) {
return GreatestCommonDivisor(m, n) == 1;
}
}
class Program {
static void Main(string[] args) {
PythagoreanTriple.GenerateTriples(1000).ToList().ForEach(t => Console.WriteLine(t));
}
}
The Wikipedia article on Formulas for generating Pythagorean triples contains other such formulae.
Algorithms can be tuned for speed, memory usage, simplicity, and other things.
Here is a pythagore_triplets algorithm tuned for speed, at the cost of memory usage and simplicity. If all you want is speed, this could be the way to go.
Calculation of list(pythagore_triplets(10000)) takes 40 seconds on my computer, versus 63 seconds for ΤΖΩΤΖΙΟΥ's algorithm, and possibly days of calculation for Tafkas's algorithm (and all other algorithms which use 3 embedded loops instead of just 2).
def pythagore_triplets(n=1000):
maxn=int(n*(2**0.5))+1 # max int whose square may be the sum of two squares
squares=[x*x for x in xrange(maxn+1)] # calculate all the squares once
reverse_squares=dict([(squares[i],i) for i in xrange(maxn+1)]) # x*x=>x
for x in xrange(1,n):
x2 = squares[x]
for y in xrange(x,n+1):
y2 = squares[y]
z = reverse_squares.get(x2+y2)
if z != None:
yield x,y,z
>>> print list(pythagore_triplets(20))
[(3, 4, 5), (5, 12, 13), (6, 8, 10), (8, 15, 17), (9, 12, 15), (12, 16, 20)]
Note that if you are going to calculate the first billion triplets, then this algorithm will crash before it even starts, because of an out of memory error. So ΤΖΩΤΖΙΟΥ's algorithm is probably a safer choice for high values of n.
BTW, here is Tafkas's algorithm, translated into python for the purpose of my performance tests. Its flaw is to require 3 loops instead of 2.
def gcd(a, b):
while b != 0:
t = b
b = a%b
a = t
return a
def find_triple(upper_boundary=1000):
for c in xrange(5,upper_boundary+1):
for b in xrange(4,c):
for a in xrange(3,b):
if (a*a + b*b == c*c and gcd(a,b) == 1):
yield a,b,c
def pyth_triplets(n=1000):
"Version 1"
for x in xrange(1, n):
x2= x*x # time saver
for y in xrange(x+1, n): # y > x
z2= x2 + y*y
zs= int(z2**.5)
if zs*zs == z2:
yield x, y, zs
>>> print list(pyth_triplets(20))
[(3, 4, 5), (5, 12, 13), (6, 8, 10), (8, 15, 17), (9, 12, 15), (12, 16, 20)]
V.1 algorithm has monotonically increasing x values.
EDIT
It seems this question is still alive :)
Since I came back and revisited the code, I tried a second approach which is almost 4 times as fast (about 26% of CPU time for N=10000) as my previous suggestion since it avoids lots of unnecessary calculations:
def pyth_triplets(n=1000):
"Version 2"
for z in xrange(5, n+1):
z2= z*z # time saver
x= x2= 1
y= z - 1; y2= y*y
while x < y:
x2_y2= x2 + y2
if x2_y2 == z2:
yield x, y, z
x+= 1; x2= x*x
y-= 1; y2= y*y
elif x2_y2 < z2:
x+= 1; x2= x*x
else:
y-= 1; y2= y*y
>>> print list(pyth_triplets(20))
[(3, 4, 5), (6, 8, 10), (5, 12, 13), (9, 12, 15), (8, 15, 17), (12, 16, 20)]
Note that this algorithm has increasing z values.
If the algorithm was converted to C —where, being closer to the metal, multiplications take more time than additions— one could minimalise the necessary multiplications, given the fact that the step between consecutive squares is:
(x+1)² - x² = (x+1)(x+1) - x² = x² + 2x + 1 - x² = 2x + 1
so all of the inner x2= x*x and y2= y*y would be converted to additions and subtractions like this:
def pyth_triplets(n=1000):
"Version 3"
for z in xrange(5, n+1):
z2= z*z # time saver
x= x2= 1; xstep= 3
y= z - 1; y2= y*y; ystep= 2*y - 1
while x < y:
x2_y2= x2 + y2
if x2_y2 == z2:
yield x, y, z
x+= 1; x2+= xstep; xstep+= 2
y-= 1; y2-= ystep; ystep-= 2
elif x2_y2 < z2:
x+= 1; x2+= xstep; xstep+= 2
else:
y-= 1; y2-= ystep; ystep-= 2
Of course, in Python the extra bytecode produced actually slows down the algorithm compared to version 2, but I would bet (without checking :) that V.3 is faster in C.
Cheers everyone :)
I juste extended Kyle Gullion 's answer so that triples are sorted by hypothenuse, then longest side.
It doesn't use numpy, but requires a SortedCollection (or SortedList) such as this one
def primitive_triples():
""" generates primitive Pythagorean triplets x<y<z
sorted by hypotenuse z, then longest side y
through Berggren's matrices and breadth first traversal of ternary tree
:see: https://en.wikipedia.org/wiki/Tree_of_primitive_Pythagorean_triples
"""
key=lambda x:(x[2],x[1])
triples=SortedCollection(key=key)
triples.insert([3,4,5])
A = [[ 1,-2, 2], [ 2,-1, 2], [ 2,-2, 3]]
B = [[ 1, 2, 2], [ 2, 1, 2], [ 2, 2, 3]]
C = [[-1, 2, 2], [-2, 1, 2], [-2, 2, 3]]
while triples:
(a,b,c) = triples.pop(0)
yield (a,b,c)
# expand this triple to 3 new triples using Berggren's matrices
for X in [A,B,C]:
triple=[sum(x*y for (x,y) in zip([a,b,c],X[i])) for i in range(3)]
if triple[0]>triple[1]: # ensure x<y<z
triple[0],triple[1]=triple[1],triple[0]
triples.insert(triple)
def triples():
""" generates all Pythagorean triplets triplets x<y<z
sorted by hypotenuse z, then longest side y
"""
prim=[] #list of primitive triples up to now
key=lambda x:(x[2],x[1])
samez=SortedCollection(key=key) # temp triplets with same z
buffer=SortedCollection(key=key) # temp for triplets with smaller z
for pt in primitive_triples():
z=pt[2]
if samez and z!=samez[0][2]: #flush samez
while samez:
yield samez.pop(0)
samez.insert(pt)
#build buffer of smaller multiples of the primitives already found
for i,pm in enumerate(prim):
p,m=pm[0:2]
while True:
mz=m*p[2]
if mz < z:
buffer.insert(tuple(m*x for x in p))
elif mz == z:
# we need another buffer because next pt might have
# the same z as the previous one, but a smaller y than
# a multiple of a previous pt ...
samez.insert(tuple(m*x for x in p))
else:
break
m+=1
prim[i][1]=m #update multiplier for next loops
while buffer: #flush buffer
yield buffer.pop(0)
prim.append([pt,2]) #add primitive to the list
the code is available in the math2 module of my Python library. It is tested against some series of the OEIS (code here at the bottom), which just enabled me to find a mistake in A121727 :-)
I wrote that program in Ruby and it similar to the python implementation. The important line is:
if x*x == y*y + z*z && gcd(y,z) == 1:
Then you have to implement a method that return the greatest common divisor (gcd) of two given numbers. A very simple example in Ruby again:
def gcd(a, b)
while b != 0
t = b
b = a%b
a = t
end
return a
end
The full Ruby methon to find the triplets would be:
def find_triple(upper_boundary)
(5..upper_boundary).each {|c|
(4..c-1).each {|b|
(3..b-1).each {|a|
if (a*a + b*b == c*c && gcd(a,b) == 1)
puts "#{a} \t #{b} \t #{c}"
end
}
}
}
end
Old Question, but i'll still input my stuff.
There are two general ways to generate unique pythagorean triples. One Is by Scaling, and the other is by using this archaic formula.
What scaling basically does it take a constant n, then multiply a base triple, lets say 3,4,5 by n. So taking n to be 2, we get 6,8,10 our next triple.
Scaling
def pythagoreanScaled(n):
triplelist = []
for x in range(n):
one = 3*x
two = 4*x
three = 5*x
triple = (one,two,three)
triplelist.append(triple)
return triplelist
The formula method uses the fact the if we take a number x, calculate 2m, m^2+1, and m^2-1, those three will always be a pythagorean triplet.
Formula
def pythagoreantriple(n):
triplelist = []
for x in range(2,n):
double = x*2
minus = x**2-1
plus = x**2+1
triple = (double,minus,plus)
triplelist.append(triple)
return triplelist
Yes, there is.
Okay, now you'll want to know why. Why not just constrain it so that z > y? Try
for z in range (y+1, 1000)
from math import sqrt
from itertools import combinations
#Pythagorean triplet - a^2 + b^2 = c^2 for (a,b) <= (1999,1999)
def gen_pyth(n):
if n >= 2000 :
return
ELEM = [ [ i,j,i*i + j*j ] for i , j in list(combinations(range(1, n + 1 ), 2)) if sqrt(i*i + j*j).is_integer() ]
print (*ELEM , sep = "\n")
gen_pyth(200)
for a in range(1,20):
for b in range(1,20):
for c in range(1,20):
if a>b and c and c>b:
if a**2==b**2+c**2:
print("triplets are:",a,b,c)
in python we can store square of all numbers in another list.
then find permutation of pairs of all number given
square them
finally check if any pair sum of square matches the squared list
Version 5 to Joel Neely.
Since X can be max of 'N-2' and Y can be max of 'N-1' for range of 1..N. Since Z max is N and Y max is N-1, X can be max of Sqrt ( N * N - (N-1) * (N-1) ) = Sqrt ( 2 * N - 1 ) and can start from 3.
MaxX = ( 2 * N - 1 ) ** 0.5
for x in 3..MaxX {
y = x+1
z = y+1
m = x*x + y*y
k = z * z
while z <= N {
while k < m {
z = z + 1
k = k + (2*z) - 1
}
if k == m and z <= N then {
// use x, y, z
}
y = y + 1
m = m + (2 * y) - 1
}
}
Just checking, but I've been using the following code to make pythagorean triples. It's very fast (and I've tried some of the examples here, though I kind of learned them and wrote my own and came back and checked here (2 years ago)). I think this code correctly finds all pythagorean triples up to (name your limit) and fairly quickly too. I used C++ to make it.
ullong is unsigned long long and I created a couple of functions to square and root
my root function basically said if square root of given number (after making it whole number (integral)) squared not equal number give then return -1 because it is not rootable.
_square and _root do as expected as of description above, I know of another way to optimize it but I haven't done nor tested that yet.
generate(vector<Triple>& triplist, ullong limit) {
cout<<"Please wait as triples are being generated."<<endl;
register ullong a, b, c;
register Triple trip;
time_t timer = time(0);
for(a = 1; a <= limit; ++a) {
for(b = a + 1; b <= limit; ++b) {
c = _root(_square(a) + _square(b));
if(c != -1 && c <= limit) {
trip.a = a; trip.b = b; trip.c = c;
triplist.push_back(trip);
} else if(c > limit)
break;
}
}
timer = time(0) - timer;
cout<<"Generated "<<triplist.size()<<" in "<<timer<<" seconds."<<endl;
cin.get();
cin.get();
}
Let me know what you all think. It generates all primitive and non-primitive triples according to the teacher I turned it in for. (she tested it up to 100 if I remember correctly).
The results from the v4 supplied by a previous coder here are
Below is a not-very-scientific set of timings (using Java under Eclipse on my older laptop with other stuff running...), where the "use x, y, z" was implemented by instantiating a Triple object with the three values and putting it in an ArrayList. (For these runs, N was set to 10,000, which produced 12,471 triples in each case.)
Version 4: 46 sec.
using square root: 134 sec.
array and map: 400 sec.
The results from mine is
How many triples to generate: 10000
Please wait as triples are being generated.
Generated 12471 in 2 seconds.
That is before I even start optimizing via the compiler. (I remember previously getting 10000 down to 0 seconds with tons of special options and stuff). My code also generates all the triples with 100,000 as the limit of how high side1,2,hyp can go in 3.2 minutes (I think the 1,000,000 limit takes an hour).
I modified the code a bit and got the 10,000 limit down to 1 second (no optimizations). On top of that, with careful thinking, mine could be broken down into chunks and threaded upon given ranges (for example 100,000 divide into 4 equal chunks for 3 cpu's (1 extra to hopefully consume cpu time just in case) with ranges 1 to 25,000 (start at 1 and limit it to 25,000), 25,000 to 50,000 , 50,000 to 75,000, and 75,000 to end. I may do that and see if it speeds it up any (I will have threads premade and not include them in the actual amount of time to execute the triple function. I'd need a more precise timer and a way to concatenate the vectors. I think that if 1 3.4 GHZ cpu with 8 gb ram at it's disposal can do 10,000 as lim in 1 second then 3 cpus should do that in 1/3 a second (and I round to higher second as is atm).
It should be noted that for a, b, and c you don't need to loop all the way to N.
For a, you only have to loop from 1 to int(sqrt(n**2/2))+1, for b, a+1 to int(sqrt(n**2-a**2))+1, and for c from int(sqrt(a**2+b**2) to int(sqrt(a**2+b**2)+2.
# To find all pythagorean triplets in a range
import math
n = int(input('Enter the upper range of limit'))
for i in range(n+1):
for j in range(1, i):
k = math.sqrt(i*i + j*j)
if k % 1 == 0 and k in range(n+1):
print(i,j,int(k))
U have to use Euclid's proof of Pythagorean triplets. Follow below...
U can choose any arbitrary number greater than zero say m,n
According to Euclid the triplet will be a(m*m-n*n), b(2*m*n), c(m*m+n*n)
Now apply this formula to find out the triplets, say our one value of triplet is 6 then, other two? Ok let’s solve...
a(m*m-n*n), b(2*m*n) , c(m*m+n*n)
It is sure that b(2*m*n) is obviously even. So now
(2*m*n)=6 =>(m*n)=3 =>m*n=3*1 =>m=3,n=1
U can take any other value rather than 3 and 1, but those two values should hold the product of two numbers which is 3 (m*n=3)
Now, when m=3 and n=1 Then,
a(m*m-n*n)=(3*3-1*1)=8 , c(m*m-n*n)=(3*3+1*1)=10
6,8,10 is our triplet for value, this our visualization of how generating triplets.
if given number is odd like (9) then slightly modified here, because b(2*m*n)
will never be odd. so, here we have to take
a(m*m-n*n)=7, (m+n)*(m-n)=7*1, So, (m+n)=7, (m-n)=1
Now find m and n from here, then find the other two values.
If u don’t understand it, read it again carefully.
Do code according this, it will generate distinct triplets efficiently.
A non-numpy version of the Hall/Roberts approach is
def pythag3(limit=None, all=False):
"""generate Pythagorean triples which are primitive (default)
or without restriction (when ``all`` is True). The elements
returned in the tuples are sorted with the smallest first.
Examples
========
>>> list(pythag3(20))
[(3, 4, 5), (8, 15, 17), (5, 12, 13)]
>>> list(pythag3(20, True))
[(3, 4, 5), (6, 8, 10), (9, 12, 15), (12, 16, 20), (8, 15, 17), (5, 12, 13)]
"""
if limit and limit < 5:
return
m = [(3,4,5)] # primitives stored here
while m:
x, y, z = m.pop()
if x > y:
x, y = y, x
yield (x, y, z)
if all:
a, b, c = x, y, z
while 1:
c += z
if c > limit:
break
a += x
b += y
yield a, b, c
# new primitives
a = x - 2*y + 2*z, 2*x - y + 2*z, 2*x - 2*y + 3*z
b = x + 2*y + 2*z, 2*x + y + 2*z, 2*x + 2*y + 3*z
c = -x + 2*y + 2*z, -2*x + y + 2*z, -2*x + 2*y + 3*z
for d in (a, b, c):
if d[2] <= limit:
m.append(d)
It's slower than the numpy-coded version but the primitives with largest element less than or equal to 10^6 are generated on my slow machine in about 1.4 seconds. (And the list m never grew beyond 18 elements.)
In c language -
#include<stdio.h>
int main()
{
int n;
printf("How many triplets needed : \n");
scanf("%d\n",&n);
for(int i=1;i<=2000;i++)
{
for(int j=i;j<=2000;j++)
{
for(int k=j;k<=2000;k++)
{
if((j*j+i*i==k*k) && (n>0))
{
printf("%d %d %d\n",i,j,k);
n=n-1;
}
}
}
}
}
You can try this
triplets=[]
for a in range(1,100):
for b in range(1,100):
for c in range(1,100):
if a**2 + b**2==c**2:
i=[a,b,c]
triplets.append(i)
for i in triplets:
i.sort()
if triplets.count(i)>1:
triplets.remove(i)
print(triplets)

Dividing an even number into N parts each part being a multiple of 2

Let's assume I have the number 100 which I need to divide into N parts each of which shouldn't exceed 30 initially. So the initial grouping would be (30,30,30). The remainder (which is 10) is to be distributed among these three groups by adding 2 to each group in succession, thus ensuring that each group is a multiple of 2. The desired output should therefore look like (34,34,32).
Note: The original number is always even.
I tried solving this in Python and this is what I came up with. Clearly it's not working in the way I thought it would. It distributes the remainder by adding 1 (and not 2, as desired) iteratively to each group.
num = 100
parts = num//30 #Number of parts into which 'num' is to be divided
def split(a, b):
result = ([a//b + 1] * (a%b) + [a//b] * (b - a%b))
return(result)
print(split(num, parts))
Output:
[34, 33, 33]
Desired output:
[34, 34, 32]
Simplified problem: forget about multiples of 2
First, let's simplify your problem for a second. Forget about the multiples of 2. Imagine you want to split a non-necessarily-even number n into k non-necessarily-even parts.
Obviously the most balanced solution is to have some parts be n // k, and some parts be n // k + 1.
How many of which? Let's call r the number of parts with n // k + 1. Then there are k - r parts with n // k, and all the parts sum up to:
(n // k) * (k - r) + (n // k + 1) * r
== (n // k) * (k - r) + (n // k) * r + r
== (n // k) * (k - r + r) + r
== (n // k) * k + r
But the parts should sum up to n, so we need to find r such that:
n == (n // k) * k + r
Happily, you might recognise Euclidean division here, with n // k being the quotient and r being the remainder.
This gives us our split function:
def split(n, k):
d,r = divmod(n, k)
return [d+1]*r + [d]*(k-r)
Testing:
print( split(50, 3) )
# [17, 17, 16]
Splitting into multiples of 2
Now back to your split_even problem. Now that we have the generic function split, a simple way to solve split_even is to use split:
def split_even(n, k):
return [2 * x for x in split(n // 2, k)]
Testing:
print( split_even(100, 3) )
# [34, 34, 32]
Generalisation: multiples of m
It's trivial to do the same thing with multiples of a number m other than 2:
def split_multiples(n, k, m=2):
return [m * x for x in split(n // m, k)]
Testing:
print( split_multiples(102, 4, 3) )
# [27, 27, 24, 24]
This solution is not very clear and easy to follow but it does not need any loops.
Full code:
def split(a,b):
lower = (a//b//2) * 2
num = a % (b*2) // 2
return [lower + 2] * num + [lower] * (b - num)
Explanation:
First get the value of all parts: We round the result of the division (value // parts) down to the next even value ((x // 2) * 2)
To get the number of higher values: We use the remainder of the division of a in double as many parts and divide it by two to compensate the multiplication
last: higher numbers are just lower + 2 times the computed number of higher values and lower numbers are filling the other spaces
My approach here is to create three arrays and sum them, the first two are simple, but the last is a little more complex to follow - it's just repping 2 (by) as many times as is can given the remainder, then repping 0s.
# Part 1
np.repeat(first, x//first)
# Part 2
np.repeat(by, x//first)
# Part 3
np.repeat([by, 0], [(x//first) - ((x - (x//first*first)) // by % by), (x - (x//first*first)) // by % by])
Wrapped into a function:
def split(x, first, by):
return(np.repeat(first, x//first) + np.repeat(by, x//first) + np.repeat([by, 0], [(x//first) - ((x - (x//first*first)) // by % by), (x - (x//first*first)) // by % by]))
split(100, 30, 2)

Code takes a lot of time to run for large numbers

Given the number of squares in a board (e.g. scrabble or chess board), N and dimensions AxB, this code tries to determine all possible
dimensional combinations that can give N number of squares in the board.
Example: N = 8
There are four possible dimensional combinations to obtain exactly 8 squares in the board. So, the code outputs board dimensions
1x8 2x3, 3x2 and 8x1. The 8x1 boards have eight 1x1 squares; the 3x2 boards have six 1x1 squares and two 2x2 squares.
Here is my solution:
def dims(num_sqrs):
dim_list=[]
for i in range(1,num_sqrs+1):
temp = []
for x in range(1,num_sqrs+1):
res = 0
a = i
b = x
while (a != 0) and (b !=0):
res = res + (a*b)
a = a -1
b = b-1
if res == num_sqrs:
dim_list.append((i,x))
print(dim_list)
dims(8)
However, this code takes too much time to run for large values of N.
Any suggestion to optimize the efficiency of the code will be much appreciated.
Here are two pretty obvious observations:
The square count for AxB is the same as the square count for BxA
If C>B then the square count for AxC is greater than the square count for AxB
Given those facts, it should be clear that:
We only need to consider AxB for A≤B, since we can just add BxA to the list if A≠B
For a given A and N, there is at most one value of B which has a square count of N.
The code below is based on the above. It tries each AxA in turn, for each one checking to see if there is some B≥A which produces the correct square count. It stops when the square count for AxA exceeds N.
Now, to find the correct value of B, a couple of slightly less obvious observations.
Suppose the square count for AxA is N. Then the square count for (A+1)x(Ax1) is N + (A+1)².
Proof: Every square in AxA can be identified by its upper left co-ordinate [i, j] and its size s. I'll write that as [s: *i, j]. (Here I'm assuming that coordinates are zero-based and go from top to bottom and left to right.)
For each such square 0 ≤ i + s < A and 0 ≤ j + s < A (assuming 0-based coordinates).
Now, suppose we change each square [s: i, j] into the square based at the same coordinate but with a size one larger, [s+1: i, j]. That new square is a square in (A+1)x(A+1), because 0 ≤ i + s + 1 < A + 1 (and similarly for j). So that transformation gives us every square in A + 1 whose size is at least 2. The only squares which we've missed are the squares of size 1, and there are exactly (A+1)×(A+1) of them.
Suppose the square count for AxB is N, and B≥A. Then the square count for Ax(B+1) is N + the sum of each integer from 1 to A. (These are the triangular number, which are A×(A+1)/2; I think that's well-known.)
Proof: The squares in Ax(B+1) are precisely the squares in AxB plus the squares whose right-hand side includes the last column of Ax(B+1). So we only need to count those. There is one such square of size A, two of size A-1, three of size A-2, and so on up to A squares of size 1.
So for a given A, we can compute the square count for AxA and the increment in the square count for each increase in B. If the increment even divides the difference between the target count and the count of AxA, then we've found an AxB.
The program below also relies on one more algebraic identity, which is pretty straight-forward: the sum of two consecutive triangular numbers is a square. That's obvious by just arranging the two triangles. The larger one contains the diagonal of the square. These facts are used to compute the next base value and increment for the next value of A.
def finds(n):
a = 1
base = 1 # Square count for AxA
inc = 1 # Difference between count(AxB) and count(AxB+1)
rects = []
while base < n:
if (n - base) % inc == 0:
rects.append((a, a + (n - base) // inc))
a += 1
newinc = inc + a
base += inc + newinc
inc = newinc
if base == n:
return rects + [(a, a)] + list(map(lambda p:p[::-1], reversed(rects)))
else:
return rects + list(map(lambda p:p[::-1], reversed(rects)))
The slowest part of that function is adding the reverse of the reverses of the AxB solutions at the end, which I only did to simplify counting the solutions correctly. My first try, which was almost twice as fast, used the loop while base <= n and then just returned rects. But it's still fast enough.
For example:
>>> finds(1000000)
[(1, 1000000), (4, 100001), (5, 66668), (15, 8338), (24, 3341),
(3341, 24), (8338, 15), (66668, 5), (100001, 4), (1000000, 1)]
>>> finds(760760)
[(1, 760760), (2, 253587), (3, 126794), (4, 76077), (7, 27172),
(10, 13835), (11, 11530), (12, 9757), (13, 8364), (19, 4010),
(20, 3629), (21, 3300), (38, 1039), (39, 988), (55, 512),
(56, 495), (65, 376), (76, 285), (285, 76), (376, 65),
(495, 56), (512, 55), (988, 39), (1039, 38), (3300, 21),
(3629, 20), (4010, 19), (8364, 13), (9757, 12), (11530, 11),
(13835, 10), (27172, 7), (76077, 4), (126794, 3), (253587, 2),
(760760, 1)]
The last one came out of this test, which took a few seconds: (It finds each successive maximum number of solutions, if you don't feel like untangling the functional elements)
>>> from functools import reduce
>>> print('\n'.join(
map(lambda l:' '.join(map(lambda ab:"%dx%d"%ab, l)),
reduce(lambda a,b: a if len(b) <= len(a[-1]) else a + [b],
(finds(n) for n in range(2,1000001)),[[(1,1)]]))))
1x1
1x2 2x1
1x5 2x2 5x1
1x8 2x3 3x2 8x1
1x14 2x5 3x3 5x2 14x1
1x20 2x7 3x4 4x3 7x2 20x1
1x50 2x17 3x9 4x6 6x4 9x3 17x2 50x1
1x140 2x47 3x24 4x15 7x7 15x4 24x3 47x2 140x1
1x280 4x29 5x20 6x15 7x12 12x7 15x6 20x5 29x4 280x1
1x770 2x257 3x129 4x78 10x17 11x15 15x11 17x10 78x4 129x3 257x2 770x1
1x1430 2x477 3x239 4x144 10x29 11x25 12x22 22x12 25x11 29x10 144x4 239x3 477x2 1430x1
1x3080 2x1027 3x514 4x309 7x112 10x59 11x50 20x21 21x20 50x11 59x10 112x7 309x4 514x3 1027x2 3080x1
1x7700 2x2567 3x1284 4x771 7x277 10x143 11x120 20x43 21x40 40x21 43x20 120x11 143x10 277x7 771x4 1284x3 2567x2 7700x1
1x10010 2x3337 3x1669 4x1002 10x185 11x155 12x132 13x114 20x54 21x50 50x21 54x20 114x13 132x12 155x11 185x10 1002x4 1669x3 3337x2 10010x1
1x34580 2x11527 3x5764 4x3459 7x1237 12x447 13x384 19x188 20x171 38x59 39x57 57x39 59x38 171x20 188x19 384x13 447x12 1237x7 3459x4 5764x3 11527x2 34580x1
1x40040 2x13347 3x6674 4x4005 7x1432 10x731 11x610 12x517 13x444 20x197 21x180 39x64 64x39 180x21 197x20 444x13 517x12 610x11 731x10 1432x7 4005x4 6674x3 13347x2 40040x1
1x100100 2x33367 3x16684 4x10011 7x3577 10x1823 11x1520 12x1287 13x1104 20x483 21x440 25x316 39x141 55x83 65x68 68x65 83x55 141x39 316x25 440x21 483x20 1104x13 1287x12 1520x11 1823x10 3577x7 10011x4 16684x3 33367x2 100100x1
1x340340 2x113447 3x56724 4x34035 7x12157 10x6191 11x5160 12x4367 13x3744 20x1627 21x1480 34x583 39x449 55x239 65x180 84x123 123x84 180x65 239x55 449x39 583x34 1480x21 1627x20 3744x13 4367x12 5160x11 6191x10 12157x7 34035x4 56724x3 113447x2 340340x1
1x760760 2x253587 3x126794 4x76077 7x27172 10x13835 11x11530 12x9757 13x8364 19x4010 20x3629 21x3300 38x1039 39x988 55x512 56x495 65x376 76x285 285x76 376x65 495x56 512x55 988x39 1039x38 3300x21 3629x20 4010x19 8364x13 9757x12 11530x11 13835x10 27172x7 76077x4 126794x3 253587x2 760760x1
I think the critical detail is that #Qudus is looking for boards where there are N squares of any size.
One simple optimization is to just break when res > n. Another optimization to make it about twice as fast is to only run it for boards where length >= width.
def dims(num_sqrs):
dim_list=[]
for i in range(1, num_sqrs + 1):
temp = []
for x in range(1, i + 1):
res = 0
a = i
b = x
while (a != 0) and (b != 0):
res = res + (a * b)
a = a - 1
b = b - 1
if res > num_sqrs:
break
if res == num_sqrs:
dim_list.append((i, x))
if i != x:
dim_list.append((x, i))
print(dim_list)
Here's a much faster solution that takes a different approach:
def dims(num_sqrs):
dim_list = []
sum_squares = [0]
sums = [0]
for i in range(1, num_sqrs + 1):
sums.append(sums[-1] + i)
sum_squares.append(sum_squares[-1] + i * i)
for i in range(1, num_sqrs + 1):
if sum_squares[i] > num_sqrs:
break
if sum_squares[i] == num_sqrs:
dim_list.append((i, i))
break
for x in range(i + 1, num_sqrs + 1):
total_squares = sum_squares[i] + sums[i] * (x - i)
if total_squares == num_sqrs:
dim_list.append((x, i))
dim_list.append((i, x))
break
if total_squares > num_sqrs:
break
return dim_list
Start with basic algebraic analysis. I derived my own formula for the sums of various sizes. From the initial analysis, we get that for a board of size n x m, there are (n-k)*(m-k) squares of size k. Summing this for k in [0, min(m, n)] we have a simple calculation formula:
sum(((n-k) * (m-k) for k in range(0, min(n, m))))
I expanded the product to nm - k(n+m) + k^2, re-derived the individual series sums, and made a non-iterative formula, assuming n <= m:
n * n * m
- n * (n - 1) / 2 * (n + m)
+ ((n - 1) * n * (2 * n - 1))/6
This first link then spoiled my fun with an even shorter formula:
t = m - n
n * (n + 1) / 6 * (2 * n + 3 * t + 1)
which follows from mine with a bit of nifty rearrangement of terms.
Now to the point of this exercise: given a desired count of squares, Q, find all rectangle dimensions (n, m) that have exactly that many squares. Starting with the formula above:
q = n * (n + 1) / 6 * (2 * n + 3 * t + 1)
Since we're given Q, the desired value for q, we can iterate through all values of n, finding whether there is a positive, integral value for t that satisfies the formula. Start by solving this for t:
t = (6/(n*(n+1)) * q - 2*n - 1) / 3
combining the denominators:
t = (6*q) / (3*n*(n+1)) - (2*n + 1)/3
I'll use the first version. Since a solution of n x m implies a solution of m x n, we can limit our search to only those cases n <= m. Also, since the numerator shrinks (negative n^3 term), we can limit the search for values of n that allow t >= 1 -- in other words, have the combined numerator at least as large as the denominator:
numer = 6 * num_sqrs - n * (n+1) * (2*n+1)
denom = 3 * n * (n+1)
Solving this:
num_sqrs > (n * (n+1) * (n+2)) / 3
Thus, the (cube root of n) / 3 is a convenient upper bound for our loop limits.
This gives us a simple iteration loop in the code:
def dims(num_sqrs):
dim = [(1, num_sqrs)]
limit = ceil((3*num_sqrs)**(1.0/3.0))
for n in range(2, limit):
numer = 6 * num_sqrs - n * (n+1) * (2*n+1)
denom = 3 * n * (n+1)
if numer % denom == 0:
t = numer // denom
if t >= 0:
dim.append((n, n+t))
return dim
Output for a couple of test cases:
>>> print(dims(8))
[(1, 8), (2, 3)]
>>> print(dims(2000))
[(1, 2000), (2, 667), (3, 334), (4, 201)]
>>> print(dims(1000000))
[(1, 1000000), (4, 100001), (5, 66668), (15, 8338), (24, 3341)]
>>> print(dims(21493600))
[(1, 21493600), (4, 2149361), (5, 1432908), (15, 179118), (24, 71653), (400, 401)]
These return immediately, so I expect that this solution is fast enough for OP's purposes.
It's quite possible that a parameterized equation would give us direct solutions, rather than iterating through possibilities. I'll leave that for the Project Euler folks. :-)
This uses the formula derived in the link provided by the OP. The only real optimization is trying not to look at dimensions that cannot produce the result. Pre-loading the results with the two end cases (figures = [(1,n_squares),(n_squares,1)]) saved a lot with big numbers. I think there are others chunks that can be discarded but I haven't figured them out yet.
def h(n_squares):
# easiest case for a n x m figure:
# n = 1 and m = n_squares
figures = [(1,n_squares),(n_squares,1)]
for n in range(2, n_squares+1):
for m in range(n, n_squares+1):
t = m - n
x = int((n * (n + 1) / 6) * ((2 * n) + (3 * t) + 1))
if x > n_squares:
break
if x == n_squares:
figures.extend([(n,m),(m,n)])
#print(f'{n:>6} x {m:<6} has {n_squares} squares')
if x > n_squares and n == m:
break
return figures
It also doesn't make lots of lists which can blow up your computer with really big numbers like 21493600 (400x401).
Formula derivation from link in OP's comment (in case that resource disappears):
text from Link
courtesy:
Doctor Anthony, The Math Forum
Link
If we have an 8 x 9 board the numbers of squares are as follows:
Size of Square Number of Squares
-------------- -----------------
1 x 1 8 x 9 = 72
2 x 2 7 x 8 = 56
3 x 3 6 x 7 = 42
4 x 4 5 x 6 = 30
5 x 5 4 x 5 = 20
6 x 6 3 x 4 = 12
7 x 7 2 x 3 = 6
8 x 8 1 x 2 = 2
----------------------------------------
Total = 240
For the general case of an n x m board, where m = n + t
We require
n n
SUM[r(r + t)] = SUM[r^2 + rt}
r=1 r=1
= n(n + 1)(2n + 1)/6 + tn(n + 1)/2
= [n(n + 1)/6]*[2n + 1 + 3t]
No. of squares =
[n(n + 1)/6]*[2n + 3t + 1] .......(1)
In the example above t = 1 and so
No. of squares = 8 x 9/6[16 + 3 + 1]
= (72/6)[20]
= 240 (as required)
The general formula for an (n x n+t) board is that given in (1)
above.
No. of squares = [n(n + 1)/6]*[2n + 3t + 1]

Strange behaviour of simple pycuda kernel

I'm quite new to cuda and pycuda.
I need a kernel that creates a matrix (of dimension n x d) out of an array (1 x d), by simply "repeating" the same array n times:
for example, suppose we have n = 4 and d = 3, then if the array is [1 2 3]
the result of my kernel should be:
[1 2 3
1 2 3
1 2 3
1 2 3]
(a matrix 4x3).
Basically, it's the same as doing numpy.tile(array, (n, 1))
I've written the code below:
kernel_code_template = """
__global__ void TileKernel(float *in, float *out)
{
// Each thread computes one element of out
int y = blockIdx.y * blockDim.y + threadIdx.y;
int x = blockIdx.x * blockDim.x + threadIdx.x;
if (y > %(n)s || x > %(d)s) return;
out[y * %(d)s + x] = in[x];
}
"""
d = 64
n = 512
blockSizex = 16
blockSizey = 16
gridSizex = (d + blockSizex - 1) / blockSizex
gridSizey = (n + blockSizey - 1) / blockSizey
# get the kernel code from the template
kernel_code = kernel_code_template % {
'd': d,
'n': n
}
mod = SourceModule(kernel_code)
TileKernel = mod.get_function("TileKernel")
vec_cpu = np.arange(d).astype(np.float32) # just as an example
vec_gpu = gpuarray.to_gpu(vec_cpu)
out_gpu = gpuarray.empty((n, d), np.float32)
TileKernel.prepare("PP")
TileKernel.prepared_call((gridSizex, gridSizey), (blockSizex, blockSizey, 1), vec_gpu.gpudata, out_gpu.gpudata)
out_cpu = out_gpu.get()
Now, if I run this code with d equals a power of 2 >= 16 I get the right result (just like numpy.tile(vec_cpu, (n, 1)) );
but if I set d equals to anything else (let's say for example 88) I get that every element of the output matrix has the
correct value, except the first column: some entries are right but others have another value, apparently random, same for every wrong element, but different every run,
and also the entries of the first column that have the wrong value are different every run.
Example:
[0 1 2
0 1 2
6 1 2
0 1 2
6 1 2
...]
I really can't figure out what is causing this problem, but maybe it's just something simple that I'm missing...
Any help will be appreciated, thanks in advance!
The bounds checking within your kernel code is incorrect. This
if (y > n || x > d) return;
out[y * d + x] = in[x];
should be:
if (y >= n || x >= d) return;
out[y * d + x] = in[x];
or better still:
if ((y < n) && (x < d))
out[y * d + x] = in[x];
All array valid indexing in the array lies on 0 < x < d and 0 < y < n. By allowing x=d you have undefined behaviour, allowing the first entry in the next row of the output array to be overwritten with an unknown value. This explains why sometimes the results were correct and other times not.

Python: Finding random k-subset partition for a given list

The following code generates all partitions of length k (k-subset partitions) for a given list.
the algorithm could be found in this topic.
def algorithm_u(ns, m):
def visit(n, a):
ps = [[] for i in xrange(m)]
for j in xrange(n):
ps[a[j + 1]].append(ns[j])
return ps
def f(mu, nu, sigma, n, a):
if mu == 2:
yield visit(n, a)
else:
for v in f(mu - 1, nu - 1, (mu + sigma) % 2, n, a):
yield v
if nu == mu + 1:
a[mu] = mu - 1
yield visit(n, a)
while a[nu] > 0:
a[nu] = a[nu] - 1
yield visit(n, a)
elif nu > mu + 1:
if (mu + sigma) % 2 == 1:
a[nu - 1] = mu - 1
else:
a[mu] = mu - 1
if (a[nu] + sigma) % 2 == 1:
for v in b(mu, nu - 1, 0, n, a):
yield v
else:
for v in f(mu, nu - 1, 0, n, a):
yield v
while a[nu] > 0:
a[nu] = a[nu] - 1
if (a[nu] + sigma) % 2 == 1:
for v in b(mu, nu - 1, 0, n, a):
yield v
else:
for v in f(mu, nu - 1, 0, n, a):
yield v
def b(mu, nu, sigma, n, a):
if nu == mu + 1:
while a[nu] < mu - 1:
yield visit(n, a)
a[nu] = a[nu] + 1
yield visit(n, a)
a[mu] = 0
elif nu > mu + 1:
if (a[nu] + sigma) % 2 == 1:
for v in f(mu, nu - 1, 0, n, a):
yield v
else:
for v in b(mu, nu - 1, 0, n, a):
yield v
while a[nu] < mu - 1:
a[nu] = a[nu] + 1
if (a[nu] + sigma) % 2 == 1:
for v in f(mu, nu - 1, 0, n, a):
yield v
else:
for v in b(mu, nu - 1, 0, n, a):
yield v
if (mu + sigma) % 2 == 1:
a[nu - 1] = 0
else:
a[mu] = 0
if mu == 2:
yield visit(n, a)
else:
for v in b(mu - 1, nu - 1, (mu + sigma) % 2, n, a):
yield v
n = len(ns)
a = [0] * (n + 1)
for j in xrange(1, m + 1):
a[n - m + j] = j - 1
return f(m, n, 0, n, a)
we know that number of k-subsets of a given list is equal to Stirling number and it could be very big for some large lists.
the code above returns a Python generator that could generate all possible k-subset partitions for the given list with calling its next method. accordingly, if I want to get only one of these partitions randomly, I have to either call next method for some random times (which makes it really slow if the Stirling number is big) or use the itertools.islice method to get a slice of size one which is really slow as before.
I'm trying to avoid listing all partitions because it would be waste of time and speed and even memory (because calculations are a lot and memory is important in my case).
the question is how can I generate only one of k-subset partitions without generating the rest ? or at least make the procedure very faster than what explained above. I need the performance because I need to get only one of them each time and I'm running the application for maybe more than ten million times.
I'd appreciate any help.
EDIT: EXAMPLE
list : { 1, 2, 3 }
for k = 3:
{ {1}, {2}, {3} }
for k = 2:
{ {1, 2}, {3} }
{ {1, 3}, {2} }
{ {1}, {2, 3} }
and for k = 1:
{ {1, 2, 3} }
consider k = 2, is there any way I can generate only one of these 3 partitions randomly, without generating the other 2? note that I want to generate random partition for any given k not only a random partition of any k which means if I set the k to 2 I would like to generate only one of these 3 not one of all 5.
Regards,
Mohammad
You can count Stirling numbers efficiently with a recursive algorithm by storing previously computed values:
fact=[1]
def nCr(n,k):
"""Return number of ways of choosing k elements from n"""
while len(fact)<=n:
fact.append(fact[-1]*len(fact))
return fact[n]/(fact[k]*fact[n-k])
cache = {}
def count_part(n,k):
"""Return number of ways of partitioning n items into k non-empty subsets"""
if k==1:
return 1
key = n,k
if key in cache:
return cache[key]
# The first element goes into the next partition
# We can have up to y additional elements from the n-1 remaining
# There will be n-1-y left over to partition into k-1 non-empty subsets
# so n-1-y>=k-1
# y<=n-k
t = 0
for y in range(0,n-k+1):
t += count_part(n-1-y,k-1) * nCr(n-1,y)
cache[key] = t
return t
Once you know how many choices there are, you can adapt this recursive code to generate a particular partition:
def ith_subset(A,k,i):
"""Return ith k-subset of A"""
# Choose first element x
n = len(A)
if n==k:
return A
if k==0:
return []
for x in range(n):
# Find how many cases are possible with the first element being x
# There will be n-x-1 left over, from which we choose k-1
extra = nCr(n-x-1,k-1)
if i<extra:
break
i -= extra
return [A[x]] + ith_subset(A[x+1:],k-1,i)
def gen_part(A,k,i):
"""Return i^th k-partition of elements in A (zero-indexed) as list of lists"""
if k==1:
return [A]
n=len(A)
# First find appropriate value for y - the extra amount in this subset
for y in range(0,n-k+1):
extra = count_part(n-1-y,k-1) * nCr(n-1,y)
if i<extra:
break
i -= extra
# We count through the subsets, and for each subset we count through the partitions
# Split i into a count for subsets and a count for the remaining partitions
count_partition,count_subset = divmod(i,nCr(n-1,y))
# Now find the i^th appropriate subset
subset = [A[0]] + ith_subset(A[1:],y,count_subset)
S=set(subset)
return [subset] + gen_part([a for a in A if a not in S],k-1,count_partition)
As an example, I've written a test program that produces different partitions of 4 numbers:
def test(A):
n=len(A)
for k in [1,2,3,4]:
t = count_part(n,k)
print k,t
for i in range(t):
print " ",i,gen_part(A,k,i)
test([1,2,3,4])
This code prints:
1 1
0 [[1, 2, 3, 4]]
2 7
0 [[1], [2, 3, 4]]
1 [[1, 2], [3, 4]]
2 [[1, 3], [2, 4]]
3 [[1, 4], [2, 3]]
4 [[1, 2, 3], [4]]
5 [[1, 2, 4], [3]]
6 [[1, 3, 4], [2]]
3 6
0 [[1], [2], [3, 4]]
1 [[1], [2, 3], [4]]
2 [[1], [2, 4], [3]]
3 [[1, 2], [3], [4]]
4 [[1, 3], [2], [4]]
5 [[1, 4], [2], [3]]
4 1
0 [[1], [2], [3], [4]]
As another example, there are 10 million partitions of 1,2,3,..14 into 4 parts.
This code can generate all partitions in 44 seconds with pypy.
There are 50,369,882,873,307,917,364,901 partitions of 1,2,3,...,40 into 4 parts. This code can generate 10 million of these in 120 seconds with pypy running on a single processor.
To tie things together, you can use this code to generate a single random partition of a list A into k non-empty subsets:
import random
def random_ksubset(A,k):
i = random.randrange(0,count_part(len(A),k))
return gen_part(A,k,i)
tl;dr:
The k-subset partitions for a given n and k can be divided into types, based on which elements are the first to go into as yet empty parts. Each of these types is represented by a bit pattern with n-1 bits of which k-1 are set. While the number of partitions is huge (given by the second Stirling number), the number of types is much smaller, e.g.:
n = 21, k = 8
number of partitions: S(21,8) = 132,511,015,347,084
number of types: (n-1 choose k-1) = 77,520
Calculating how many partitions there are of each type is simple, based on the position of the zeros in the bit pattern. If you make a list of all the types (by iterating over all n:k bit patterns) and keep a running total of the number of partitions, you can then use a binary search on this list to find the type of the partition with a given rank (in Log2(n-1 choose k-1) steps; 17 for the example above), and then translate the bit pattern into a partition and calculate into which part each element goes (in n steps). Every part of this method can be done iteratively, requiring no recursion.
Here's a non-recursive solution. I've tried to roll my own, but it may (partially) overlap with Peter's answer or existing methods.
If you have a set of n elements, e.g. with n=8:
{a,b,c,d,e,f,g,h}
then k-subset partitions will take this shape, e.g. with k=5:
{a,e} {b,c,h} {d} {f} {g}
This partition can also be written as:
1,2,2,3,1,4,5,2
which lists which part each of the elements goes in. So this sequence of n digits with values from 1 to k represents a k-subset partition of n elements.
However, not all such sequences are valid partitions; every digit from 1 to k must be present, otherwise there would be empty parts:
1,2,2,3,1,3,5,2 → {a,e} {b,c,h} {d,f} {} {g}
Also, to avoid duplicates, digit x can only be used after digit x-1 has been used. So the first digit is always 1, the second can be at most 2, and so on. If in the example we use digits 4 and 5 before 3, we get duplicate partitions:
1,2,2,3,1,4,5,2 → {a,e} {b,c,h} {d} {f} {g}
1,2,2,4,1,5,3,2 → {a,e} {b,c,h} {g} {d} {f}
When you group the partitions based on when each part is first used, you get these types:
1,1,1,1,2,3,4,5 0001111 11111111 1 1
1,1,1,2,12,3,4,5 0010111 11112111 2 2
1,1,1,2,3,123,4,5 0011011 11111311 3 3
1,1,1,2,3,4,1234,5 0011101 11111141 4 4
1,1,1,2,3,4,5,12345 0011110 11111115 5 5
1,1,2,12,12,3,4,5 0100111 11122111 2*2 4
1,1,2,12,3,123,4,5 0101011 11121311 2*3 6
1,1,2,12,3,4,1234,5 0101101 11121141 2*4 8
1,1,2,12,3,4,5,12345 0101110 11121115 2*5 10
1,1,2,3,123,123,4,5 0110011 11113311 3*3 9
1,1,2,3,123,4,1234,5 0110101 11113141 3*4 12
1,1,2,3,123,4,5,12345 0110110 11113115 3*5 15
1,1,2,3,4,1234,1234,5 0111001 11111441 4*4 16
1,1,2,3,4,1234,5,12345 0111010 11111415 4*5 20
1,1,2,3,4,5,12345,12345 0111100 11111155 5*5 25
1,2,12,12,12,3,4,5 1000111 11222111 2*2*2 8
1,2,12,12,3,123,4,5 1001011 11221311 2*2*3 12
1,2,12,12,3,4,1234,5 1001101 11221141 2*2*4 16
1,2,12,12,3,4,5,12345 1001110 11221115 2*2*5 20
1,2,12,3,123,123,4,5 1010011 11213311 2*3*3 18
1,2,12,3,123,4,1234,5 1010101 11213141 2*3*4 24
1,2,12,3,123,4,5,12345 1010110 11213115 2*3*5 30
1,2,12,3,4,1234,1234,5 1011001 11211441 2*4*4 32
1,2,12,3,4,1234,5,12345 1011010 11211415 2*4*5 40
1,2,12,3,4,5,12345,12345 1011100 11211155 2*5*5 50
1,2,3,123,123,123,4,5 1100011 11133311 3*3*3 27
1,2,3,123,123,4,1234,5 1100101 11133141 3*3*4 36
1,2,3,123,123,4,5,12345 1100110 11133115 3*3*5 45
1,2,3,123,4,1234,1234,5 1101001 11131441 3*4*4 48
1,2,3,123,4,1234,5,12345 1101010 11131415 3*4*5 60
1,2,3,123,4,5,12345,12345 1101100 11131155 3*5*5 75
1,2,3,4,1234,1234,1234,5 1110001 11114441 4*4*4 64
1,2,3,4,1234,1234,5,12345 1110010 11114415 4*4*5 80
1,2,3,4,1234,5,12345,12345 1110100 11114155 4*5*5 100
1,2,3,4,5,12345,12345,12345 1111000 11111555 5*5*5 125 SUM = 1050
In the above diagram, a partition of the type:
1,2,12,3,123,4,1234,5
means that:
a goes into part 1
b goes into part 2
c goes into part 1 or 2
d goes into part 3
e goes into part 1, 2 or 3
f goes into part 4
g goes into part 1, 2, 3 or 4
h goes into part 5
So partitions of this type have a digit that can have 2 values, a digit that can have 3 values, and a digit that can have 4 values (this is indicated in the third column in the diagram above). So there are a total of 2 × 3 × 4 partitions of this type (as indicated in columns 4 and 5). The sum of these is of course the Stirling number: S(8,5) = 1050.
The second column in the diagram is another way of notating the type of the partition: after starting with 1, every digit is either a digit that has been used before, or a step up (i.e. the highest digit used so far + 1). If we represent these two options by 0 and 1, we get e.g.:
1,2,12,3,123,4,1234,5 → 1010101
where 1010101 means:
Start with 1
1 → step up to 2
0 → repeat 1 or 2
1 → step up to 3
0 → repeat 1, 2 or 3
1 → step up to 4
0 → repeat 1, 2, 3 or 4
1 → step up to 5
So every binary sequence with n-1 digits and k-1 ones represents a type of partition. We can calculate the number of partitions of a type by iterating over the digits from left to right, incrementing a factor when we find a one, and multiplying with the factor when we find a zero, e.g.:
1,2,12,3,123,4,1234,5 → 1010101
Start with product = 1, factor = 1
1 → increment factor: 2
0 → product × factor = 2
1 → increment factor: 3
0 → product × factor = 6
1 → increment factor: 4
0 → product × factor = 24
1 → increment factor: 5
And again for this example, we find that there are 24 partitions of this type. So, counting the partitions of each type can be done by iterating over all n-1-digit integers with k-1 digits set, using any method (e.g. Gosper's Hack):
0001111 1 1
0010111 2 3
0011011 3 6
0011101 4 10
0011110 5 15
0100111 4 19
0101011 6 25
0101101 8 33
0101110 10 43
0110011 9 52
0110101 12 64
0110110 15 79
0111001 16 95
0111010 20 115
0111100 25 140
1000111 8 148
1001011 12 160
1001101 16 176
1001110 20 196
1010011 18 214
1010101 24 238
1010110 30 268
1011001 32 300
1011010 40 340
1011100 50 390
1100011 27 417
1100101 36 453
1100110 45 498
1101001 48 546
1101010 60 606
1101100 75 681
1110001 64 745
1110010 80 825
1110100 100 925
1111000 125 1050
Finding a random partition then means choosing a number from 1 to S(n,k), going over the counts per partition type while keeping a running total (column 3 above), and picking the corresponding partition type, and then calculating the value of the repeated digits, e.g.:
S(8,5) = 1050
random pick: e.g. 333
type: 1011010 → 1,2,12,3,4,1234,5,12345
range: 301 - 340
variation: 333 - 301 = 32
digit options: 2, 4, 5
digit values: 20, 5, 1
variation: 32 = 1 × 20 + 2 × 5 + 2 × 1
digits: 1, 2, 2 (0-based) → 2, 3, 3 (1-based)
partition: 1,2,2,3,4,3,5,3
and the 333rd partition of 8 elements in 5 parts is:
1,2,2,3,4,3,5,3 → {a} {b,c} {d,f,h} {e} {g}
There are a number of options to turn this into code; if you store the n-1-digit numbers as a running total, you can do subsequent lookups using a binary search over the list, whose length is C(n-1,k-1), to reduce time complexity from O(C(n-1,k-1)) to O(Log2(C(n-1,k-1))).
I've made a first test in JavaScript (sorry, I don't speak Python); it's not pretty but it demonstrates the method and is quite fast. The example is for the case n=21 and k=8; it creates the count table for 77,520 types of partitions, returns the total number of partitions 132,511,015,347,084 and then retrieves 10 randomly picked partitions within that range. On my computer this code returns a million randomly selected partitions in 3.7 seconds. (note: the code is zero-based, unlike the explanation above)
function kSubsetPartitions(n, k) { // Constructor
this.types = [];
this.count = [];
this.total = 0;
this.elems = n;
var bits = (1 << k - 1) - 1, done = 1 << n - 1;
do {
this.total += variations(bits);
this.types.push(bits);
this.count.push(this.total);
}
while (!((bits = next(bits)) & done));
function variations(bits) {
var product = 1, factor = 1, mask = 1 << n - 2;
while (mask) {
if (bits & mask) ++factor;
else product *= factor;
mask >>= 1;
}
return product;
}
function next(a) { // Gosper's Hack
var c = (a & -a), r = a + c;
return (((r ^ a) >> 2) / c) | r;
}
}
kSubsetPartitions.prototype.partition = function(rank) {
var range = 1, type = binarySearch(this.count, rank);
if (type) {
rank -= this.count[type - 1];
range = this.count[type] - this.count[type - 1];
}
return translate(this.types[type], this.elems, range, rank);
// This translates the bit pattern format and creates the correct partition
// for the given rank, using a letter format for demonstration purposes
function translate(bits, len, range, rank) {
var partition = [["A"]], part, max = 0, mask = 1 << len - 2;
for (var i = 1; i < len; i++, mask >>= 1) {
if (!(bits & mask)) {
range /= (max + 1);
part = Math.floor(rank / range);
rank %= range;
}
else part = ++max;
if (!partition[part]) partition[part] = "";
partition[part] += String.fromCharCode(65 + i);
}
return partition.join(" / ");
}
function binarySearch(array, value) {
var low = 0, mid, high = array.length - 1;
while (high - low > 1) {
mid = Math.ceil((high + low) / 2);
if (value < array[mid]) high = mid;
else low = mid;
}
return value < array[low] ? low : high;
}
}
var ksp = new kSubsetPartitions(21, 8);
document.write("Number of k-subset partitions for n,k = 21,8 → " +
ksp.total.toLocaleString("en-US") + "<br>");
for (var tests = 10; tests; tests--) {
var rnd = Math.floor(Math.random() * ksp.total);
document.write("Partition " + rnd.toLocaleString("en-US", {minimumIntegerDigits:
15}) + " → " + ksp.partition(rnd) + "<br>");
}
It isn't really necessary to store the bit patterns for each partition type, because they can be recreated from their index (see e.g. the second algorithm in this answer). If you only store the running total of the number of variations per partition type, that halves the memory requirement.
This second code example in C++ stores only the counts, and returns the partition as an n-length array containing the part number for each element. Usage example at the end of the code. On my computer it creates the count list for n=40 and k=32 in 12 seconds and then returns 10 million partitions in 24 seconds.
Values of n can go up to 65 and k up to 64, but for some combinations the number of partitions will be greater than 264, which this code obviously can't handle. If you translate it into Python, there should be no such restrictions. (Note: enable zero check in binomial coefficient function if k=1.)
class kSubsetPartitions {
std::vector <uint64_t> count;
uint64_t total;
uint8_t n;
uint8_t k;
public:
kSubsetPartitions(uint8_t n, uint8_t k) {
this->total = 0;
this->n = n;
this->k = k;
uint64_t bits = ((uint64_t) 1 << k - 1) - 1;
uint64_t types = choose(n - 1, k - 1);
this->count.reserve(types);
while (types--) {
this->total += variations(bits);
this->count.push_back(this->total);
bits = next(bits);
}
}
uint64_t range() {
return this->total;
}
void partition(uint64_t rank, uint8_t *buffer) {
uint64_t range = 1;
uint64_t type = binarySearch(rank);
if (type) {
rank -= this->count[type - 1];
range = this->count[type] - this->count[type - 1];
}
format(pattern(type), range, rank, buffer);
}
private:
uint64_t pattern(uint64_t type) {
uint64_t steps, bits = 0, mask = (uint64_t) 1 << this->n - 2;
uint8_t ones = this->k - 1;
for (uint8_t i = this->n - 1; i; i--, mask >>= 1) {
if (i > ones) {
steps = choose(i - 1, ones);
if (type >= steps) {
type -= steps;
bits |= mask;
--ones;
}
}
else bits |= mask;
}
return bits;
}
uint64_t choose(uint8_t x, uint8_t y) { // C(x,y) using Pascal's Triangle
static std::vector <std::vector <uint64_t> > triangle;
if (triangle.empty()) {
triangle.resize(this->n);
triangle[0].push_back(1);
for (uint8_t i = 1; i < this->n; i++) {
triangle[i].push_back(1);
for (uint8_t j = 1; j < i; j++) {
triangle[i].push_back(triangle[i - 1][j - 1] + triangle[i - 1][j]);
}
triangle[i].push_back(1);
}
}
return triangle[x][y];
}
void format(uint64_t bits, uint64_t range, uint64_t rank, uint8_t *buffer) {
uint64_t mask = (uint64_t) 1 << this->n - 2;
uint8_t max = 0, part;
*buffer = 0;
while (mask) {
if (!(bits & mask)) {
range /= (max + 1);
part = rank / range;
rank %= range;
}
else part = ++max;
*(++buffer) = part;
mask >>= 1;
}
}
uint64_t binarySearch(uint64_t rank) {
uint64_t low = 0, mid, high = this->count.size() - 1;
while (high - low > 1) {
mid = (high + low + 1) / 2;
if (rank < this->count[mid]) high = mid;
else low = mid;
}
return rank < this->count[low] ? low : high;
}
uint64_t variations(uint64_t bits) {
uint64_t product = 1;
uint64_t mask = (uint64_t) 1 << this->n - 2;
uint8_t factor = 1;
while (mask) {
if (bits & mask) ++factor;
else product *= factor;
mask >>= 1;
}
return product;
}
uint64_t next(uint64_t a) { // Gosper's Hack
// if (!a) return a; // k=1 => a=0 => c=0 => division by zero!
uint64_t c = (a & -a), r = a + c;
return (((r ^ a) >> 2) / c) | r;
}
};
// USAGE EXAMPLE:
// uint8_t buffer[40];
// kSubsetPartitions* ksp = new kSubsetPartitions(40, 32);
// uint64_t range = ksp->range();
// ksp->partition(any_integer_below_range, buffer);
Below is an overview of the values of n and k that result in more than 264 partitions, and cause overflow in the code above. Up to n=26, all values of k give valid results.
25: - 26: - 27: 8-13 28: 7-15 29: 6-17 30: 6-18 31: 5-20 32: 5-21
33: 5-22 34: 4-23 35: 4-25 36: 4-26 37: 4-27 38: 4-28 39: 4-29 40: 4-31
41: 4-32 42: 4-33 43: 3-34 44: 3-35 45: 3-36 46: 3-37 47: 3-38 48: 3-39
49: 3-40 50: 3-42 51: 3-43 52: 3-44 53: 3-45 54: 3-46 55: 3-47 56: 3-48
57: 3-49 58: 3-50 59: 3-51 60: 3-52 61: 3-53 62: 3-54 63: 3-55 64: 3-56
65: 3-57
A version which doesn't store the number of partitions per type is possible, and would require almost no memory. Looking up the partitions that correspond to randomly selected integers would be slower, but if the selection of integers was sorted, it could be even faster than the version which requires binary sort for every lookup.
You'd start with the first bit pattern, calculate the number of partitions of this type, see if the first integer(s) fall into this range, calculate their partitions, and then move on to the next bit pattern.
How about something like this:
import itertools
import random
def random_ksubset(ls, k):
# we need to know the length of ls, so convert it into a list
ls = list(ls)
# sanity check
if k < 1 or k > len(ls):
return []
# Create a list of length ls, where each element is the index of
# the subset that the corresponding member of ls will be assigned
# to.
#
# We require that this list contains k different values, so we
# start by adding each possible different value.
indices = list(range(k))
# now we add random values from range(k) to indices to fill it up
# to the length of ls
indices.extend([random.choice(list(range(k))) for _ in range(len(ls) - k)])
# shuffle the indices into a random order
random.shuffle(indices)
# construct and return the random subset: sort the elements by
# which subset they will be assigned to, and group them into sets
return [{x[1] for x in xs} for (_, xs) in
itertools.groupby(sorted(zip(indices, ls)), lambda x: x[0])]
This produces random k-subset partitions like so:
>>> ls = {1,2,3}
>>> print(random_ksubset(ls, 2))
[set([1, 2]), set([3])]
>>> print(random_ksubset(ls, 2))
[set([1, 3]), set([2])]
>>> print(random_ksubset(ls, 2))
[set([1]), set([2, 3])]
>>> print(random_ksubset(ls, 2))
[set([1]), set([2, 3])]
This method satisfies OP's requirement of getting one randomly-generated partition, without enumerating all possible partitions. Memory complexity here is linear. Run-time complexity is O(N log N) due to the sort. I suppose it might be possible to get this down to linear, if that was important, using a more complicated method of constructing the return value.
As #Leon points out, this satisfies the requirements of his option 2 in trying to define the problem. What this won't do is deterministically generate partition #N (this is Leon's option 1, which would allow you to randomly pick an integer N and then retrieve the corresponding partition). Leon's clarification is important, because, to satisfy the spirit of the question, every possible partition of the collection should be generated with equal probability. On our toy problem, this is the case:
>>> from collections import Counter
>>> Counter(frozenset(map(frozenset, random_ksubset(ls, 2))) for _ in range(10000))
Counter({frozenset({frozenset({2, 3}), frozenset({1})}): 3392,
frozenset({frozenset({1, 3}), frozenset({2})}): 3212,
frozenset({frozenset({1, 2}), frozenset({3})}): 3396})
However. In general, this method does not generate each partition with equal probability. Consider:
>>> Counter(frozenset(map(frozenset, random_ksubset(range(4), 2)))
... for _ in range(10000)).most_common()
[(frozenset({frozenset({1, 3}), frozenset({0, 2})}), 1671),
(frozenset({frozenset({1, 2}), frozenset({0, 3})}), 1667),
(frozenset({frozenset({2, 3}), frozenset({0, 1})}), 1642),
(frozenset({frozenset({0, 2, 3}), frozenset({1})}), 1285),
(frozenset({frozenset({2}), frozenset({0, 1, 3})}), 1254),
(frozenset({frozenset({0, 1, 2}), frozenset({3})}), 1245),
(frozenset({frozenset({1, 2, 3}), frozenset({0})}), 1236)]
We can see here that we are more likely to generate "more balanced" partitions (because there are more ways to construct these). The partitions that contain singleton sets are produced less frequently.
It seems that an efficient uniform sampling method over k-partitions of sets is sort of an unsolved research question (also see mathoverflow). Nijenhuis and Wilf give code for sampling from all partitions (Chapter 12), which could work with rejection testing, and #PeterdeRivaz's answer can also uniformly sample a k-partition. The drawback with both of these methods is that they require computing the Stirling numbers, which grow exponentially in n, and the algorithms are recursive, which I think will make them slow on large inputs. As you mention "millions" of partitions in your comment, I think that these approaches will only be tractable up to a certain input size.
A. Nijenhuis and H. Wilf. Combinatorial Algorithms for Computers and
Calculators. Academic Press, Orlando FL, second edition, 1978.
Exploring Leon's option 1 might be interesting. Here's a rough procedure to deterministically produce a particular partition of a collection using #Amadan's suggestion of taking an integer value interpreted as a k-ary number. Note that not every integer value produces a valid k-subset partition (because we disallow empty subsets):
def amadan(ls, N, k):
"""
Given a collection `ls` with length `b`, a value `k`, and a
"partition number" `N` with 0 <= `N` < `k**b`, produce the Nth
k-subset paritition of `ls`.
"""
ls = list(ls)
b = len(ls)
if not 0 <= N < k**b: return None
# produce the k-ary index vector from the number N
index = []
# iterate through each of the subsets
for _ in range(b):
index.append(N % k)
N //= k
# subsets cannot be empty
if len(set(index)) != k: return None
return frozenset(frozenset(x[1] for x in xs) for (_, xs) in
itertools.groupby(sorted(zip(index, ls)),
lambda x:x[0]))
We can confirm that this generates the Stirling numbers properly:
>>> for i in [(4,1), (4,2), (4,3), (4,4), (5,1), (5,2), (5,3), (5,4), (5,5)]:
... b,k = i
... r = [amadan(range(b), N, k) for N in range(k**b)]
... r = [x for x in r if x is not None]
... print(i, len(set(r)))
(4, 1) 1
(4, 2) 7
(4, 3) 6
(4, 4) 1
(5, 1) 1
(5, 2) 15
(5, 3) 25
(5, 4) 10
(5, 5) 1
This may also be able to produce each possible partition with equal probability; I'm not quite sure. Here's a test case, where it works:
>>> b,k = 4,3
>>> r = [amadan(range(b), N, k) for N in range(k**b)]
>>> r = [x for x in r if x is not None]
>>> print(Counter([' '.join(sorted(''.join(map(str, x)) for x in p)) for p in r]))
Counter({'0 13 2': 6,
'01 2 3': 6,
'0 12 3': 6,
'03 1 2': 6,
'02 1 3': 6,
'0 1 23': 6})
Another working case:
>>> b,k = 5,4
>>> r = [amadan(range(b), N, k) for N in range(k**b)]
>>> r = [x for x in r if x is not None]
>>> print(Counter([' '.join(sorted(''.join(map(str, x)) for x in p)) for p in r]))
Counter({'0 12 3 4': 24,
'04 1 2 3': 24,
'0 1 23 4': 24,
'01 2 3 4': 24,
'03 1 2 4': 24,
'0 13 2 4': 24,
'0 1 24 3': 24,
'02 1 3 4': 24,
'0 1 2 34': 24,
'0 14 2 3': 24})
So, to wrap this up in a function:
def random_ksubset(ls, k):
ls = list(ls)
maxn = k**len(ls)-1
rv = None
while rv is None:
rv = amadan(ls, random.randint(0, maxn), k)
return rv
And then we can do:
>>> random_ksubset(range(3), 2)
frozenset({frozenset({2}), frozenset({0, 1})})
>>> random_ksubset(range(3), 2)
frozenset({frozenset({1, 2}), frozenset({0})})
>>> random_ksubset(range(3), 2)
frozenset({frozenset({1, 2}), frozenset({0})})
>>> random_ksubset(range(3), 2)
frozenset({frozenset({2}), frozenset({0, 1})})

Categories

Resources