キーワード辞典
コップの果汁を入れ替える3つの方法

登録日 13/06/23   更新日 13/06/23


教科「情報」の教科書で、よくアルゴリズムの一例として使われる、 2つのコップの果汁の入れ替えを別のコップを介して行う表現、 あれって、イラストが、 何故同じ大きさのコップでは無いのだろうとか、 何故同じ果汁ではないのだろうとか、 以前からずぅっと漠然とした違和感を持っていたので、その話。



コップの果汁を入れ替える3つの方法

同じ大きさのコップ、A、B、が有る。 コップAには、500mlの、 コップBには、350mlの、同じオレンジジュースが入っている。 この2つのコップのジュースの量を入れ替え、 コップAには、350mlの、 コップBには、500mlの、オレンジジュースが入っている状態にしたい。 どうしたら良いだろうか。 コップには目盛りが付いている。


その1

もう一つ、同じ大きさのコップCを用意し、これを介して入れ替える。 すなわち、
(1). コップAのジュースをコップCへ移す。
(2). コップBのジュースをコップAへ移す。
(3). コップCのジュースをコップBへ移す。

プログラムの例。 intサイズのコップA、B、Cを用意する。
シンプル、判り易い、確実、な方法。
プログラムの場合は、 移動では無くて、複写なんですけどね。
// Swap_1.java		2013.6.23	by Ryn

public class Swap_1 {

	public static void main(String[] args) {

		int a = 500, b = 350, c;

		System.out.println("a = " + a + ", b = "+ b);

		c = a;			// ←(1)
		a = b;			// ←(2)
		b = c;			// ←(3)

		System.out.println("a = " + a + ", b = "+ b);
	}
}


その2

コップAからコップBへ150ml移す。 すなわち、
(1). コップAとコップBの差を求める。
(2). コップAから差の分のジュースを、
(3). コップBへ移す。

プログラムの例。 ズルいけど発想は同じだと思う。
intサイズのコップA、Bを用意する。
プログラムの場合は、差が負であっても可能だが、果汁に拘りたい人は大小関係を比較して処理をすれば良い。
差分を使っているのでオーバーフロー(コップから溢れる)はしないが、 コップのサイズがfloatなどの場合に誤差が生じる可能性が有る。
// Swap_2.java		2013.6.23	by Ryn

public class Swap_2 {

	public static void main(String[] args) {

		int a = 500, b = 350;

		System.out.println("a = " + a + ", b = "+ b);

		b = a - b;			// b = 500 - 350 = 150
		a -= b;				// a = 500 - 150 = 350
		b += a;				// b = 150 + 350 = 500

		System.out.println("a = " + a + ", b = "+ b);
	}
}


その3

加算、減算では無く、排他的論理和でも出来る。 これをXOR交換アルゴリズムと言う。 この方法はアセンブラで数の少ないレジスタを直接操作して行うには効果が有るが、 高級言語では「その1」の方法よりも処理速度が遅くなる傾向にある。
// Swap_3.java		2013.6.23	by Ryn

public class Swap_3 {

	public static void main(String[] args) {

		int a = 500, b = 350;
		
		System.out.println("a = " + a + ", b = "+ b);

		b ^= a;
		a ^= b;
		b ^= a;

		System.out.println("a = " + a + ", b = "+ b);
	}
}


確かに実務的には「その1」の方法が、 シンプル、判り易い、確実、なのは間違いがないのですが、 アルゴリズムとしては、違う形のコップ、違う種類のジュースの例にしてしまうと、 「その2」や「その3」への発想にはつながらないだろうなぁ、 と、思うのです。 こだわり過ぎでしょうか。





[ 赤い玉の画像 ] 「キーワード辞典」の目次へ

[ 黒板消しとチョーク受けの画像 ]