[erlang-questions] Matrix rotator

Bryan Fink <>
Mon Jun 15 04:41:25 CEST 2009


On Sun, Jun 14, 2009 at 4:24 PM, Tony Arcieri<> wrote:
> On Sun, Jun 14, 2009 at 2:08 PM, Johnny Billquist <> wrote:
>
>> The problem is rather trivial in itself. Are you looking for some
>> particularly efficient algorithm, or what?
>>
>
> Whatever you'd like, but creative or clever solutions are always
> interesting.

Oh, hell - why not?  I'll submit:

rotate([])     -> [];
rotate(Matrix) -> rotate(Matrix, []).

rotate([[]|_], Acc) -> Acc;
rotate(Matrix, Acc) ->
    rotate([ Tail || [_|Tail] <- Matrix],
            [[ Head || [Head|_] <- Matrix ]|Acc]).

If I count correctly, the above is 1 intermediate list created (the
"next tails")  and 2 list-reversals (each list-comp) for each row of
input.  I was also able to come up with a version that made the
tradeoff of 50% more intermediate lists, but a quarter of the
reversals (again, if I count correctly).  It also cuts out half the
traversals of the list of rows.  That code is below, but is nowhere
near as concise:

rotate([]) -> [];
rotate(Matrix) ->
    rotate(forward, lists:reverse(Matrix), [ [] || _ <- hd(Matrix) ]).

rotate(forward, [], Acc) -> lists:reverse(Acc);
rotate(backward, [], Acc) -> Acc;
rotate(forward, [Row|Rest], Acc) ->
    rotate(backward, Rest, prepend(Row, Acc));
rotate(backward, [Row|Rest], Acc) ->
    rotate(forward, Rest, prepend(lists:reverse(Row), Acc)).

prepend(From, To) -> prepend(From, To, []).
prepend([Hf|Tf], [Ht|Tt], Acc) -> prepend(Tf, Tt, [[Hf|Ht]|Acc]);
prepend([], [], Acc)           -> Acc.

-Bryan


More information about the erlang-questions mailing list