列表被设想为整数长度函数

时间:2009-06-23 22:43:47

标签: list erlang

我正在尝试使用Karate Chop Kata来学习Erlang。我将kata中提供的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

我尝试了不同的声明斩(N,[L],M)....和使用长度([L])的排列但是无法解决这个问题。欢迎任何建议。

PS。正如你可能已经猜到的那样,当谈到Erlang时,我就是个笨蛋。

4 个答案:

答案 0 :(得分:3)

所以我现在时间紧迫,但我看到的第一个问题是

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

错误,因为chop(N,L)将始终匹配。扭转这些条款,看看它在哪里。

除此之外,在1元素列表的情况下,nth(0,[1])将失败。我觉得这些列表可能是1索引的。

答案 1 :(得分:0)

函数erlang:length/1返回列表的长度。

你叫长度(1)而1不是列表。

长度([1])将返回1 长度([1,2,3,4 [)将返回4 等等...

答案 2 :(得分:0)

作为最重要的学习内容你应该意识到,在erlang中使用二进制搜索列表是错误的想法,因为lists:nth/2不是O(1)而是O(N)操作。尝试list_to_tuple/1而不是在元组上执行。这是值得的工作。

array模块上尝试它也是值得的。

答案 3 :(得分:-1)

似乎结合Ben Hughes的言论解决了这个问题。为了完整起见,我将粘贴下面的二进制搜索的测试传递实现。

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.