www.jammni.de

Logo - Kleiner Drache
Login
Username:

Passwort:

Daten merken
Auto-Login
Registrieren
 
Online
niemand
 
Forumsuche
Suche nach:

Logo - DracheHaskell-Forum

Märchenfigur

Gepostet:
01.05.2011 15:11

Probleme mit ^^, ^, ** und \'fold\'  
Hallo.

ich hab da gerade ein Problem, wo ich schon seit gestern nicht mehr weiter komme. Ich dachte, wenn ich mal darüber schlafe wird das schon, hat aber nichts gebracht.

Ich soll eine wie ich finde ziemlich umständliche und nutzlose funktion schreiben, die als Eingabe [[Integer]] erhält und dann sowas ausrechnet wie: b1 ^(b2 ^(b3 ^(b4 ...))...) wobei jedes bi berechnet wird durch eine Kette von Subtraktionen von allen Elementen eines Elementes der Eingabe
Smilie
Ein Beispiel wäre sicherlich hilfreich
eingabe: [[10,3,4],[15,4,3],[5,2]]
rechnung: ((10-3)-4) ^ (((15-4)-3) ^ (5-2))
___________b1____^___(_b2____^_b3 )
Ausgabe: na, das Ergebnis eben

das ganze soll auch mit der Funktion foldr oder foldl implementiert werden

bisher habe ich das geschafft:

dingens :: [[Integer]] -> Integer
dingens (xs) = foldl (^^) (bi (concat (take 1 xs))) (map bi xs)


-- die funktion bi funktioniert schon so, wie sie soll
bi :: [Integer] -> Integer
bi (x : xs) = foldl (-) (x) (xs)


ich bekomm mit jedem operator, in zeile 2, ob ich jetzt ^, ^^ oder ** verwende immer nur fehlermeldungen, dass da was mit den werten nicht stimme.

No Instance for (fractional Integer)
arising from a use of \'^^\'
in the first argument of \'foldl\', namely \'(^^)\' ...

also die funktion foldl versteh ich im moment so, dass foldl (+) (5) [2,4,1,5] ausrechnet (((5+2)+4)+1)+5 und foldr eben 5+(2+(4+(1+5))). Stimmt das?
Zum Seitenanfang    
 
Landei

Gepostet:
02.05.2011 09:19

   
Hoogle sagt: (^^) :: (Fractional a, Integral b) => a -> b -> a

Da du nur Integers hast, musst du diese entweder zu Fractional konvertieren (fromIntegeral war das, glaub ich), oder dir deine eigene power-Funktion schreiben, was wahrscheinlich übersichtlicher wird. Lustigerweise habe ich dazu gerade ein Frage auf StackOverflow beantwortet ( http://stackoverflow.com/questions/5852084/haskell-power-function/5854132#5854132 ):


power _ 0 = 1
power 0 _ = 0
power x n = let sqr k = k * k
half_n = n `div` 2
sqrHalfPower = sqr ( power x half_n )
in if even n then sqrHalfPower else x * sqrHalfPower


Eine \"naive\" Version wäre

power :: Integer -> Integer -> Integer
power a n = product (replicate (fromInteger n) a)


Nun brauchst du noch ein Start-Element - ihr dürft ja sicher foldl0 nicht nehmen, was hier eigentlich die richtige Lösung wäre. Dazu würde ich let und pattern matching verwenden:


dingens :: [[Integer]] -> Integer
dingens xss = let (x:xs) = map bi xss
in foldl power x xs


Natürlich scheitert der Code für null- und einelementige Listen.
Zum Seitenanfang    
 
Märchenfigur

Gepostet:
02.05.2011 17:00

   
TOP
danke.

hab\'s gleich mal ausprobiert und jetzt funktioniert es auch.
Das eigentlich entscheidende für mich war, dass ich mir ja meine eigene Funktion schreiben kann, wenn ich mit den vorgegebenen nicht klar komme.

Weil wir das ja eigentlich selber machen sollten, hab ich dann auch ne eigene power funktion geschrieben:
hoch :: Integer -> Integer -> Integer
hoch 0 _ = 0
hoch _ 0 = 1
hoch x y = x * hoch x (y-1)
funktioniert ja so weit

Die Funktion für dingens hab ich noch so, wie im ersten post. Meine alte Funktion scheint auch richtig zu funktionieren. Bei deinem Vorschlag hab ich noch nicht ganz durchgeblickt Zum einen scheint da nicht das gewünschte rauszukommen, zum anderen versteh ich noch nicht so genau, was das \'let (x:xs)\' bewirkt

also wenn ich nach dieser Funktion [[4,2],[5,3],[6,2]] ausrechnen will, kommt 256 raus.
müssten aber (4-2) ^ ((5-3) ^ (6-2)) = 2 ^ (2 ^ 4) = 2 ^ 16 raus kommen.

mit dem let kenn ich mich noch nicht so gut aus. Muss ich aber umbedingt schnell lernen, also wollte ich gleich mal fragen, wie es in diesem beispiel funktionieren sollte.

danke soweit schonmal für die Hilfe
Zum Seitenanfang    
 
Landei

Gepostet:
02.05.2011 21:23

   
Meine Funktion rechnet (2 ^ 2) ^ 4 = 4 ^ 4 = 256. Andersrum (wie du es willst) ginge, wenn man in meinem dingens einfach foldl durch foldr ersetzten würde.

Das mit dem let ist einfach. Man könnte auch Schritt für Schritt schreiben:

dingens :: [[Integer]] -> Integer
dingens xss = let liste = map bi xss
x = head liste
xs = tail liste
in foldl power x xs


Bei der Zuweisung darf man nun auch Patterns benutzen, wie für Funktionsargumente. Die Liste wird also mit (x:xs) = ... schon während der Zuweisung \"seziert\".

Ich finde es übrigens gut, wie du selbst experimentierst. Kennst du eigentlich schon http://learnyouahaskell.com/chapters (leider Englisch)?
Zum Seitenanfang    
 
Märchenfigur

Gepostet:
05.05.2011 16:45

   
vielen Dank für die Antwort.

tut mir leid, dass ich erst jetzt schreibe, aber ich hatte die letzten Tage noch andere Dinge, die meine Aufmerksamkeit benötigten. Ich wollte nur nicht, dass ich dastehe, wie einer, der sich nicht um die antworten schert, die man zu seiner Frage gegeben hat.

das mit let (x:xs) habe ich dann auch verstanden, danke.
Zum Seitenanfang