% file: "smith.erl"
-ifdef(ETOS).
-define(IS_INTEGER(X),is_integer(X)).
-else.
-define(IS_INTEGER(X),integer(X)).
-endif.
-module(smith).
-export([?MODULE/0]).
?MODULE() ->
Tops = generate_sequences(100,32,1),
Side = generate_sequence(32,0),
statistics(runtime),
R = loop(2,Tops,Side,0),
{R,R =:= 16}.
max(A,B) when ?IS_INTEGER(A), ?IS_INTEGER(B) ->
if
A > B -> A;
true -> B
end.
alpha_beta_penalty(A,B) when ?IS_INTEGER(A), ?IS_INTEGER(B) -> max(A-4,B-1).
generate_sequence(Length,R) when ?IS_INTEGER(Length) ->
if
Length == 0 -> [];
true -> [R rem 10 | generate_sequence(Length-1,
(R * 11 + 1237501)
rem 10067)]
end.
generate_sequences(0,_,_) -> [];
generate_sequences(N,Length,R) when ?IS_INTEGER(N), ?IS_INTEGER(Length) ->
[generate_sequence(Length, R) | generate_sequences(N-1,Length,R+1)].
match_entry(Top,Side,UpperLeft,Upper,Left) when ?IS_INTEGER(Top), ?IS_INTEGER(Side) ->
MeLeft = alpha_beta_penalty(element(3, Left), element(1, Left)),
MeUpper = alpha_beta_penalty(element(3, Upper), element(2, Upper)),
MeUpperLeft =
if
Top == Side ->
max(MeLeft,
max(MeUpper,
max(element(3,UpperLeft)+1,0)));
true ->
max(MeLeft,
max(MeUpper,
max(element(3,UpperLeft),0)))
end,
{MeLeft, MeUpper, MeUpperLeft,
max(MeUpperLeft,
max(element(4,Left),
max(element(4,Upper),element(4,UpperLeft))))}.
match_zero_entry(Top,Side,{Left,_,UpperLeft,Max}) when ?IS_INTEGER(Top), ?IS_INTEGER(Side) ->
ELeft = alpha_beta_penalty(UpperLeft, Left),
Weight = max(1-abs(Side-Top),0),
EUpperLeft = max(max(ELeft,max(1-abs(Side-Top),0)),0),
EMax = max(max(Max,EUpperLeft),0),
{ELeft, -1, EUpperLeft, EMax}.
match(Tops,Side,Prev,UpperLeft,Left) ->
match0(Tops, Side, Prev, UpperLeft, Left, [], none).
match0([],_,_,_,_,Acc,Last) -> {Acc,Last};
match0([Top|Tops],Side,[Upper|Prev],UpperLeft,Left,Acc,Last) when
?IS_INTEGER(Top), ?IS_INTEGER(Side) ->
E = match_entry(Top, Side, UpperLeft, Upper, Left),
match0(Tops, Side, Prev, Upper, E, [E|Acc], E);
match0([Top|Tops],Side,none,UpperLeft,Left,Acc,Last) when
?IS_INTEGER(Top), ?IS_INTEGER(Side) ->
E = match_zero_entry(Top, Side, Left),
match0(Tops, Side, none, UpperLeft, E, [E|Acc], E).
match_two_seq(Side,Top,Prev) ->
match_two_seq0(Side, Top, Prev, none).
match_two_seq0([],_,_,Result) -> Result;
match_two_seq0([S|Side],Top,Prev,Acc) when ?IS_INTEGER(S) ->
{Row,Result} = match(Top,S,Prev,{0,0,0,0},{0,0,0,0}),
match_two_seq0(Side, Top, Row, Result).
match_sequences(Tops,Side) ->
match_sequences0(Tops, Side, -9999999).
match_sequences0([],_,MaxResult) -> MaxResult;
match_sequences0([Top|Tops],Side,CrntResult) ->
Result = element(4, match_two_seq(Top, Side, none)),
match_sequences0(Tops, Side, max(CrntResult, Result)).
loop(0,Tops,Side,R) -> R;
loop(N,Tops,Side,R) -> loop(N-1,Tops,Side,match_sequences(Tops,Side)).