D
David Tran
Here is my solution, it is kind of short ...
#--------------------------------------------------------------------
# Program : Solution for Ruby Quiz #33 Tiling Turmoil
# Author : David Tran
# Date : 2005-05-20
# Version : 1.0
#--------------------------------------------------------------------
def tile(a, n, m, s, x)
@Count +=3D 1 =20
h =3D m/2
new_s =3D [s, s+h, s+h*n, s+h*n+h]
new_x =3D [s+(h-1)*n+(h-1), s+(h-1)*n+h, s+h*n+h-1, s+h*n+h]=20
p =3D ((x-s) / n < h) ? ((x-s) % n < h) ? 0 : 1 \
: ((x-s) % n < h) ? 2 : 3
new_x.each_index{ |i| a[new_x] =3D @Count if i !=3D p }
return if h =3D=3D 1
new_x[p] =3D x
new_s.each_with_index { |e, i| tile(a, n, h, e, new_x) }
end
(puts "Usage: #$0 n"; exit) if (ARGV.size !=3D 1 || ARGV[0].to_i <=3D 0)
n =3D 2 ** ARGV[0].to_i
@Count =3D 0
a =3D Array.new(n*n)
x =3D rand(a.size)
a[x] =3D 'X'
tile(a, n, n, 0, x)
format =3D "%#{2 + Math.log10(a.size).to_i}s"
a.each_with_index {|e, i| print(format % e); puts if (i+1)%(n) =3D=3D 0}
# End of Program------------------------------------------------------
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
It is base on S. Golomb gave an inductive proof :
http://www.cut-the-knot.com/Curriculum/Geometry/Tromino.shtml
Here is some explanation for my program about tile method:
a - is a dimension one array of n x n ( flat of orign dimension 2 array)
n - is the number side ( 2 ** input number )
m - is the number side of sub square
s - is the start point index ( top-left corner index for sub square )
x - is the missing cell index
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Base on The four color theorem, we could color the tile by using max 4 colo=
rs.
http://www.math.gatech.edu/~thomas/FC/fourcolor.html
So, I modified again my solution to show by using 4 color codes:
http://mathworld.wolfram.com/Four-ColorTheorem.html
#--------------------------------------------------------------------
# Program : Solution for Ruby Quiz #33 Tiling Turmoil
# Author : David Tran
# Date : 2005-05-20
# Version : Using 4 color codes
#--------------------------------------------------------------------
def tile(a, n, m, s, x)
h =3D m/2
new_s =3D [s, s+h, s+h*n, s+h*n+h]
new_x =3D [s+(h-1)*n+(h-1), s+(h-1)*n+h, s+h*n+h-1, s+h*n+h]=20
around_tile =3D [new_x[0]%n =3D=3D 0 ? nil : new_x[0]-1,=20
new_x[0] < n ? nil : new_x[0]-n,
new_x[1] < n ? nil : new_x[1]-n,
(new_x[1]+1)%n =3D=3D 0 ? nil : new_x[1]+1,
new_x[2]%n =3D=3D 0 ? nil : new_x[2]-1,
new_x[2]/n + 1 >=3D n ? nil : new_x[2]+n,
new_x[3]/n + 1 >=3D n ? nil : new_x[3]+n,=20
(new_x[3]+1)% n =3D=3D 0 ? nil : new_x[3]+1]
=20
p =3D ((x-s)/ n < h) ? ((x-s)% n < h) ? 0 : 1 \
: ((x-s)% n < h) ? 2 : 3
around_tile[p*2, 2] =3D new_x[p]
(1..4).each do |color|=20
use =3D false
around_tile.each do |i|
next if i.nil?
(use =3D true; break) if a =3D=3D color
end
if (!use)
new_x.each_index{ |i| a[new_x] =3D color if i !=3D p }
break;
end
end
return if h =3D=3D 1
new_x[p] =3D x
new_s.each_with_index { |e, i| tile(a, n, h, e, new_x) }
end
(puts "Usage: #$0 n"; exit) if (ARGV.size !=3D 1 || ARGV[0].to_i <=3D 0)
n =3D 2 ** ARGV[0].to_i
a =3D Array.new(n*n)
x =3D rand(a.size)
a[x] =3D 0
tile(a, n, n, 0, x)
colorCode =3D [' ', '*', 'o', '+', '-']
a.each_with_index { |e, i| print(" #{colorCode[e]}"); puts if (i+1)%n =3D=
=3D 0 }
# End of Program------------------------------------------------------
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
This gives a solution presents like:
$> tiling2.rb 4
o o + + o o + + o o + + o o + +
o * * + o * * + o * * + o * * +
+ * o o + + * o + * o o + + * o
+ + o * * + o o + + o * * + o o
o o + * o o + + o o + + * o + +
o * + + o * * + o * * + o o * +
+ * * o + * o o + + * o + * * o
+ + o o + + o * * + o o + + o o
o o + + o o + * o o + + o o + +
o * * + o * + + o * * + o * * +
+ * o o + * * o + * o o + + * o
+ + o * + + o o + + o * + o o
o o + * * o + + o o + * * o + +
o * + + o o * + o * + + o o * +
+ * * o + * * o + * * o + * * o
+ + o o + + o o + + o o + + o o
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
My first and second solution always recalculation next "missing" cell
possition, it is kind of waste time, because, except the "missing" cell
all will be one of top-left, top-right, bottom-left, bottom-right
coner "missing"
on next iteration and so on.
So, one ugly and quickly improve is like:
#--------------------------------------------------------------------
# Program : Solution for Ruby Quiz #33 Tiling Turmoil
# Author : David Tran
# Date : 2005-05-20
# Version : Without always recalculate "missing" cell
#--------------------------------------------------------------------
DIRECTION =3D [ [ 0, 3, 0, 1],
[ 2, 1, 0, 1],
[ 2, 3, 2, 1],
[ 2, 3, 0, 3] ]
def tile(a, n, m, s, x, p)
@Count +=3D 1
h =3D m/2
new_s =3D [s, s+h, s+h*n+h, s+h*n]
new_x =3D [s+(h-1)*n+(h-1), s+(h-1)*n+h, s+h*n+h, s+h*n+h-1]
if p < 0
pp =3D ((x-s) / n < h) ? ((x-s) % n < h) ? 0 : 1 \
: ((x-s) % n < h) ? 3 : 2 =20
else
pp =3D p
end
=20
new_x.each_index{ |i| a[new_x] =3D @Count if i !=3D pp }
return if h =3D=3D 1
dir =3D DIRECTION[pp]
if p < 0
dir =3D dir.dup
dir[pp] =3D -1
end
new_s.each_with_index { |e, i| tile(a, n, h, e, x, dir) }
end
(puts "Usage: #$0 n"; exit) if (ARGV.size !=3D 1 || ARGV[0].to_i <=3D 0)
n =3D 2 ** ARGV[0].to_i
a =3D Array.new(n*n)
x =3D rand(a.size)
a[x] =3D 'X'
@Count =3D 0
tile(a, n, n, 0, x, -1)
format =3D "%#{2 + Math.log10(a.size).to_i}s"
a.each_with_index {|e, i| print(format % e); puts if (i+1)%(n) =3D=3D 0}
# End of Program------------------------------------------------------
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Anyway, I still like my first short solution even it seems waste time to=20
recalculate "missing" cell ...
#--------------------------------------------------------------------
# Program : Solution for Ruby Quiz #33 Tiling Turmoil
# Author : David Tran
# Date : 2005-05-20
# Version : 1.0
#--------------------------------------------------------------------
def tile(a, n, m, s, x)
@Count +=3D 1 =20
h =3D m/2
new_s =3D [s, s+h, s+h*n, s+h*n+h]
new_x =3D [s+(h-1)*n+(h-1), s+(h-1)*n+h, s+h*n+h-1, s+h*n+h]=20
p =3D ((x-s) / n < h) ? ((x-s) % n < h) ? 0 : 1 \
: ((x-s) % n < h) ? 2 : 3
new_x.each_index{ |i| a[new_x] =3D @Count if i !=3D p }
return if h =3D=3D 1
new_x[p] =3D x
new_s.each_with_index { |e, i| tile(a, n, h, e, new_x) }
end
(puts "Usage: #$0 n"; exit) if (ARGV.size !=3D 1 || ARGV[0].to_i <=3D 0)
n =3D 2 ** ARGV[0].to_i
@Count =3D 0
a =3D Array.new(n*n)
x =3D rand(a.size)
a[x] =3D 'X'
tile(a, n, n, 0, x)
format =3D "%#{2 + Math.log10(a.size).to_i}s"
a.each_with_index {|e, i| print(format % e); puts if (i+1)%(n) =3D=3D 0}
# End of Program------------------------------------------------------
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
It is base on S. Golomb gave an inductive proof :
http://www.cut-the-knot.com/Curriculum/Geometry/Tromino.shtml
Here is some explanation for my program about tile method:
a - is a dimension one array of n x n ( flat of orign dimension 2 array)
n - is the number side ( 2 ** input number )
m - is the number side of sub square
s - is the start point index ( top-left corner index for sub square )
x - is the missing cell index
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Base on The four color theorem, we could color the tile by using max 4 colo=
rs.
http://www.math.gatech.edu/~thomas/FC/fourcolor.html
So, I modified again my solution to show by using 4 color codes:
http://mathworld.wolfram.com/Four-ColorTheorem.html
#--------------------------------------------------------------------
# Program : Solution for Ruby Quiz #33 Tiling Turmoil
# Author : David Tran
# Date : 2005-05-20
# Version : Using 4 color codes
#--------------------------------------------------------------------
def tile(a, n, m, s, x)
h =3D m/2
new_s =3D [s, s+h, s+h*n, s+h*n+h]
new_x =3D [s+(h-1)*n+(h-1), s+(h-1)*n+h, s+h*n+h-1, s+h*n+h]=20
around_tile =3D [new_x[0]%n =3D=3D 0 ? nil : new_x[0]-1,=20
new_x[0] < n ? nil : new_x[0]-n,
new_x[1] < n ? nil : new_x[1]-n,
(new_x[1]+1)%n =3D=3D 0 ? nil : new_x[1]+1,
new_x[2]%n =3D=3D 0 ? nil : new_x[2]-1,
new_x[2]/n + 1 >=3D n ? nil : new_x[2]+n,
new_x[3]/n + 1 >=3D n ? nil : new_x[3]+n,=20
(new_x[3]+1)% n =3D=3D 0 ? nil : new_x[3]+1]
=20
p =3D ((x-s)/ n < h) ? ((x-s)% n < h) ? 0 : 1 \
: ((x-s)% n < h) ? 2 : 3
around_tile[p*2, 2] =3D new_x[p]
(1..4).each do |color|=20
use =3D false
around_tile.each do |i|
next if i.nil?
(use =3D true; break) if a =3D=3D color
end
if (!use)
new_x.each_index{ |i| a[new_x] =3D color if i !=3D p }
break;
end
end
return if h =3D=3D 1
new_x[p] =3D x
new_s.each_with_index { |e, i| tile(a, n, h, e, new_x) }
end
(puts "Usage: #$0 n"; exit) if (ARGV.size !=3D 1 || ARGV[0].to_i <=3D 0)
n =3D 2 ** ARGV[0].to_i
a =3D Array.new(n*n)
x =3D rand(a.size)
a[x] =3D 0
tile(a, n, n, 0, x)
colorCode =3D [' ', '*', 'o', '+', '-']
a.each_with_index { |e, i| print(" #{colorCode[e]}"); puts if (i+1)%n =3D=
=3D 0 }
# End of Program------------------------------------------------------
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
This gives a solution presents like:
$> tiling2.rb 4
o o + + o o + + o o + + o o + +
o * * + o * * + o * * + o * * +
+ * o o + + * o + * o o + + * o
+ + o * * + o o + + o * * + o o
o o + * o o + + o o + + * o + +
o * + + o * * + o * * + o o * +
+ * * o + * o o + + * o + * * o
+ + o o + + o * * + o o + + o o
o o + + o o + * o o + + o o + +
o * * + o * + + o * * + o * * +
+ * o o + * * o + * o o + + * o
+ + o * + + o o + + o * + o o
o o + * * o + + o o + * * o + +
o * + + o o * + o * + + o o * +
+ * * o + * * o + * * o + * * o
+ + o o + + o o + + o o + + o o
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
My first and second solution always recalculation next "missing" cell
possition, it is kind of waste time, because, except the "missing" cell
all will be one of top-left, top-right, bottom-left, bottom-right
coner "missing"
on next iteration and so on.
So, one ugly and quickly improve is like:
#--------------------------------------------------------------------
# Program : Solution for Ruby Quiz #33 Tiling Turmoil
# Author : David Tran
# Date : 2005-05-20
# Version : Without always recalculate "missing" cell
#--------------------------------------------------------------------
DIRECTION =3D [ [ 0, 3, 0, 1],
[ 2, 1, 0, 1],
[ 2, 3, 2, 1],
[ 2, 3, 0, 3] ]
def tile(a, n, m, s, x, p)
@Count +=3D 1
h =3D m/2
new_s =3D [s, s+h, s+h*n+h, s+h*n]
new_x =3D [s+(h-1)*n+(h-1), s+(h-1)*n+h, s+h*n+h, s+h*n+h-1]
if p < 0
pp =3D ((x-s) / n < h) ? ((x-s) % n < h) ? 0 : 1 \
: ((x-s) % n < h) ? 3 : 2 =20
else
pp =3D p
end
=20
new_x.each_index{ |i| a[new_x] =3D @Count if i !=3D pp }
return if h =3D=3D 1
dir =3D DIRECTION[pp]
if p < 0
dir =3D dir.dup
dir[pp] =3D -1
end
new_s.each_with_index { |e, i| tile(a, n, h, e, x, dir) }
end
(puts "Usage: #$0 n"; exit) if (ARGV.size !=3D 1 || ARGV[0].to_i <=3D 0)
n =3D 2 ** ARGV[0].to_i
a =3D Array.new(n*n)
x =3D rand(a.size)
a[x] =3D 'X'
@Count =3D 0
tile(a, n, n, 0, x, -1)
format =3D "%#{2 + Math.log10(a.size).to_i}s"
a.each_with_index {|e, i| print(format % e); puts if (i+1)%(n) =3D=3D 0}
# End of Program------------------------------------------------------
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Anyway, I still like my first short solution even it seems waste time to=20
recalculate "missing" cell ...