2009-06-23 10 views
3

konzipiert Ich versuche Erlang mit der Karate Chop Kata zu lernen. Ich übersetzte den in den Kata gelieferten Runit-Test in einen Eunit-Test und programmierte eine kleine Funktion, um die anstehende Aufgabe zu erfüllen.Liste ist als Integer von Länge Funktion

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

Compiliert ok.Running den Test jedoch gibt, (unter anderem) die folgenden Fehler an:

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

ich verschiedene Permutationen erklärt chop (N, [L], M) versucht haben. ... und mit Länge ([L]), konnte dieses Problem jedoch nicht lösen. Irgendwelche Vorschläge sind willkommen.

ps. Wie du vielleicht vermutet hast, bin ich ein Nube, wenn es um Erlang geht.

Antwort

3

Also für die Zeit bin ich im Moment gedrückt , aber das erste Problem, das ich sehe, ist, dass

ist falsch, weil chop (N, L) wird immer übereinstimmen. Reverse die Klauseln und sehen, wo Sie das bekommt.

Darüber hinaus wird nth (0, [1]) im Falle der 1-Element-Liste fehlschlagen. Ich habe das Gefühl, dass diese Listen wahrscheinlich 1-indexiert sind.

0

Die Funktion erlang:length/1 gibt die Länge einer Liste zurück.

Sie haben Länge (1) und 1 ist keine Liste.

Länge ([1]) zurückkehren würde 1 Länge ([1,2,3,4 [) zurückkehren würde 4 etc, etc ...

+0

Guter Link für nicht Windows-Benutzer! – rdo

-1

Es scheint, dass die Kombination der Bemerkungen von Ben Hughes das Problem löst. Nur der Vollständigkeit halber füge ich die Tests-Weitergabe meiner binären Suche unten hinzu.

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

Schöne Übung, Sie versehentlich O (N * logN) -Lösung für das Problem gemacht, die in O (N) gelöst werden sollte, wenn Sie versuchen, O (LogN) Methode auf falsche Datenstruktur. –

+0

Der vorherige Kommentar ist aufgrund des Neuschreibens veraltet. Aber ich bin sicher, dass Hynek noch Verbesserungen finden kann. ;-). –

0

Als wichtigste Sache, die Sie lernen sollten erkennen, dass für die Listen in erlang binäre Suche ist eine falsche Vorstellung, weil lists:nth/2 nicht O (1), aber O (N) Betrieb. Versuchen Sie list_to_tuple/1 und dann tun Sie es auf Tupel. Es ist viel mehr wert, zu arbeiten.

Es kann auch wert sein, es auf array Modul zu versuchen.