列表被视为长度函数的整数

发布于 2024-07-25 11:56:09 字数 1179 浏览 3 评论 0原文

我正在尝试使用 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

我尝试了声明 Chop(N,[L],M) .... 和使用 length([L]) 的不同排列,但还没有能够解决这个问题。 欢迎任何建议。

附: 正如你可能已经猜到的,我对 Erlang 很狂热。

I'm trying to learn Erlang using the Karate Chop Kata. I translated the runit test supplied in the kata to an eunit test and coded up a small function to perform the task at hand.

-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.

Compiles ok.Running the test however gives, (amongst others) the following failure:

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

I've tried different permutations of declaring chop(N,[L],M) .... and using length([L]) but have not been able to resolve this issue. Any suggestions are welcome.

ps. As you might have guessed I'm a nube when it comes to Erlang.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

亚希 2024-08-01 11:56:09

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

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

是错误的,因为 Chop(N,L) 总是匹配。 颠倒这些条款,看看会带来什么结果。

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

So I'm pressed for time at the moment, but the first problem I see is that

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

is wrong because chop(N,L) will always match. reverse the clauses and see where that gets you.

Beyond that, in the case of the 1 element list, nth(0, [1]) will fail. I feel like these lists are probably 1-indexed.

她说她爱他 2024-08-01 11:56:09

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

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

As most significant thing to learn you should realize, that using binary search for lists in erlang is wrong idea, because lists:nth/2 is not O(1) but O(N) operation. Try list_to_tuple/1 and than do it on tuple. It is much more worth work.

It can also be worth to try it on array module.

倾听心声的旋律 2024-08-01 11:56:09

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

您调用了 length(1) 并且 1 不是列表。

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

The function erlang:length/1 returns the length of a list.

You called length(1) and 1 isn't a list.

length([1]) would return 1
length([1,2,3,4[) would return 4
etc, etc...

素食主义者 2024-08-01 11:56:09

看来,结合本·休斯的言论就可以解决这个问题。 为了完整起见,我在下面粘贴了我的二分搜索的通过测试的实现。

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.

It appears that combining the remarks from Ben Hughes solves the problem. Just for completeness I'm pasting the tests-passing implementation of my binary search below.

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.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文