Archive

Posts Tagged ‘Algorithmus’

Kombinatorik {n \choose k}: effiziente Berechnung der Varianten

April 14th, 2009 1 comment

Ich hatte schon früher das Problem einen Algorithmus zu finden um alle Varianten der Positionierung von k Elementen auf n Plätzen zu ermitteln (also {n \choose k} Möglichkeiten der Positionierung), besonders wenns um Speichereffizenz (nicht alle Kombination speichern) geht. Jupp hat mich heut wieder auf das Problem gestoßen und ich hab endlich eine “schöne” Lösung gefunden (es wird nicht viel benötigt, nur ein paar Schleifen und die Berechnung des Binomialkoeff.):

program iterkombi
	implicit none
	integer(kind=4), parameter :: n=6, k=2
	integer(kind=4) :: tmpN, tmpK, ind, pos, i, j
	integer(kind=4), dimension(1:n) :: arrayP
	character(len=15) :: str
 
	! schleife über Nr. der Kombination
	do j=1, binomial(n,k), 1
		ind = j
		tmpN = n; tmpK = k
		pos = 0; arrayP = 0
		! jedes der k Elemente positionieren
		do i=1, k, 1
			pos = pos + 1
			do while( ind - binomial(tmpN-1,tmpK-1) > 0 )
				ind = ind - binomial(tmpN-1,tmpK-1)
				tmpN = tmpN - 1
				pos = pos + 1
			end do
			tmpN = n - pos
			tmpK = tmpK - 1
			arrayP( pos ) = 1
		end do
		write(str,*) n
		write(unit=*,fmt='(A,I0,A,A,'//str//'I1)') "Belegungsarray (Nr. ", j, "): ", char(9), arrayP
	end do
 
	contains
 
	function binomial( n,k )
		integer(kind=4) :: binomial
		integer(kind=4) :: n, k, i, x, y
		x = 1; y = 1
		do i=k+1, n, 1
			x = x*i 	! n!/k!
		end do
		do i=2, n-k, 1
			y = y*i 	! (n-k)!
		end do
		binomial = x / y
	end function
end program

Ausgabe:

Belegungsarray (Nr. 1): 	110000
Belegungsarray (Nr. 2): 	101000
Belegungsarray (Nr. 3): 	100100
Belegungsarray (Nr. 4): 	100010
Belegungsarray (Nr. 5): 	100001
Belegungsarray (Nr. 6): 	011000
Belegungsarray (Nr. 7): 	010100
Belegungsarray (Nr. 8): 	010010
Belegungsarray (Nr. 9): 	010001
Belegungsarray (Nr. 10): 	001100
Belegungsarray (Nr. 11): 	001010
Belegungsarray (Nr. 12): 	001001
Belegungsarray (Nr. 13): 	000110
Belegungsarray (Nr. 14): 	000101
Belegungsarray (Nr. 15): 	000011

Der Vorteil: es kann jede Kombination einzeln berechnet werden ohne zu wissen wie die vorherige Kombination aussah.