這次換個簡單一點的語言:Fortran 95。
我很驚訝GFortran 4.7仍然預設是Fortran 77,所以副檔名若是.f或.for會錯, 要存成.f90或.f95才行。
Fortran是Column major語言,所以若要遞迴還需要宣告recursive,堆疊方式造成Fortran永遠處理遞迴會比C麻煩。再加上很遜的Format,我就用以前學的Fortran 77寫法完成 :P。
我很驚訝GFortran 4.7仍然預設是Fortran 77,所以副檔名若是.f或.for會錯, 要存成.f90或.f95才行。
Fortran是Column major語言,所以若要遞迴還需要宣告recursive,堆疊方式造成Fortran永遠處理遞迴會比C麻煩。再加上很遜的Format,我就用以前學的Fortran 77寫法完成 :P。
program Combinations
implicit none
integer, parameter :: all=5
integer, parameter :: want=2
integer :: currentrow
integer, dimension(:, :), pointer :: result
call comb(all, want)
contains
function factorial(n)
integer:: n, factorial, i
factorial = product((/(i, i=1, n)/))
end function
subroutine addlist(before, beforelength, left, leftlength)
integer, intent(in), dimension(0:)::before, left
integer, intent(in) :: beforelength, leftlength
integer ::i, j
do i = 0, beforelength-1
result(currentrow, i) = before(i)
end do
do j=0, leftlength-1
result(currentrow, i+j) = left(j)
end do
currentrow = currentrow + 1
end subroutine
subroutine comb(all, want)
integer, intent(in) ::all, want
integer :: resultno, i, j
integer, dimension(0) :: before
character (500) :: fmt
fmt = '(i0' // repeat (', 1x, i0', all - 1) // ')'
currentrow = 0
resultno = factorial(all)/ ((factorial(want)* factorial(all-want)))
allocate(result(resultno, all))
write(*, "(a4, i2, a4)") "共:", resultno, "筆"
call calc(before, 0, all, want)
write (*, *) 'currentrow=', currentrow, ' all=', all
do i=0, currentrow-1
write (*, fmt) (result(i, j), j=0, all-1)
end do
end subroutine
recursive subroutine calc(before, beforelength, all, want)
integer, dimension(0:) :: before
integer, intent(in) :: beforelength, all, want
integer :: i, leftlength
integer, dimension(0:all) :: strall, newbefore, left
if (want == 0) then
do i=1, all
strall(i) = 0
end do
call addList(before, beforelength, strall, all)
else if (all==want) then
do i=0, all-1
strall(i) = 1
end do
call addList(before, beforelength, strall, all)
else if(all == 1) then
leftlength = 1
select case(want)
case (0)
left(0)=0
case (1)
left(0)=1
end select
call addlist(before, beforelength, left, leftlength);
else
do i=0, beforelength-1
newbefore(i) = before(i)
end do
newbefore(i) = 0
call calc(newbefore, beforelength+1, all-1, want)
newbefore(i) = 1
call calc(newbefore, beforelength+1, all-1, want-1)
end if
end subroutine
end program main
留言