June 2018 Update

This commit is contained in:
Ingy döt Net 2018-06-22 20:57:24 +00:00
parent ba8067c3b7
commit 22f33d4004
5278 changed files with 84726 additions and 14379 deletions

View file

@ -1,41 +1,361 @@
program nptest
integer n,i,a
logical nextp
external nextp
parameter(n=4)
dimension a(n)
do i=1,n
a(i)=i
enddo
10 print *,(a(i),i=1,n)
if(nextp(n,a)) go to 10
end
program testing_permutation_algorithms
implicit none
integer :: nmax
integer, dimension(:),allocatable :: ida
logical :: mtc
logical :: even
integer :: i
integer(8) :: ic
integer :: clock_rate, clock_max, t1, t2
real(8) :: dt
integer :: pos_min, pos_max
!
!
! Beginning:
!
write(*,*) 'INPUT N:'
read *, nmax
write(*,*) 'N =', nmax
allocate ( ida(1:nmax) )
!
!
! (1) Starting:
!
do i = 1, nmax
ida(i) = i
enddo
!
ic = 0
call system_clock ( t1, clock_rate, clock_max )
!
mtc = .false.
!
do
call subnexper ( nmax, ida, mtc, even )
!
! 1) counting the number of permutatations
!
ic = ic + 1
!
! 2) writing out the result:
!
! do i = 1, nmax
! write (100,"(i3,',')",advance = "no") ida(i)
! enddo
! write(100,*)
!
! repeat if not being finished yet, otherwise exit.
!
if (mtc) then
cycle
else
exit
endif
!
enddo
!
call system_clock ( t2, clock_rate, clock_max )
dt = ( dble(t2) - dble(t1) )/ dble(clock_rate)
!
! Finishing (1)
!
write(*,*) "1) subnexper:"
write(*,*) 'Total permutations :', ic
write(*,*) 'Total time elapsed :', dt
!
!
! (2) Starting:
!
do i = 1, nmax
ida(i) = i
enddo
!
pos_min = 1
pos_max = nmax
!
ic = 0
call system_clock ( t1, clock_rate, clock_max )
!
call generate ( pos_min )
!
call system_clock ( t2, clock_rate, clock_max )
dt = ( dble(t2) - dble(t1) )/ dble(clock_rate)
!
! Finishing (2)
!
write(*,*) "2) generate:"
write(*,*) 'Total permutations :', ic
write(*,*) 'Total time elapsed :', dt
!
!
! (3) Starting:
!
do i = 1, nmax
ida(i) = i
enddo
!
ic = 0
call system_clock ( t1, clock_rate, clock_max )
!
i = 1
call perm ( i )
!
call system_clock ( t2, clock_rate, clock_max )
dt = ( dble(t2) - dble(t1) )/ dble(clock_rate)
!
! Finishing (3)
!
write(*,*) "3) perm:"
write(*,*) 'Total permutations :', ic
write(*,*) 'Total time elapsed :', dt
!
!
! (4) Starting:
!
do i = 1, nmax
ida(i) = i
enddo
!
ic = 0
call system_clock ( t1, clock_rate, clock_max )
!
do
!
! 1) counting the number of permutatations
!
ic = ic + 1
!
! 2) writing out the result:
!
! do i = 1, nmax
! write (100,"(i3,',')",advance = "no") ida(i)
! enddo
! write(100,*)
!
! repeat if not being finished yet, otherwise exit.
!
if ( nextp(nmax,ida) ) then
cycle
else
exit
endif
!
enddo
!
call system_clock ( t2, clock_rate, clock_max )
dt = ( dble(t2) - dble(t1) )/ dble(clock_rate)
!
! Finishing (4)
!
write(*,*) "4) nextp:"
write(*,*) 'Total permutations :', ic
write(*,*) 'Total time elapsed :', dt
!
!
! What's else?
! ...
!
!==
deallocate(ida)
!
stop
!==
contains
!==
! Modified version of SUBROUTINE NEXPER from the book of
! Albert Nijenhuis and Herbert S. Wilf, "Combinatorial
! Algorithms For Computers and Calculators", 2nd Ed, p.59.
!
subroutine subnexper ( n, a, mtc, even )
implicit none
integer,intent(in) :: n
integer,dimension(n),intent(inout) :: a
logical,intent(inout) :: mtc, even
!
! local varialbes:
!
integer,save :: nm3
integer :: ia, i, s, d, i1, l, j, m
!
if (mtc) goto 10
nm3 = n-3
do i = 1,n
a(i) = i
enddo
mtc = .true.
5 even = .true.
if ( n .eq. 1 ) goto 8
6 if ( a(n) .ne. 1 .or. a(1) .ne. 2+mod(n,2) ) return
if ( n .le. 3 ) goto 8
do i = 1,nm3
if( a(i+1) .ne. a(i)+1 ) return
enddo
8 mtc = .false.
function nextp(n,a)
integer n,a,i,j,k,t
logical nextp
dimension a(n)
i=n-1
10 if(a(i).lt.a(i+1)) go to 20
i=i-1
if(i.eq.0) go to 20
go to 10
20 j=i+1
k=n
30 t=a(j)
a(j)=a(k)
a(k)=t
j=j+1
k=k-1
if(j.lt.k) go to 30
j=i
if(j.ne.0) go to 40
nextp=.false.
return
40 j=j+1
if(a(j).lt.a(i)) go to 40
t=a(i)
a(i)=a(j)
a(j)=t
nextp=.true.
end
10 if ( n .eq. 1 ) goto 27
if( .not. even ) goto 20
ia = a(1)
a(1) = a(2)
a(2) = ia
even = .false.
goto 6
20 s = 0
do i1 = 2,n
ia = a(i1)
i = i1-1
d = 0
do j = 1,i
if ( a(j) .gt. ia ) d = d+1
enddo
s = d+s
if ( d .ne. i*mod(s,2) ) goto 35
enddo
27 a(1) = 0
goto 8
35 m = mod(s+1,2)*(n+1)
do j = 1,i
if(isign(1,a(j)-ia) .eq. isign(1,a(j)-m)) cycle
m = a(j)
l = j
enddo
a(l) = ia
a(i1) = m
even = .true.
return
end subroutine
!=====
!
! http://rosettacode.org/wiki/Permutations#Fortran
!
recursive subroutine generate (pos)
implicit none
integer,intent(in) :: pos
integer :: val
if (pos > pos_max) then
!
! 1) counting the number of permutatations
!
ic = ic + 1
!
! 2) writing out the result:
!
! write (*,*) permutation
!
else
do val = 1, nmax
if (.not. any (ida( : pos-1) == val)) then
ida(pos) = val
call generate (pos + 1)
endif
enddo
endif
end subroutine
!=====
!
! http://rosettacode.org/wiki/Permutations#Fortran
!
recursive subroutine perm (i)
implicit none
integer,intent(inout) :: i
!
integer :: j, t, ip1
!
if (i == nmax) then
!
! 1) couting the number of permutatations
!
ic = ic + 1
!
! 2) writing out the result:
!
! write (*,*) a
!
else
ip1 = i+1
do j = i, nmax
t = ida(i)
ida(i) = ida(j)
ida(j) = t
call perm ( ip1 )
t = ida(i)
ida(i) = ida(j)
ida(j) = t
enddo
endif
return
end subroutine
!=====
!
! http://rosettacode.org/wiki/Permutations#Fortran
!
function nextp ( n, a )
logical :: nextp
integer,intent(in) :: n
integer,dimension(n),intent(inout) :: a
!
! local variables:
!
integer i,j,k,t
!
i = n-1
10 if ( a(i) .lt. a(i+1) ) goto 20
i = i-1
if ( i .eq. 0 ) goto 20
goto 10
20 j = i+1
k = n
30 t = a(j)
a(j) = a(k)
a(k) = t
j = j+1
k = k-1
if ( j .lt. k ) goto 30
j = i
if (j .ne. 0 ) goto 40
!
nextp = .false.
!
return
!
40 j = j+1
if ( a(j) .lt. a(i) ) goto 40
t = a(i)
a(i) = a(j)
a(j) = t
!
nextp = .true.
!
return
end function
!=====
!
! What's else ?
! ...
!=====
end program

View file

@ -0,0 +1,41 @@
program nptest
integer n,i,a
logical nextp
external nextp
parameter(n=4)
dimension a(n)
do i=1,n
a(i)=i
enddo
10 print *,(a(i),i=1,n)
if(nextp(n,a)) go to 10
end
function nextp(n,a)
integer n,a,i,j,k,t
logical nextp
dimension a(n)
i=n-1
10 if(a(i).lt.a(i+1)) go to 20
i=i-1
if(i.eq.0) go to 20
go to 10
20 j=i+1
k=n
30 t=a(j)
a(j)=a(k)
a(k)=t
j=j+1
k=k-1
if(j.lt.k) go to 30
j=i
if(j.ne.0) go to 40
nextp=.false.
return
40 j=j+1
if(a(j).lt.a(i)) go to 40
t=a(i)
a(i)=a(j)
a(j)=t
nextp=.true.
end

View file

@ -1,3 +1,5 @@
using Combinatorics
term = "RCode"
i = 0
pcnt = factorial(length(term))

View file

@ -1,34 +1,40 @@
struct QuickPerm<T> {
pub fn permutations(size: usize) -> Permutations {
Permutations { idxs: (0..size).collect(), swaps: vec![0; size], i: 0 }
}
pub struct Permutations {
idxs: Vec<usize>,
elems: Vec<T>,
idx: usize,
swaps: Vec<usize>,
i: usize,
}
impl<T: Clone> QuickPerm<T> {
fn new(elems: Vec<T>) -> Self {
QuickPerm { idxs: (0..elems.len()+1).collect(), elems: elems, idx: 1 }
}
}
impl Iterator for Permutations {
type Item = Vec<usize>;
impl<T: Clone> Iterator for QuickPerm<T> {
type Item = Vec<T>;
fn next(&mut self) -> Option<Self::Item> {
if self.idx == self.elems.len() { return None; }
self.idxs[self.idx] -= 1;
let other = if self.idx % 2 == 1 { self.idxs[self.idx] } else { 0 };
self.elems.swap(self.idx, other);
self.idx = 1;
while self.idxs[self.idx] == 0 {
self.idxs[self.idx] = self.idx;
self.idx += 1;
if self.i > 0 {
loop {
if self.i >= self.swaps.len() { return None; }
if self.swaps[self.i] < self.i { break; }
self.swaps[self.i] = 0;
self.i += 1;
}
self.idxs.swap(self.i, (self.i & 1) * self.swaps[self.i]);
self.swaps[self.i] += 1;
}
Some(self.elems.clone())
self.i = 1;
Some(self.idxs.clone())
}
}
fn main() {
for perm in QuickPerm::new(vec![1,2,3]) {
println!("{:?}", perm);
}
let perms = permutations(3).collect::<Vec<_>>();
assert_eq!(perms, vec![
vec![0, 1, 2],
vec![1, 0, 2],
vec![2, 0, 1],
vec![0, 2, 1],
vec![1, 2, 0],
vec![2, 1, 0],
]);
}

View file

@ -1,4 +1,5 @@
use std::collections::VecDeque;
fn permute<T, F: Fn(&[T])>(used: &mut Vec<T>, unused: &mut VecDeque<T>, action: &F) {
if unused.is_empty() {
action(used);
@ -11,15 +12,7 @@ fn permute<T, F: Fn(&[T])>(used: &mut Vec<T>, unused: &mut VecDeque<T>, action:
}
}
// Same as the vec! macro, but for VecDeques as well
macro_rules! vec_deque {
($($item:expr),*) => {{
let mut deque = ::std::collections::VecDeque::new();
$(deque.push_back($item);)*
deque
}}
}
fn main() {
permute(&mut Vec::new(), &mut vec_deque![1,2,3], &|perm| println!("{:?}", perm));
let mut queue = (1..4).collect::<VecDeque<_>>();
permute(&mut Vec::new(), &mut queue, &|perm| println!("{:?}", perm));
}

View file

@ -0,0 +1,27 @@
ArrayedCollection extend [
permuteAndDo: aBlock
["Permute receiver in-place, and call aBlock.
Requires integer keys."
self permuteUpto: self size andDo: aBlock]
permuteUpto: n andDo: aBlock
[n = 0 ifTrue: [^aBlock value].
1 to: n do:
[:i |
self swap: i with: n.
self permuteUpto: n-1 andDo: aBlock.
self swap: i with: n]]
]
SequenceableCollection extend [
permutations
["Answer a ReadStream of permuted shallow copies of receiver."
| c |
c := MappedCollection
collection: self
map: self keys asArray.
^Generator on:
[:g |
c map permuteAndDo: [g yield: (c copyFrom: 1 to: c size)]]]

View file

@ -0,0 +1,2 @@
st> 'Abc' permutations contents
('bcA' 'cbA' 'cAb' 'Acb' 'bAc' 'Abc' )

View file

@ -22,23 +22,15 @@ void genperm() {
p = 1
do {
a[p++, .] = u
i = n
for (i = n; i > 1; i--) {
if (u[i-1] < u[i]) break
}
if (i > 1) {
j = i
k = n
while (j < k) {
s = u[j]
u[j] = u[k]
u[k] = s
j++
k--
}
while (j < k) u[(j++, k--)] = u[(k, j)]
s = u[i-1]
j = i
for (j = i; u[j] < s; j++) {
}
u[i-1] = u[j]