5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

今週のアルゴリズム:最短経路の計算!(Java/Groovy/Scala/Fortran/Pascalでnext_permutation)

Last updated at Posted at 2013-12-25
Permutation Iterator next_permutation URL
C#/Go/Python/Ruby/VB まとめ含む http://qiita.com/cielavenir/items/ac96da5e3040c2edb78c
Boo/C#/Nemerle/VB http://qiita.com/cielavenir/items/0e07a024049017f7dea2
Java/Groovy/Scala/Fortran/Pascal http://qiita.com/cielavenir/items/4347fd0c6c69fa60804a
D/Go/JavaScript/Lua/R http://qiita.com/cielavenir/items/9e821d04f574a6623d03
Perl HSP/PHP/Python/Ruby http://qiita.com/cielavenir/items/006a878292c5be209231
Go2/Crystal/Kotlin/Nim/Julia http://qiita.com/cielavenir/items/74f8d547437154c14e72
V/Rust http://qiita.com/cielavenir/items/cec1812999547909a9e4
D/Nemerle/JavaScript/Perl6/PHP C/C++/Crystal/Go2/Julia
Kotlin/Nim/Perl/Perl6
(github参照)

Java
ジェネリクスの使い方で苦労してます…。

import java.util.*;
class Main{
	static <T> void reverse(List<T> a,int start,int size){
		int end=start+size-1;
		for(;start<end;start++){
			T z=a.get(start);a.set(start,a.get(end));a.set(end,z);
			end--;
		}
	}
	static <T extends Comparable<? super T>> boolean next_permutation(List<T> a,int n){
		if(n<0||a.size()<n)return false;
		int i;
		reverse(a,n,a.size()-n);
		for(i=a.size()-2;i>=0;i--)if(a.get(i).compareTo(a.get(i+1))<0)break;
		if(i<0){
			reverse(a,0,a.size());
			return false;
		}
		int k=i;
		for(i=a.size()-1;i>=k+1;i--)if(a.get(k).compareTo(a.get(i))<0)break;
		int l=i;
		T z=a.get(k);a.set(k,a.get(l));a.set(l,z);
		reverse(a,k+1,a.size()-(k+1));
		return true;
	}
	static <T extends Comparable<? super T>> boolean next_permutation(List<T> a){
		return next_permutation(a,a.size());
	}

	static final int N=6;
	public static void main(String[]z){
		int r=0,i;
		List<Integer>e0=new ArrayList<Integer>(),f0=new ArrayList<Integer>();
		for(i=0;i<N;i++){e0.add(0);f0.add(0);}
		for(i=0;i<N;i++){e0.add(1);f0.add(1);}
		int[] e=new int[N*2+1];
		int[] f=new int[N*2+1];
		do{
			for(i=0;i<N*2;i++)e[i+1]=e[i]+e0.get(i);
			do{
				for(i=0;i<N*2;i++){
					f[i+1]=f[i]+f0.get(i);
					if(e[i]==f[i]&&e[i+1]==f[i+1])break;
				}
				if(i==N*2)r++;
			}while(next_permutation(f0));
		}while(next_permutation(e0));
		System.out.println(r);
	}
}

Groovy
Enumeratorの概念がないだけでこんなに汚くなるのね…。
※精査したところ、1行目だけ#コメントが許容されるようですが、記述した場合シンタックスハイライトがうまく動かなくなるようです。なので、コードブロックからは削除しました。chmod +xしたい場合は1行目に
#!/usr/bin/env groovy
を別途入れて下さい。

def next_permutation(a,n=a.size){
	if(n<0||a.size<n)return false
	if(n<a.size)a[0..a.size()-1]=a[0..n-1]+a[n..-1].reverse()
	k=(a.size-2..0).find{a[it]<a[it+1]}
	if(k==null){
		a[0..a.size()-1]=a.reverse()
		return false
	}
	l=(a.size()-1..k+1).find{a[k]<a[it]}
	z=a[k];a[k]=a[l];a[l]=z
	a[0..a.size()-1]=a[0..k]+a[k+1..-1].reverse()
	return true
}

N=6
e0=([0]*N+[1]*N).sort()
f0=([0]*N+[1]*N).sort()
//各Pは経路を表す。1が縦、0が横を表す。
r=0
i=0
e=[0]*(N*2+1)
f=[0]*(N*2+1)
while(true){
	(N*2).times{e[it+1]=e[it]+e0[it]}
	//数学の座標系のように左下をA、右上をBとすると、eの各インデックスiにおいて、x座標がi-e[i]、y座標がe[i]となる。
	while(true){
		x=!(0..N*2-1).any{
			f[it+1]=f[it]+f0[it]
			//i番目の座標とi+1番目の座標が等しければ、「道に重複がある」とみなせる。
			e[it]==f[it] && e[it+1]==f[it+1]
		}
		if(x)r++
		if(!next_permutation(f0))break;
	}
	if(!next_permutation(e0))break
}
println r // 100360

Scala
chmod +xしたい場合は1行目に
#!/usr/bin/env scala
!#
を入れればよいですが、そうするとscalacでエラーになるので、コードブロックではやっておりません。

import scala.util.control.Breaks
object Main{
	def reverse[T](a: Array[T],start: Int,size: Int) = {
		val end=start+size-1
		for(i <- 0 to size/2-1){
			val z=a(start+i)
			a(start+i)=a(end-i)
			a(end-i)=z
		}
	}
	def next_permutation[T <% Ordered[T]](a: Array[T],n: Int): Boolean = {
		if(n<0||a.size<n)return false
		reverse(a,n,a.size-n)
		var k = -1
		val b = new Breaks
		b.breakable{
			for(i<-(a.size-2) to 0 by -1)if(a(i)<a(i+1)){k=i;b.break}
		}
		if(k<0){
			reverse(a,0,a.size)
			return false
		}
		var l = -1
		b.breakable{
			for(i<-a.size-1 to k+1 by -1)if(a(k).compare(a(i))<0){l=i;b.break}
		}
		val z=a(k);a(k)=a(l);a(l)=z
		reverse(a,k+1,a.size-(k+1))
		return true
	}
	def next_permutation[T <% Ordered[T]](a: Array[T]): Boolean = {
		return next_permutation(a,a.size)
	}
	def main(args: Array[String]) = {
		val N=6
		val b = new Breaks
		var r=0
		val e0=new Array[Int](N*2)
		val f0=new Array[Int](N*2)
		for(i<-Range(0,N)){e0(N+i)=1;f0(N+i)=1}
		val e=new Array[Int](N*2+1)
		val f=new Array[Int](N*2+1)
		do{
			for(i<-Range(0,N*2))e(i+1)=e(i)+e0(i)
			do{
				var x = 1
				b.breakable{
					for(i<-Range(0,N*2)){
						f(i+1)=f(i)+f0(i)
						if(e(i)==f(i)&&e(i+1)==f(i+1)){x=0;b.break}
					}
				}
				r+=x
			}while(next_permutation(f0))
		}while(next_permutation(e0))
		println(r);
	}
}

Fortran

implicit none
interface
subroutine reverse(a_,start_,size_)
	integer a_(*)
	integer start_,size_
end
logical function next_permutation(a_,n_)
	integer a_(:)
	integer n_
end
end interface
integer,parameter::N=6
integer r,i,x
integer e0(N*2)
integer f0(N*2)
integer e(N*2+1)
integer f(N*2+1)
do i=1,N
	e0(i)=0
	f0(i)=0
	e0(N+i)=1
	f0(N+i)=1
enddo
r=0
e(1)=0
f(1)=0
do while(.true.)
	do i=1,N*2
		e(i+1)=e(i)+e0(i)
	enddo
	do while(.true.)
		x=1
		do i=1,N*2
			f(i+1)=f(i)+f0(i)
			if((e(i).eq.f(i)).and.(e(i+1).eq.f(i+1))) then
				x=0
				exit
			endif
		enddo
		r=r+x
		if(.not.next_permutation(f0,size(f0))) exit
	enddo
	if(.not.next_permutation(e0,size(e0))) exit
enddo
write(*,"(i0)"),r
end

subroutine reverse(a_,start_,size_)
	integer a_(*)
	integer start_,size_
	integer end_,i_
	integer z_
	end_=start_+size_-1
	do i_=0,size_/2-1
		z_=a_(start_+i_)
		a_(start_+i_)=a_(end_-i_)
		a_(end_-i_)=z_
	end do
end

logical function next_permutation(a_,n_)
	integer a_(:)
	integer n_
	integer i_,k_,l_
	integer z_
	next_permutation=.false.
	if((0.le.n_).and.(n_.le.size(a_))) then
		call reverse(a_,n_,size(a_)+1-n_)
		i_=size(a_)-1
		do while(i_.ge.1)
			if(a_(i_).lt.a_(i_+1)) then
				exit
			endif
			i_=i_-1
		enddo
		if(i_.lt.1) then
			call reverse(a_,1,size(a_))
		else
			k_=i_
			i_=size(a_)
			do while(i_.ge.k_+1)
				if(a_(k_).lt.a_(i_)) then
					exit
				endif
				i_=i_-1
			enddo
			l_=i_;
			z_=a_(k_)
			a_(k_)=a_(l_)
			a_(l_)=z_
			call reverse(a_,k_+1,size(a_)+1-(k_+1))
			next_permutation=.true.
		endif
	endif
end

Pascal

{$apptype console} //Delphi6
program CodeIQRoute;
var
N:longint;
r:longint;
i:longint;
x:longint;
e0:array of longint;
f0:array of longint;
e:array of longint;
f:array of longint;

procedure reverse(var a:array of longint;start:longint;size:longint);
var
	en,i:longint;
	z:longint;
begin
	en:=start+size-1;
	for i:=0 to trunc(size/2-1) do begin
		z:=a[start+i];
		a[start+i]:=a[en-i];
		a[en-i]:=z;
	end;
end;

function next_permutation(var a:array of longint;n:longint):boolean;
var
	i,k,l:longint;
	z:longint;
begin
	next_permutation:=false;
	if (0<=n) and (n<=length(a)) then begin
		reverse(a,n,length(a)-n);
		i:=length(a)-2;
		while i>=0 do begin
			if a[i]<a[i+1] then break;
			i:=i-1;
		end;
		if i<0 then begin
			reverse(a,0,length(a));
		end else begin
			k:=i;
			i:=length(a)-1;
			while i>=k+1 do begin
				if a[k]<a[i] then break;
				i:=i-1;
			end;
			l:=i;
			z:=a[k];
			a[k]:=a[l];
			a[l]:=z;
			reverse(a,k+1,length(a)-(k+1));
			next_permutation:=true;
		end;
	end;
end;

begin
N:=6;
r:=0;
setlength(e0,N*2);
setlength(f0,N*2);
for i:=0 to N-1 do begin
	e0[N+i]:=1;
	f0[N+i]:=1;
end;
setlength(e,N*2+1);
setlength(f,N*2+1);
repeat
	for i:=0 to N*2-1 do e[i+1]:=e[i]+e0[i];
	repeat
		x:=1;
		for i:=0 to N*2-1 do begin
			f[i+1]:=f[i]+f0[i];
			if (e[i]=f[i]) and (e[i+1]=f[i+1]) then begin
				x:=0;
				break;
			end;
		end;
		r:=r+x;
	until not next_permutation(f0,length(f0));
until not next_permutation(e0,length(e0));
writeln(r);
end.
5
5
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?