Cut a rectangle: Difference between revisions

Content added Content deleted
(Added Elixir)
Line 519: Line 519:
10 x 10: 1124140214</pre>
10 x 10: 1124140214</pre>
Using the LDC2 compiler the runtime is about 15.98 seconds (the first C entry runs in about 16.75 seconds with GCC).
Using the LDC2 compiler the runtime is about 15.98 seconds (the first C entry runs in about 16.75 seconds with GCC).

=={{header|Eiffel}}==
=={{header|Eiffel}}==
<lang Eiffel>
<lang Eiffel>
Line 814: Line 815:
Rectangle 10 x 9: 99953769 possibilities
Rectangle 10 x 9: 99953769 possibilities
Rectangle 10 x 10: 1124140214 possibilities
Rectangle 10 x 10: 1124140214 possibilities
</pre>

=={{header|Elixir}}==
{{trans|Ruby}}
===Count only===
<lang elixir>import Integer

defmodule Rectangle do
def cut_it(h, w) when is_odd(h) and is_odd(w), do: 0
def cut_it(h, w) when is_odd(h), do: cut_it(w, h)
def cut_it(_, 1), do: 1
def cut_it(h, 2), do: h
def cut_it(2, w), do: w
def cut_it(h, w) do
grid = List.duplicate(false, (h + 1) * (w + 1))
t = div(h, 2) * (w + 1) + div(w, 2)
if is_odd(w) do
grid = grid |> List.replace_at(t, true) |> List.replace_at(t+1, true)
walk(h, w, div(h, 2), div(w, 2) - 1, grid) + walk(h, w, div(h, 2) - 1, div(w, 2), grid) * 2
else
grid = grid |> List.replace_at(t, true)
count = walk(h, w, div(h, 2), div(w, 2) - 1, grid)
if h == w, do: count * 2,
else: count + walk(h, w, div(h, 2) - 1, div(w, 2), grid)
end
end
defp walk(h, w, y, x, grid, count\\0)
defp walk(h, w, y, x,_grid, count) when y in [0,h] or x in [0,w], do: count+1
defp walk(h, w, y, x, grid, count) do
blen = (h + 1) * (w + 1) - 1
t = y * (w + 1) + x
grid = grid |> List.replace_at(t, true) |> List.replace_at(blen-t, true)
Enum.reduce(next(w), count, fn {nt, dy, dx}, cnt ->
if Enum.at(grid, t+nt), do: cnt, else: cnt + walk(h, w, y+dy, x+dx, grid)
end)
end
defp next(w), do: [{w+1, 1, 0}, {-w-1, -1, 0}, {-1, 0, -1}, {1, 0, 1}] # {next,dy,dx}
end

Enum.each(1..9, fn w ->
Enum.each(1..w, fn h ->
if is_even(w * h), do: IO.puts "#{w} x #{h}: #{Rectangle.cut_it(w, h)}"
end)
end)</lang>

{{out}}
<pre>
2 x 1: 1
2 x 2: 2
3 x 2: 3
4 x 1: 1
4 x 2: 4
4 x 3: 9
4 x 4: 22
5 x 2: 5
5 x 4: 39
6 x 1: 1
6 x 2: 6
6 x 3: 23
6 x 4: 90
6 x 5: 263
6 x 6: 1018
7 x 2: 7
7 x 4: 151
7 x 6: 2947
8 x 1: 1
8 x 2: 8
8 x 3: 53
8 x 4: 340
8 x 5: 1675
8 x 6: 11174
8 x 7: 55939
8 x 8: 369050
9 x 2: 9
9 x 4: 553
9 x 6: 31721
9 x 8: 1812667
</pre>

===Show each of the cuts===
{{works with|Elixir|1.2}}
<lang elixir>defmodule Rectangle do
def cut(h, w, disp\\true) when rem(h,2)==0 or rem(w,2)==0 do
limit = div(h * w, 2)
start_link
grid = make_grid(h, w)
walk(h, w, grid, 0, 0, limit, %{}, [])
if disp, do: display(h, w)
result = Agent.get(__MODULE__, &(&1))
Agent.stop(__MODULE__)
MapSet.to_list(result)
end
defp start_link do
Agent.start_link(fn -> MapSet.new end, name: __MODULE__)
end
defp make_grid(h, w) do
for i <- 0..h-1, j <- 0..w-1, into: %{}, do: {{i,j}, true}
end
defp walk(h, w, grid, x, y, limit, cut, select) do
grid2 = grid |> Map.put({x,y}, false) |> Map.put({h-x-1,w-y-1}, false)
select2 = [{x,y} | select] |> Enum.sort
unless cut[select2] do
if length(select2) == limit do
Agent.update(__MODULE__, fn set -> MapSet.put(set, select2) end)
else
cut2 = Map.put(cut, select2, true)
search_next(grid2, select2)
|> Enum.each(fn {i,j} -> walk(h, w, grid2, i, j, limit, cut2, select2) end)
end
end
end
defp dirs(x, y), do: [{x+1, y}, {x-1, y}, {x, y-1}, {x, y+1}]
defp search_next(grid, select) do
(for {x,y} <- select, {i,j} <- dirs(x,y), grid[{i,j}], do: {i,j})
|> Enum.uniq
end
defp display(h, w) do
Agent.get(__MODULE__, &(&1))
|> Enum.each(fn select ->
grid = Enum.reduce(select, make_grid(h,w), fn {x,y},grid ->
%{grid | {x,y} => false}
end)
IO.puts to_string(h, w, grid)
end)
end
defp to_string(h, w, grid) do
text = for x <- 0..h*2, into: %{}, do: {x, String.duplicate(" ", w*4+1)}
text = Enum.reduce(0..h, text, fn i,acc ->
Enum.reduce(0..w, acc, fn j,txt ->
to_s(txt, i, j, grid)
end)
end)
Enum.map_join(0..h*2, "\n", fn i -> text[i] end)
end
defp to_s(text, i, j, grid) do
text = if grid[{i,j}] != grid[{i-1,j}], do: replace(text, i*2, j*4+1, "---"), else: text
text = if grid[{i,j}] != grid[{i,j-1}], do: replace(text, i*2+1, j*4, "|"), else: text
replace(text, i*2, j*4, "+")
end
defp replace(text, x, y, replacement) do
len = String.length(replacement)
Map.update!(text, x, fn str ->
String.slice(str, 0, y) <> replacement <> String.slice(str, y+len..-1)
end)
end
end

Rectangle.cut(2, 2) |> length |> IO.puts
Rectangle.cut(3, 4) |> length |> IO.puts</lang>

{{out}}
<pre style="height:64ex;overflow:scroll">
+---+---+
| |
+---+---+
| |
+---+---+
+---+---+
| | |
+ + +
| | |
+---+---+
2
+---+---+---+---+
| |
+ + +---+---+
| | |
+---+---+ + +
| |
+---+---+---+---+
+---+---+---+---+
| |
+ +---+ +---+
| | | | |
+---+ +---+ +
| |
+---+---+---+---+
+---+---+---+---+
| |
+---+ +---+ +
| | | | |
+ +---+ +---+
| |
+---+---+---+---+
+---+---+---+---+
| |
+---+---+ + +
| | |
+ + +---+---+
| |
+---+---+---+---+
+---+---+---+---+
| | |
+ + +---+ +
| | |
+ +---+ + +
| | |
+---+---+---+---+
+---+---+---+---+
| | |
+ +---+ + +
| | | | |
+ + +---+ +
| | |
+---+---+---+---+
+---+---+---+---+
| | |
+ + + + +
| | |
+ + + + +
| | |
+---+---+---+---+
+---+---+---+---+
| | |
+ +---+ + +
| | |
+ + +---+ +
| | |
+---+---+---+---+
+---+---+---+---+
| | |
+ + +---+ +
| | | | |
+ +---+ + +
| | |
+---+---+---+---+
9
</pre>
</pre>