[Prolog] Rekursiv die Anzahl der Elemente einer Liste bestimmen

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • [Prolog] Rekursiv die Anzahl der Elemente einer Liste bestimmen

    Moin zusammen!

    für mich ist Prolog neu, und ich habe noch einige Schwierigkeiten mit der Denkweise bei der Arbeit mit einer deklarativen Programmiersprache. Vielleicht könnt ihr mir beim Lösen der im Titel genannten Aufgabe helfen - das wäre für mich eine echte Hilfe!

    Es geht darum, dass bei folgendem Aufruf folgendes Ergebnis herauskommt:

    Quellcode

    1. count_rek([1,2,3,4],Count).
    2. Count = 4
    3. yes


    Mein Problem dabei ist, dass ich nicht weiß, wie sich Count hochzählen lässt, bzw. wie man erreichen kann, dass Prolog dies tut.

    Mein Code sieht derzeit wie folgt aus:

    Quellcode

    1. count_rek([],0).
    2. count_rek([_|R],Count) :- count_rek(R,Count + 1).


    Für den trivialen Fall, dass die Liste leer ist, wird der Count korrekt mit 0 ausgegeben. Für die anderen Fälle haut der Code natürlich nicht hin. Teilweise weiß ich zwar wieso, aber ich weiß nicht, wie ich das Programm verändern kann, damit es funktioniert. Kann mir bitte jemand eine Hilfestellung geben?
  • Der "triviale" Fall, die leere Liste ist absolut richtig, den brauchst du natürlich für den Rekursionsabbruch. Der nicht triviale Teil sieht so aus: Du hast zwei Parameter, die Liste und Count, und du weißt dass die Liste nicht leer sein kann, da Prolog sonst die andere Regel angewendet hätte. Der Trick ist die Verwendendung der Funktion tail (wenn du mit Listen arbeitest kannst du fast alle Probleme auf die Verwendung von head und tail zurückführen). Tail gibt die Liste ohne ihr erstes Element zurück. Du rufst einfach die Funktion nochmal auf, mit tail(R) und Count + 1 und dann sollte es eigentlich auch schon funktionieren. Du reduzierst mit jedem Rekursionsaufruf die Liste um ein Element und erhöst Count um einen, bis die Liste leer ist - dann gibst du Count aus.
    ~ mfg SeBa

    Ich beantworte keine PMs zu Computer-/Programmierproblemen. Bitte wendet euch an das entsprechende Forum.

    [Blockierte Grafik: http://i.creativecommons.org/l/by-sa/3.0/80x15.png]
  • Hi SeBa!

    mache ich das in meinem Code nicht eigentlich schon in der zweiten Zeile? Das Ding ist, dass ich für diese Aufgabe keine Prädikate verwenden darf, die schon im System vordefiniert sind. Wenn ich "count_rek([1],Count)" aufrufe, gibt er mir "false" aus, obwohl Count ja 1 sein müsste.

    Ich habe es mittlerweile geschafft, dass er den korrekten Count ausgibt, jedoch nicht durch eine Zahl, sondern einen mathematischen Term. Wenn ich den obigen Aufruf mit folgenden Code mache:

    Quellcode

    1. count_rek([],0) :- true.
    2. count_rek([_|R],Count + 1) :- count_rek(R,Count).


    Gibt Prolog "Count = 0+1." aus.

    Nun weiß ich, dass man für die Evaluierung von Ausdrücken "is" verwenden soll. Wenn ich aber schreibe

    Quellcode

    1. count_rek([],0) :- true.
    2. count_rek([_|R],Count is Count + 1) :- count_rek(R,Count).


    gibt er "Count = (0 is 0+1)." aus.

    Ich weiß langsam nichtmehr weiter.. Was mache ich falsch?
  • Ich gucke definitiv zu selten in dieses Forum. Ich habe grade kein Prolog zu Hand, aber ich versuchs trotzdem mal. Was ein ganz typischer Denkefehler bei Prolog ist, ist dass man Variablen nicht einfach verändern kann. Eine Variable kann in einem Aufruf nur einen Wert bekommen, Sachen wie N is N + 1 gehen deswegen nicht.

    Quellcode

    1. count_rek([],0).
    2. count_rek([_|R],Count) :- count_rek(R,Count1), Count is Count1 + 1.


    Meinen vorherigen Post kannst du vergessen, weil Tail darfst du ja nicht benutzen (ist ja ein eingebautes Prädikat), aber das erledigst du ja schon mit [_|R].War also Schwachsinn. Ich hoffe es hilft dir jetzt noch.
    ~ mfg SeBa

    Ich beantworte keine PMs zu Computer-/Programmierproblemen. Bitte wendet euch an das entsprechende Forum.

    [Blockierte Grafik: http://i.creativecommons.org/l/by-sa/3.0/80x15.png]