163 lines
3.3 KiB
Text
163 lines
3.3 KiB
Text
class
|
|
GRID
|
|
|
|
create
|
|
make
|
|
|
|
feature {NONE}
|
|
|
|
n: INTEGER
|
|
|
|
m: INTEGER
|
|
|
|
feature
|
|
|
|
print_solution
|
|
-- Prints solution to cut a rectangle.
|
|
do
|
|
calculate_possibilities
|
|
io.put_string ("Rectangle " + n.out + " x " + m.out + ": " + count.out + " possibilities%N")
|
|
end
|
|
|
|
count: INTEGER
|
|
-- Number of solutions
|
|
|
|
make (a_n: INTEGER; a_m: INTEGER)
|
|
-- Initialize Problem with 'a_n' and 'a_m'.
|
|
require
|
|
a_n > 0
|
|
a_m > 0
|
|
do
|
|
n := a_n
|
|
m := a_m
|
|
count := 0
|
|
end
|
|
|
|
calculate_possibilities
|
|
-- Select all possible starting points.
|
|
local
|
|
i: INTEGER
|
|
do
|
|
if (n = 1 or m = 1) then
|
|
count := 1
|
|
end
|
|
|
|
from
|
|
i := 0
|
|
until
|
|
i > n or (n = 1 or m = 1)
|
|
loop
|
|
solve (create {POINT}.make_with_values (i, 0), create {POINT}.make_with_values (n - i, m), create {LINKED_LIST [POINT]}.make, create {LINKED_LIST [POINT]}.make)
|
|
i := i + 1
|
|
variant
|
|
n - i + 1
|
|
end
|
|
from
|
|
i := 0
|
|
until
|
|
i > m or (n = 1 or m = 1)
|
|
loop
|
|
solve (create {POINT}.make_with_values (n, i), create {POINT}.make_with_values (0, m - i), create {LINKED_LIST [POINT]}.make, create {LINKED_LIST [POINT]}.make)
|
|
i := i + 1
|
|
variant
|
|
m - i + 1
|
|
end
|
|
end
|
|
|
|
feature {NONE}
|
|
|
|
solve (p, q: POINT; visited_p, visited_q: LINKED_LIST [POINT])
|
|
-- Recursive solution of cut a rectangle.
|
|
local
|
|
possible_next: LINKED_LIST [POINT]
|
|
next: LINKED_LIST [POINT]
|
|
opposite: POINT
|
|
do
|
|
if p.negative or q.negative then
|
|
|
|
elseif p.same (q) then
|
|
add_solution
|
|
else
|
|
possible_next := get_possible_next (p)
|
|
create next.make
|
|
across
|
|
possible_next as x
|
|
loop
|
|
if x.item.x >= n or x.item.y >= m then
|
|
-- Next point cannot be on the border. Do nothing.
|
|
|
|
elseif x.item.same (q) then
|
|
add_solution
|
|
elseif not contains (x.item, visited_p) and not contains (x.item, visited_q) then
|
|
next.extend (x.item)
|
|
end
|
|
end
|
|
|
|
across
|
|
next as x
|
|
loop
|
|
-- Move in one direction
|
|
-- Calculate the opposite end of the cut by moving into the opposite direction (compared to p -> x)
|
|
create opposite.make_with_values (q.x - (x.item.x - p.x), q.y - (x.item.y - p.y))
|
|
|
|
visited_p.extend (p)
|
|
visited_q.extend (q)
|
|
|
|
solve (x.item, opposite, visited_p, visited_q)
|
|
|
|
-- Remove last point again
|
|
visited_p.finish
|
|
visited_p.remove
|
|
|
|
visited_q.finish
|
|
visited_q.remove
|
|
end
|
|
end
|
|
end
|
|
|
|
get_possible_next (p: POINT): LINKED_LIST [POINT]
|
|
-- Four possible next points.
|
|
local
|
|
q: POINT
|
|
do
|
|
create Result.make
|
|
|
|
--up
|
|
create q.make_with_values (p.x + 1, p.y)
|
|
if q.valid and q.x <= n and q.y <= m then
|
|
Result.extend (q);
|
|
end
|
|
|
|
--down
|
|
create q.make_with_values (p.x - 1, p.y)
|
|
if q.valid and q.x <= n and q.y <= m then
|
|
Result.extend (q)
|
|
end
|
|
|
|
--left
|
|
create q.make_with_values (p.x, p.y - 1)
|
|
if q.valid and q.x <= n and q.y <= m then
|
|
Result.extend (q)
|
|
end
|
|
|
|
--right
|
|
create q.make_with_values (p.x, p.y + 1)
|
|
if q.valid and q.x <= n and q.y <= m then
|
|
Result.extend (q)
|
|
end
|
|
end
|
|
|
|
add_solution
|
|
-- Increment count.
|
|
do
|
|
count := count + 1
|
|
end
|
|
|
|
contains (p: POINT; set: LINKED_LIST [POINT]): BOOLEAN
|
|
-- Does set contain 'p'?
|
|
do
|
|
set.compare_objects
|
|
Result := set.has (p)
|
|
end
|
|
|
|
end
|