Skip to content

Instantly share code, notes, and snippets.

@egobrain
Created September 5, 2015 13:05
Show Gist options
  • Save egobrain/6f6c23a248d5917da385 to your computer and use it in GitHub Desktop.
Save egobrain/6f6c23a248d5917da385 to your computer and use it in GitHub Desktop.
Ants fp
-module(ants).
-export([main/1]).
-mode(compile).
readline_iterator(File) ->
fun() ->
case file:read_line(File) of
{ok, Line} -> {ok, Line, readline_iterator(File)};
eof -> done;
{error, _Reason} = Err -> Err
end
end.
main([Filename]) ->
{ok, File} = file:open(Filename, [read, {encoding,unicode}]),
{ok, DotsP} = re:compile(":", [unicode]),
{ok, RuleP} = re:compile("(?<n>\\d)+(?<rule>.{3})(?<l>.?)", [unicode]),
foreach(
fun(Line) ->
Bin = unicode:characters_to_binary(Line),
[Data, RuleStr] = re:split(Bin, DotsP, [{return, binary}]),
{match, [PositionBin, Rule, Letter]} =
re:run(RuleStr, RuleP, [{capture, [n,rule,l], binary}]),
Position = binary_to_integer(PositionBin),
DataList = [<<Ch/utf8>>||<<Ch/utf8>> <= Data],
LettersI1 = from_list(DataList),
LettersI2 = apply_rule({Position, Rule, Letter}, LettersI1),
InfinitX = fun Loop() -> {ok, <<"Х"/utf8>>, Loop} end,
InfLettersI1 = append(LettersI1, InfinitX),
InfLettersI2 = append(LettersI2, InfinitX),
N = 2,
BothI = zip(by(N, InfLettersI1), by(N, InfLettersI2)),
ResI = dropwhen(
fun({[<<"Х"/utf8>>, <<"Х"/utf8>>], [<<"Х"/utf8>>,<<"Х"/utf8>>]}) -> true;
(_) -> false
end, BothI),
{ok, Res} = fold(fun({A, B}, S) -> metrics(A,B) + S end, 0, ResI),
io:format("~p\n", [Res])
end,
readline_iterator(File)).
apply_rule({Pos, <<"удл"/utf8>>, _}, I) ->
drop(Pos, I);
apply_rule({Pos, <<"изм"/utf8>>, L}, I) ->
replace(Pos, L, I);
apply_rule({Pos, <<"вст"/utf8>>, L}, I) ->
add(Pos, L, I).
metrics(A, B) ->
case metrics_(A, B) of
{ok, V} -> V;
error ->
case metrics_(B, A) of
{ok, V} -> V;
error -> 100
end
end.
metrics_(A, A) -> {ok, 0};
metrics_([<<"К"/utf8>>, <<"Л"/utf8>>], [<<"К"/utf8>>, <<"Х"/utf8>>]) -> {ok, 0};
metrics_([<<"Л"/utf8>>, <<"К"/utf8>>], [<<"Л"/utf8>>, <<"П"/utf8>>]) -> {ok, 0};
metrics_([<<"Л"/utf8>>, <<"Л"/utf8>>], [<<"Л"/utf8>>, <<"Х"/utf8>>]) -> {ok, 0};
metrics_([<<"П"/utf8>>, <<"К"/utf8>>], [<<"П"/utf8>>, <<"П"/utf8>>]) -> {ok, 0};
metrics_([<<"Х"/utf8>>, <<"К"/utf8>>], [<<"Х"/utf8>>, <<"Л"/utf8>>]) -> {ok, 5};
metrics_([<<"П"/utf8>>, <<"К"/utf8>>], [<<"К"/utf8>>, <<"П"/utf8>>]) -> {ok, 5};
metrics_([<<"П"/utf8>>, <<"П"/utf8>>], [<<"К"/utf8>>, <<"П"/utf8>>]) -> {ok, 5};
metrics_([<<"К"/utf8>>, <<"К"/utf8>>], [<<"Л"/utf8>>, <<"Л"/utf8>>]) -> {ok, 5};
metrics_([<<"К"/utf8>>, <<"К"/utf8>>], [<<"Л"/utf8>>, <<"Х"/utf8>>]) -> {ok, 5};
metrics_([<<"П"/utf8>>, <<"Л"/utf8>>], [<<"П"/utf8>>, <<"Х"/utf8>>]) -> {ok, 25};
metrics_([<<"П"/utf8>>, <<"Л"/utf8>>], [<<"К"/utf8>>, <<"Л"/utf8>>]) -> {ok, 25};
metrics_([<<"П"/utf8>>, <<"Л"/utf8>>], [<<"К"/utf8>>, <<"Х"/utf8>>]) -> {ok, 25};
metrics_([<<"П"/utf8>>, <<"Х"/utf8>>], [<<"К"/utf8>>, <<"Л"/utf8>>]) -> {ok, 25};
metrics_([<<"П"/utf8>>, <<"Х"/utf8>>], [<<"К"/utf8>>, <<"Х"/utf8>>]) -> {ok, 25};
metrics_([<<"Х"/utf8>>, <<"П"/utf8>>], [<<"П"/utf8>>, <<"Х"/utf8>>]) -> {ok, 25};
metrics_([<<"Х"/utf8>>, <<"П"/utf8>>], [<<"П"/utf8>>, <<"Л"/utf8>>]) -> {ok, 25};
metrics_([<<"Х"/utf8>>, <<"П"/utf8>>], [<<"К"/utf8>>, <<"Л"/utf8>>]) -> {ok, 25};
metrics_([<<"Х"/utf8>>, <<"П"/utf8>>], [<<"К"/utf8>>, <<"Х"/utf8>>]) -> {ok, 25};
metrics_(_, _) -> error.
%% === Iterator ================================================================
empty() -> fun() -> done end.
from_list(List) ->
Loop =
fun([]) -> done;
([H|T]) -> {ok, H, from_list(T)}
end,
fun() -> Loop(List) end.
take(N, Iterator) when N > 0 ->
take_(N, [], Iterator).
take_(0, Acc, I) -> {ok, lists:reverse(Acc), I};
take_(C, Acc, I) ->
case I() of
{ok, Data, Next} -> take_(C-1, [Data|Acc], Next);
done -> {ok, lists:reverse(Acc), empty()};
{error, _Reason} = Err -> Err
end.
fold(Fun, State, Iterator) ->
case Iterator() of
{ok, Data, Next} ->
fold(Fun, Fun(Data, State), Next);
done -> {ok, State};
{error, _Reason} = Err -> Err
end.
foreach(Fun, Iterator) ->
case Iterator() of
{ok, Data, Next} ->
_ = Fun(Data),
foreach(Fun, Next);
done -> ok;
{error, _Reason} = Err -> Err
end.
append(Iterator1, Iterator2) ->
fun() ->
case Iterator1() of
{ok, Data, Next} -> {ok, Data, append(Next, Iterator2)};
done -> Iterator2();
{error, _Reason} = Err -> Err
end
end.
dropwhen(Fun, Iterator) ->
fun() ->
case Iterator() of
{ok, Data, Next} ->
case Fun(Data) of
true -> done;
false -> {ok, Data, dropwhen(Fun, Next)}
end;
done -> done;
{error, _Reason} = Err -> Err
end
end.
zip(I1, I2) ->
fun() ->
{ok, D1, Next1} = I1(),
{ok, D2, Next2} = I2(),
{ok, {D1, D2}, zip(Next1, Next2)}
end.
by(N, I) ->
fun() ->
case take(N, I) of
{ok, Data, Next} ->
{ok, Data, by(N, Next)};
Other -> Other
end
end.
drop(N, I) ->
fun() ->
case I() of
{ok, Data, Next} ->
case N =:= 1 of
true -> Next();
false -> {ok, Data, drop(N-1, Next)}
end;
Other -> Other
end
end.
replace(N, Value, I) ->
fun() ->
case I() of
{ok, Data, Next} ->
case N =:= 1 of
true -> {ok, Value, Next};
false -> {ok, Data, replace(N-1, Value, Next)}
end;
Other -> Other
end
end.
add(1, Value, I) ->
fun() -> {ok, Value, I} end;
add(N, Value, I) ->
fun() ->
case I() of
{ok, Data, Next} ->
{ok, Data, add(N-1, Value, Next)};
Other -> Other
end
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment