I admitted defeat on an elegant solution for part 2 and came here seeking enlightenment. Disappointed there’s nothing simple and clean.
Part 1, I was tolerably happy with:
p1(InputData) ->
length([Row || Row <- InputData, safe(util:str_to_ints(Row))]).
safe(L) ->
safe(L, 0) =:= length(L) - 1.
safe([_H], A) -> abs(A);
safe([H | T], A) when A >= 0 andalso H < hd(T) andalso H >= hd(T) - 3 -> safe(T, A + 1);
safe([H | T], A) when A =< 0 andalso H > hd(T) andalso H =< hd(T) + 3 -> safe(T, A - 1);
safe(_, _) -> 0.
(See my Day 1 post for utility & unit test functions).
Note that the incrementing/decrementing guards (A >= 0
and A =< 0
respectively) are actually superfluous, but would make it more efficient with longer input rows.