Список понимается как целочисленная по длине функция - PullRequest
3 голосов
/ 24 июня 2009

Я пытаюсь выучить Эрланг, используя Каратэ Чоп Ката . Я перевел тест runit, предоставленный в ката, на тест eunit и запрограммировал небольшую функцию для выполнения поставленной задачи.

-module(chop).
-export([chop/2]).
-import(lists).
-include_lib("eunit/include/eunit.hrl").
-ifdef(TEST).
chop_test_() -> [
    ?_assertMatch(-1, chop(3, [])),
    ?_assertMatch(-1, chop(3, [1])),
    ?_assertMatch(0,  chop(1, [1])),
 ....several asserts deleted for brevity...
].
-endif.

chop(N,L) -> chop(N,L,0);
chop(_,[]) -> -1.
chop(_, [],_) -> -1;
chop(N, L, M) ->
    MidIndex = length(L) div 2,
    MidPoint = lists:nth(MidIndex,L),
    {Left,Right} = lists:split(MidIndex,L),
    case MidPoint of 
    _ when MidPoint < N -> chop(N,Right,M+MidIndex);
    _ when MidPoint =:= N -> M+MidIndex;
    _ when MidPoint > N -> chop(N,Left,M)
    end.

Компилируется нормально. Однако при выполнении теста (среди прочего) возникает следующая ошибка:

::error:badarg
 in function erlang:length/1
  called as length(1)
 in call from chop:chop/3

Я пробовал разные варианты объявления chop (N, [L], M) .... и использования длины ([L]), но не смог решить эту проблему. Любые предложения приветствуются.

пс. Как вы уже догадались, я неравнодушен к Эрлангу.

Ответы [ 4 ]

3 голосов
/ 24 июня 2009

Так что сейчас мне не хватает времени, но первая проблема, которую я вижу, состоит в том, что

chop(N,L) -> chop(N,L,0);
chop(_,[]) -> -1.

неверно, потому что chop (N, L) всегда будет совпадать. отмените пункты и посмотрите, к чему это приведет.

Кроме того, в случае списка из 1 элементов nth (0, [1]) завершится ошибкой. Я чувствую, что эти списки, вероятно, имеют 1 индекс.

0 голосов
/ 24 июня 2009

Как самая важная вещь для изучения, вы должны понимать, что использование двоичного поиска по спискам в erlang - неправильная идея, поскольку lists:nth/2 - это не O (1), а O (N) операция.Попробуйте list_to_tuple/1, а затем сделайте это на кортеже.Это стоит гораздо больше работы.

Также стоит попробовать его на модуле array.

0 голосов
/ 24 июня 2009

Похоже, что объединение замечаний Бена Хьюза решает проблему. Просто для полноты я вставляю реализацию бинарного поиска для прохождения тестов ниже.

chop(_,[]) -> -1;
chop(N,L) -> 
    Array = array:from_list(L),
chop(N,Array, 0, array:size(Array)-1).
chop(N, L, K, K) -> 
    Element = array:get(K,L),
    if 
        Element == N -> K; 
        true -> -1
    end;
chop(_, _, K, M) when M < K -> -1;
chop(N, L, K, M) ->
    MidIndex = K + ((M - K) div  2),
    MidPoint = array:get(MidIndex,L),
    case MidPoint of 
        N -> MidIndex;
        _ when MidPoint < N -> chop(N,L,MidIndex+1,M);
        _ -> chop(N,L,K,MidIndex-1)
    end.
0 голосов
/ 24 июня 2009

Функция erlang: length / 1 возвращает длину списка.

Вы назвали length (1), а 1 - это не список.

длина ([1]) вернет 1 длина ([1,2,3,4 [) вернет 4 и тд и тп ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...