|  | A path produced by a program I wrote follows the form-feed.  I think it is
correct, but I have not checked it by hand, yet (you can't trust computers).
I did a few things to speed up the program:
	Actually rotating the elements would take too much time.  Even
	switching them would take a significant amount of time.  So
	the program starts by finding all permutations of five elements
	and gives each of them a number.  Then it fills two arrays.  One
	array gives the number of the permutation found by rotating a
	given permutation; the other arrays gives the number of the
	permutation found by switching the last two elements.
	Another array is maintained as a flag for each permutation,
	indicating whether it has been used or not.  In addition, each
	set of five permutations which can be obtained from each other
	by rotations only is collected:  There is an array which gives
	a set number (from 0 to 23) for each permutation.  An array
	is kept to give the number of used permutations in each set.
	If a set of five permutations is drawn on paper, one can see several
	things:  At most four rotations in a row are possible.  And
	each set of five permutations can support either only four rotations
	or one rotation and two rotations, since a path through all
	the permutations must enter and leave any subset of vertices
	(permutations) and even number of times.
	Thus, if the program performs a switch and finds itself in a set
	of five permutations of which two have already been used, it knows
	it must perform exactly two rotations and a switch.  Conversely,
	finding three permutations used means one rotation and a switch are
	required.  No used permutations means one, two, and four rotations,
	followed by a switch, must all be tried.
				-- edp
Switch.
Rotate.
Switch.
Rotate.
Switch.
Rotate.
Rotate.
Switch.
Rotate.
Switch.
Rotate.
Rotate.
Rotate.
Rotate.
Switch.
Rotate.
Switch.
Rotate.
Rotate.
Rotate.
Rotate.
Switch.
Rotate.
Switch.
Rotate.
Switch.
Rotate.
Rotate.
Switch.
Rotate.
Rotate.
Rotate.
Rotate.
Switch.
Rotate.
Rotate.
Rotate.
Rotate.
Switch.
Rotate.
Switch.
Rotate.
Rotate.
Switch.
Rotate.
Rotate.
Switch.
Rotate.
Rotate.
Rotate.
Rotate.
Switch.
Rotate.
Rotate.
Switch.
Rotate.
Rotate.
Switch.
Rotate.
Rotate.
Rotate.
Rotate.
Switch.
Rotate.
Rotate.
Rotate.
Rotate.
Switch.
Rotate.
Rotate.
Switch.
Rotate.
Rotate.
Switch.
Rotate.
Rotate.
Rotate.
Rotate.
Switch.
Rotate.
Rotate.
Rotate.
Rotate.
Switch.
Rotate.
Rotate.
Rotate.
Rotate.
Switch.
Rotate.
Switch.
Rotate.
Switch.
Rotate.
Rotate.
Switch.
Rotate.
Rotate.
Switch.
Rotate.
Switch.
Rotate.
Switch.
Rotate.
Rotate.
Rotate.
Rotate.
Switch.
Rotate.
Switch.
Rotate.
Rotate.
Switch.
Rotate.
Rotate.
Switch.
Rotate.
Rotate.
Rotate.
Rotate.
 | 
|  | I claim there is at least one Hamiltonian path through the fours.  Here it
is:
Hamiltonian path through permutations of four objects:
0123 rotate . . .
1230 rotate . . .
2301 rotate . . .
3012 swap . . .
3021 rotate . . .
0213 rotate . . .
2130 swap . . .
2103 rotate . . .
1032 swap . . .
1023 rotate . . .
0231 rotate . . .
2310 rotate . . .
3102 swap . . .
3120 rotate . . .
1203 rotate . . .
2031 rotate . . .
0312 swap . . .
0321 rotate . . .
3210 swap . . .
3201 rotate . . .
2013 rotate . . .
0132 rotate . . .
1320 swap . . .
1302
That path was produced with the following BLISS program.  If you want
to run it as is, you'll also need SPRITE::USER1:[OSMAN.BLISSLIB]USEFULBLI.L32
and TERMNL.OBJ.  Here's the program:
module hamil (main = beg, addressing_mode (external = general, nonexternal =
general)) = begin
forward routine!s
	beg,
	hamil,
	slow_rotate,
	slow_swap,
	index_to_digits,
	digits_to_index,
	printout;
library 'sys$library:starlet';
library 'blisslib:usefulbli';
literal
	c_indicate_swap = 0, c_indicate_rotate = 1,
	max_n_factorial = 24;
own
	n : initial (4),
	n_factorial : initial (24),
	seen : vector [max_n_factorial],
	path : vector [max_n_factorial],
	rotate_table : vector [max_n_factorial],
	op : vector [max_n_factorial],
	swap_table : vector [max_n_factorial];
routine printout =
	begin
	local
	    digits : vector [4];
	type ('Hamiltonian path through permutations of four objects:');
	incr i from 0 to .n_factorial - 1 do
	    begin
	    index_to_digits (.path[.i], digits[0]);
	    typePart (decimal (.digits[0]), decimal (.digits[1]),
		decimal (.digits[2]), decimal (.digits[3]));
	    if .i neq .n_factorial - 1
	    then
		selectOne .op[.i + 1] of set
		[c_indicate_rotate] : typePart (' rotate . . .');
		[c_indicate_swap]   : typePart (' swap . . .');
		tes;
	    typeCarriageReturn ()
	    end
	end;
routine beg =
	begin
	ch$fill (0, 4 * .n_factorial, seen[0]);
	incr i from 0 to .n_factorial - 1 do
	    begin
	    rotate_table[.i] = slow_rotate(.i);
	    swap_table[.i] = slow_swap(.i)
	    end;
	seen[0] = 1;
	path[0] = 0;
	if hamil (1)
	then printout ()
	else type ('No hamiltonian paths found through the permutations of ',
	    decimal (.n), ' objects.');
	ss$_normal
	end;
routine hamil (current) =
	begin
	local
	    state : initial (.path[.current - 1]);
	if .current geq .n_factorial
	then return 1;
	if not .seen[.rotate_table[.state]]
	then
	    begin
	    path[.current] = .rotate_table[.state];
	    seen[.rotate_table[.state]] = 1;
	    op[.current] = c_indicate_rotate;
	    if hamil (.current + 1)
	    then return 1;
	    seen[.rotate_table[.state]] = 0
	    end;
	if not .seen[.swap_table[.state]]
	then
	    begin
	    path[.current] = .swap_table[.state];
	    seen[.swap_table[.state]] = 1;
	    op[.current] = c_indicate_swap;
	    if hamil (.current + 1)
	    then return 1;
	    seen[.swap_table[.state]] = 0
	    end;
	return 0
	end;
routine slow_rotate (index) =
	begin
	local
	    digits : vector [4], temp;
	index_to_digits (.index, digits[0]);
	temp = .digits[0];
	digits[0] = .digits[1];
	digits[1] = .digits[2];
	digits[2] = .digits[3];
	digits[3] = .temp;
	digits_to_index (digits[0])
	end;
routine slow_swap (index) =
	begin
	local
	    digits : vector [4], temp;
	index_to_digits (.index, digits[0]);
	temp = .digits[2];
	digits[2] = .digits[3];
	digits[3] = .temp;
	digits_to_index (digits[0])
	end;
routine digits_to_index (digits : ref vector [4]) =
	begin
	local
	    index : initial ((((.digits[0] * 10) + .digits[1]) * 10 +
		.digits[2]) * 10 + .digits[3]),
	    codes : vector [24] initial (
		0123, 0132, 0213, 0231, 0312, 0321,
		1023, 1032, 1203, 1230, 1302, 1320,
		2013, 2031, 2103, 2130, 2301, 2310,
		3012, 3021, 3102, 3120, 3201, 3210);
	(ch$find_sub (24 * 4, codes[0], 4, index) - codes[0]) / 4
	end;
routine index_to_digits (index, digits : ref vector[4]) =
	begin
	local
	    choice;
	macro rest (a,b,c,d,e,f) =
	    choice = (case .index mod 6 from 0 to 5 of set
		[0]:a;[1]:b;[2]:c;[3]:d;[4]:e;[5]:f;tes) % ;
	digits[0] = .index / 6;
	case .digits[0] from 0 to 3 of set
	[0] : rest (123, 132, 213, 231, 312, 321);
	[1] : rest (023, 032, 203, 230, 302, 320);
	[2] : rest (013, 031, 103, 130, 301, 310);
	[3] : rest (012, 021, 102, 120, 201, 210);
	tes;
	digits[3] = .choice mod 10;
	digits[2] = .choice / 10;
	digits[1] = .digits[2] / 10;
	digits[2] = .digits[2] mod 10
	end;
end
eludom
/Eric
 |