От: | Lazy Cjow Rhrr | lj://_lcr_ | |
Дата: | 16.03.06 11:02 | ||
Оценка: | 15 (1) |
Решение ТрурляM>Дан рисунок, представленный ASCII кодами (. — белый, # — черный). Задача...
-module(image).
-compile(export_all).
-import(lists, [append/1, duplicate/2, map/2, merge/3,
reverse/1, split/2, sublist/3, unzip/1, zip/2, zipwith/3]).
%% Font for bounds/1
%% ### ## ## ### # ### ## ### ### ###
%% # # # # # ## # # # # # # # #
%% # # # # # # # ## ### # # ###
%% # # # # # ### # # # # # # #
%% ### ### ### ### # ## ### # ### ##
-define(Font, {8#75557, 8#62227, 8#61247, 8#71217, 8#13571,
8#74616, 8#34757, 8#75122, 8#75257, 8#75716}).
-define(Fwidth, 3).
-define(Fheight, 5).
test() ->
L = [
"....................",
".###...##.###..#..#.",
".#..#.#...#..#.##.#.",
".###....#.#..#.#.##.",
".#..#.##..###..#..#.",
"...................."
],
Lt = [{id, L},
{scale, L, {1, 2}},
{bounds, L} ],
Ft =fun (Tr) when is_tuple(Tr) ->
TrName = element(1, Tr),
io:format("~p =>~n~p~n", [TrName, transform(Tr)])
end,
map(Ft, Lt), % Go!
ok.
%%% mega transformation function :-)
transform({Transform, Picture}) when is_function(Transform, 1) ->
Transform(Picture);
transform({Transform, Picture, _Data}) when is_function(Transform, 1) ->
Transform(Picture);
transform({Transform, Picture, Data}) when is_function(Transform, 2) ->
Transform(Picture, Data);
transform({Transform, Picture}) when is_atom(Transform) ->
apply(?MODULE, Transform, [Picture]);
transform({Transform, Picture, Data}) when is_atom(Transform) ->
apply(?MODULE, Transform, [Picture, Data]).
%%% particular transformations
id(L) -> L.
mv(L) -> map({lists,reverse}, L).
mh(L) -> reverse(L).
mvh(L) -> mv(mh(L)).
transpose([]) ->
[];
transpose([[] | Tail]) ->
transpose(Tail);
transpose([[H | T] | Tail]) ->
{Headz, Tailz} = unzip([{H, T} || [H | T] <- Tail]),
[[H | Headz] | transpose([T | Tailz])].
r90(L) -> mh(transpose(L)).
r_90(L) -> transpose(mh(L)).
invert(L) ->
F = fun ($.) -> $#; ($#) -> $. end,
map(fun (R)-> [F(X) || X <- R] end, L).
scale(L, {M, N}) ->
Ds = fun (S) -> duplicate(M, S) end, % "duplicate string" fun
Di = fun (X) -> duplicate(N, X) end, % "duplicate item" fun
map(fun (S) -> append(map(Di, S)) end, append(map(Ds, L))).
diff(L1, L2) ->
D = fun (S1, S2) ->
F = fun ( X, Y) when X==Y -> $.;
(_X, _Y) -> $#
end,
zipwith(F, S1, S2)
end,
zipwith(D, L1, L2).
%%% make sure that 1 <= X <= X+W <= N; 1 <= Y <= Y+H <= M
crop(L, {Y, X, W, H}) ->
sublist(
map(fun (S) -> sublist(S, X, W) end, L),
Y, H).
%%% bounds
bounds(L) ->
convert_bounds(tuple_to_list(bounds_y(L))).
%% bounds on Y axis
bounds_y(L) ->
bounds_y(0, empty, L).
bounds_y(Y, Val, [Hs | Ts]) ->
bounds_y(Y + 1, bounds_x(1, Y + 1, Val, Hs), Ts);
bounds_y(_Y, Val, []) ->
Val.
%% bounds on X axis
bounds_x(X, Y, Val, [H | T]) ->
case {H, Val} of
{$#, empty} -> bounds_x(X + 1, Y, {X, X, Y, Y}, T);
{$#, {X0,_X1,Y0,_Y1}} when X > X0 -> bounds_x(X + 1, Y, {X0, X, Y0, Y}, T);
{$#, {_X0,X1,Y0,_Y1}} -> bounds_x(X + 1, Y, {X, X1, Y0, Y}, T);
_anything_else_ -> bounds_x(X + 1, Y, Val, T)
end;
bounds_x(_X, _Y, Val, []) ->
Val.
%%% conversion helpers
%% input [Xmin, Xmax, Ymin, Ymax]
convert_bounds([]) ->
[];
convert_bounds([N]) ->
convert_int(N);
convert_bounds([Nh | Nt]) ->
Concat = fun (L1, L2) -> L1 ++ "..." ++ L2 end,
zipwith(Concat,
convert_int(Nh), convert_bounds(Nt)).
%% input like 123
convert_int(N) when is_integer(N) ->
convert_digits(integer_to_list(N)).
%% input like "1234567890"
convert_digits([]) ->
[];
convert_digits([D]) ->
convert_char(element(D - $0 + 1, ?Font));
convert_digits([D | Dlist]) ->
Concat = fun (L1, L2) -> L1 ++ "." ++ L2 end,
zipwith(Concat,
convert_char(element(D - $0 + 1, ?Font)),
convert_digits(Dlist)).
%% input like 6009 (== 8#13571)
convert_char(C) when is_integer(C) ->
Bins = erlang:integer_to_list(C, 2),
Align = duplicate(?Fwidth * ?Fheight - length(Bins), $0),
convert_bins(Align ++ Bins).
%% input like "110010010010111"
convert_bins([]) ->
[];
convert_bins(Blist) ->
F = fun ($1) -> $#; (_)->$. end,
{H, T} = split(?Fwidth, Blist),
[map(F, H) | convert_bins(T)].
19 > image:test().
id =>
["....................",
".###...##.###..#..#.",
".#..#.#...#..#.##.#.",
".###....#.#..#.#.##.",
".#..#.##..###..#..#.",
"...................."]
scale =>
["........................................",
"..######......####..######....##....##..",
"..##....##..##......##....##..####..##..",
"..######........##..##....##..##..####..",
"..##....##..####....######....##....##..",
"........................................"]
bounds =>
["##....##..###...##....###",
"..#....#..#.#.....#...#..",
".#.....#..###....#....##.",
"#......#....#...#.......#",
"###...###.##....###...##."]
ok