| 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
|