Here's an algorithm in Curry which takes n
and matches on two strings within edit distance n
of each other.
lev :: Eq a => Int -> [a] -> [a] -> ()
lev n (a : b) (a : c) =
lev n b c
lev n (_ : b) (_ : c) | n > 0 =
lev (n - 1) b c
lev n (_ : b) c | n > 0 =
lev (n - 1) b c
lev n b (_ : c) | n > 0 =
lev (n - 1) b c
lev n [] [] =
()
This modifies the naive recursive algorithm so that we limit the number of edits we can try. Once we try n
edits we give up.
If we translate this into Prolog we get
p(_, [], []).
p(N, [A|B], [A|C]) :-
p(N, B, C).
p(N, [_|B], C) :-
N>0,
p(N-1, B, C).
p(N, B, [_|C]) :-
N>0,
p(N-1, B, C).
p(N, [_|B], [_|C]) :-
N>0,
p(N-1, B, C).
While these do limit the number of edits they can try, there is no limit to the branching factor. So it has exponential running time with respect to the size of the input. In Prolog I can fix this with a cut:
p(_, [], []).
p(N, [A|B], [A|C]) :-
!, p(N, B, C).
p(N, [_|B], C) :-
N>0,
p(N-1, B, C).
p(N, B, [_|C]) :-
N>0,
p(N-1, B, C).
p(N, [_|B], [_|C]) :-
N>0,
p(N-1, B, C).
Now the branching factor is capped and this runs in linear time. However I can't make this same change in Curry since Curry lacks cuts.
What is the idiomatic Curry way to implement this?