Search code examples
recursionerlang

How to Find the Widest Valley


There are list of numbers which represent size of blocks and I want to find out biggest Valley shape in the list. Constraint is that unlike normal valley two end can be flat like in following example [5, 5] is still counts as valley end

Some examples; [1, 5, 5, 2, 8] => [5, 5, 2, 8] widest valley [2, 6, 8, 5] => [2,6,8] widest valley [9, 8, 13, 13, 2, 2, 15, 17] => [13, 13, 2, 2, 15, 17] widest valley

It's not a homework or something but I am wondering how I can solve it in Erlang

I solved it in another language but Erlang is a bit recursive that's why I need some help


Solution

  • I'm no expert, but I'd solve the problem like this:

    -record(valley, {from=1, to=1, deepest=1}).
    
    widest_valley([]) ->
        [];
    widest_valley([H]) ->
        [H];
    widest_valley([H,T]) ->
        [H,T];
    widest_valley(L) ->
        widest_valley(L, #valley{}, #valley{}, 1, 2).
    
    widest_valley(L, _Curr, Widest, _FlatFrom, Pos) when Pos > length(L) ->
        lists:sublist(L, Widest#valley.from, 1 + Widest#valley.to - Widest#valley.from);
    widest_valley(L, Curr, Widest, FlatFrom, Pos) ->
        Before  = lists:nth(Pos - 1, L),
        AtPos   = lists:nth(Pos, L),
        Deepest = lists:nth(Curr#valley.deepest, L),
        Curr1 = if Before == Deepest ->
                        Curr#valley{deepest = if AtPos < Deepest ->
                                                      Pos;
                                                 true            ->
                                                      Curr#valley.deepest
                                              end};
                   AtPos < Before ->
                        #valley{from=FlatFrom, deepest=Pos};
                   true ->
                        Curr
                end,
        FlatFrom1 = if AtPos == Before ->
                            FlatFrom;
                       true ->
                            Pos
                    end,
        Widest1 = if Pos - Curr1#valley.from > Widest#valley.to - Widest#valley.from ->
                          Curr1#valley{to=Pos};
                     true ->
                          Widest
                  end,
        widest_valley(L, Curr1, Widest1, FlatFrom1, Pos + 1).