Autor Thema: Scheme Funktion Vergleich zweier Listen liefert nicht das erwartete Ergebnis  (Gelesen 2349 mal)

Manuela

  • Member
Hi,

inzwischen nähere ich mich an die Funktion an, die ich haben will. Eigentlich sollte #t oder #f rauskommen, tut es leider nicht  :(

\version "2.19.32"

\language "deutsch"

myMusik= < c  e  >
myChords=\chordmode { c }

#(define (pitch-equals? p1 p2)
   (and
    (= (ly:pitch-alteration p1) (ly:pitch-alteration p2))
    (= (ly:pitch-notename p1) (ly:pitch-notename p2))))

#(define vergleichs-versuch?
   ;; wir versuchen zu eruieren
   ;; ob alle Elemente der Liste l1 in l2 enthalten sind
   ;; genauer gesagt müssen nur notename und alteration stimmen
   ;; die Oktavlage interessiert uns nicht
   (lambda ( l1 l2 )
     ( cond
       ;; zunächst prüfen wir, ob die Testliste bereits erschöpft ist
       ;; wenn ja dann ist es wahr
       ((null? l1) #t)
       ;; wenn die Zielliste erschöpft ist
       ;; ist es falsch
       ((null? l2) #f)
       ;; wir überprüfen das erste Element der Testliste
       ;; wenn es gleich dem ersten Element der Zielliste ist
       ;; dann können wir mit dem restlichen Teil der Testliste fortsetzen
       ((pitch-equals? (car l1) (car l2))
        vergleichs-versuch? (cdr l1) l2
        )
       ;; ansonsten versuchen wir es mit dem folgenden Element der Zielliste
       (else vergleichs-versuch? l1 (cdr l2))
       )
     )
   )

#(define ListeI (music-pitches myMusik))
#(define ListeII (music-pitches myChords))
#(display (vergleichs-versuch? ListeI ListeII))

Rauskommen tut das:

(#<Pitch c' > #<Pitch e' > #<Pitch g' >)

Was mache ich falsch?

Update: das habe ich inzwischen selbst rausgefunden, was waren wieder einmal die Klammern  ::)
« Letzte Änderung: Freitag, 25. März 2016, 20:25 von Manuela »

harm6

  • Member
Re: Scheme Funktion Vergleich zweier Listen liefert nicht das erwartete Ergebnis
« Antwort #1 am: Freitag, 25. März 2016, 21:23 »
Halo Manuela,

Du bist etwas zu optimistisch mit Deinem coding, teste mal mit:

myMusik= < c e >
myChords= < e c >

Um das Problem zu lösen, sortiere die Listen zuvor, z.B.:

#(define (pitch-equals? p1 p2)
   (and
    (= (ly:pitch-alteration p1) (ly:pitch-alteration p2))
    (= (ly:pitch-notename p1) (ly:pitch-notename p2))))

#(define vergleichs-versuch?
   ;; wir versuchen zu eruieren
   ;; ob alle Elemente der Liste l1 in l2 enthalten sind
   ;; genauer gesagt müssen nur notename und alteration stimmen
   ;; die Oktavlage interessiert uns nicht
   (lambda ( l1 l2 )
     ( cond
       ;; zunächst prüfen wir, ob die Testliste bereits erschöpft ist
       ;; wenn ja dann ist es wahr
       ((null? l1) #t)
       ;; wenn die Zielliste erschöpft ist
       ;; ist es falsch
       ((null? l2) #f)
       ;; wir überprüfen das erste Element der Testliste
       ;; wenn es gleich dem ersten Element der Zielliste ist
       ;; dann können wir mit dem restlichen Teil der Testliste fortsetzen
       ((pitch-equals? (car l1) (car l2))
        (vergleichs-versuch? (cdr l1) l2)
        )
       ;; ansonsten versuchen wir es mit dem folgenden Element der Zielliste
       (else (vergleichs-versuch? l1 (cdr l2)))
       )
     )
   )

#(define ListeI (music-pitches myMusik))
#(define ListeII (music-pitches myChords))
#(write-me
  "vergleichs-versuch? "
  (vergleichs-versuch? (sort ListeI ly:pitch<?)  (sort ListeII ly:pitch<?)))


Die absolute Kurzfassung:
myMusik= < c f >
myChords= < e c >
#(define ListeI (music-pitches myMusik))
#(define ListeII (music-pitches myChords))

#(write-me "test "
  (every (lambda (x) (->bool (member x ListeII))) ListeI))

`->bool' ist allerdings noch nicht mal im guile-manual zu finden, aber die Definition ist simpel,  kann man sich holen mittels:

guile> (procedure-source ->bool)
(lambda (x) (not (not x)))
guile>

Gruß,
  Harm

Manuela

  • Member
Re: Scheme Funktion Vergleich zweier Listen liefert nicht das erwartete Ergebnis
« Antwort #2 am: Freitag, 25. März 2016, 21:32 »
Harm, du hast natürlich recht wie immer, danke  :D
Und wieder einmal staune ich...

Wie kriege ich die pitch-equals? Funktion mit dem bool-Ausdruck verknüpft?

harm6

  • Member
Re: Scheme Funktion Vergleich zweier Listen liefert nicht das erwartete Ergebnis
« Antwort #3 am: Freitag, 25. März 2016, 23:12 »
Zitat von: Manuela
Wie kriege ich die pitch-equals? Funktion mit dem bool-Ausdruck verknüpft?

Warum solltest Du?
`pitch-equals?' gibt sowieso immer ein boolean zurück, afaict.

Gruß,
  Harm

Manuela

  • Member
Re: Scheme Funktion Vergleich zweier Listen liefert nicht das erwartete Ergebnis
« Antwort #4 am: Samstag, 26. März 2016, 06:38 »
Es soll kein Unterschied zwischen f / f, / f' / f'' gemacht werden.
bool liefert nur dann gleich, wenn auch die Oktave stimmt.
Man könnte eine Funktion vorsetzen, die alle Oktavewerte der Pitches gleich macht. Aber da bin ich wieder mal überfordert...

Noch eine Frage: eine Funktion, die aus einer Liste ls von n Elementen eine Liste macht, die aus Listen besteht, wo von ls jeweils k Elemente weggelassen werden?

Ich weiß gar nicht, wie ich dir danken soll. Ich bin meinem Ziel schon sehr nahe, muss nur noch den Musikoutput hinkriegen (siehe anderer Thread)

Update: hab was gefunden, kann es jetzt aber nicht ausprobieren, da keine Zeit und auf einem Computer. Ich poste den Code hier, damit ich ihn auch wiederfinde  ;)

(define (combinations k nlst)
  (cond ((zero? k)
         '(()))
        ((null? nlst)
         '())
        (else
         (append (map (lambda (k-1)
                        (cons (car nlst) k-1))
                      (combinations (- k 1) (cdr nlst)))
                 (combinations k (cdr nlst))))))
« Letzte Änderung: Samstag, 26. März 2016, 06:48 von Manuela »

harm6

  • Member
Re: Scheme Funktion Vergleich zweier Listen liefert nicht das erwartete Ergebnis
« Antwort #5 am: Samstag, 26. März 2016, 11:14 »
Zitat
Es soll kein Unterschied zwischen f / f, / f' / f'' gemacht werden.
bool liefert nur dann gleich, wenn auch die Oktave stimmt.

member hat ein optionales Argument, wie, d.h. mit welcher Methode verglichen wird.
Also:

\version "2.19.32"

#(define (pitch-equals? p1 p2)
   (and
    (= (ly:pitch-alteration p1) (ly:pitch-alteration p2))
    (= (ly:pitch-notename p1) (ly:pitch-notename p2))))

myMusik= < c f' >
myChords= < e c >
#(define ListeI (music-pitches myMusik))
#(define ListeII (music-pitches myChords))

#(write-me "test "
  (every (lambda (x) (->bool (member x ListeII pitch-equals?))) ListeI))

Zitat
Noch eine Frage: eine Funktion, die aus einer Liste ls von n Elementen eine Liste macht, die aus Listen besteht, wo von ls jeweils k Elemente weggelassen werden?

Es gibt take, take-right, drop, drop-right, list-head, list-tail siehe guile-manual.
Reicht das?

Gruß,
  Harm

Manuela

  • Member
Re: Scheme Funktion Vergleich zweier Listen liefert nicht das erwartete Ergebnis
« Antwort #6 am: Samstag, 26. März 2016, 15:15 »
Nochmals Danke Harm.

Ich habe das gefunden, das macht, was ich will:

\version "2.19.38"

#(define (combs k nlst)
   (cond ((zero? k)
          '(()))
     ((null? nlst)
      '())
     (else
      (append (map (lambda (k-1)
                     (cons (car nlst) k-1))
                (combs (- k 1) (cdr nlst))
                )
        (combs k (cdr nlst))
        )
      )
     )
   )

Du erledigst das wahrscheinlich in einer Zeile  ;)

Update: ich sehe gerade, den Code habe ich eh schon weiter oben gepostet  :-[
« Letzte Änderung: Samstag, 26. März 2016, 15:18 von Manuela »

fugenkomponist

  • Member
Re: Scheme Funktion Vergleich zweier Listen liefert nicht das erwartete Ergebnis
« Antwort #7 am: Samstag, 26. März 2016, 16:06 »
Du erledigst das wahrscheinlich in einer Zeile  ;)
Viel einfacher gehts nicht, nein. Man könnte ein bisschen an der Codeformatierung arbeiten, z. B. brauchen die ganzen schließenden Klammern eigentlich keine eigene Zeile:
#(define (combs k liste)
   (cond
    ((zero? k) '(()))
    ((null? liste) '())
    (else
     (append
      (map
       (lambda (t) (cons (car liste) t))
       (combs (1- k) (cdr liste)))
      (combs k (cdr liste))))))
In Scheme gehts nunmal nicht viel kürzer.

Andere Sprachen sparen da mehr ein, z. B. Haskell:
combs 0 _      = [[]]
combs _ []     = []
combs k (l:ls) = map (l:) (combs (k-1) ls) ++ combs k ls
Scheme → Haskell
append → (++)
cond → pattern matching
cons → (:)
(car liste) und (cdr liste) → liste als pattern (l:ls)
(lambda (t) (cons … t)) → (:) teilweise auswerten ohne explizites λ
« Letzte Änderung: Samstag, 26. März 2016, 16:08 von fugenkomponist »