2017-03-24 1 views
0

Ich verwende Rekursion, um zwei Zahlen zu vergleichen (ex 123 ist das gleiche mit 123) und speichern, wie viele Ziffern sie gemeinsam haben (ex 123 im Vergleich zu 123 hat 3 und mit 124 hat 2).Haskell vergleichen Problem

Während mein Programm diese Nummer findet, möchte ich Bedingungen für jede Situation setzen (zB wenn sie 2 Ziffern im gemeinsamen Ausgabewert haben 44 oder wenn sie 3 etwas anderes machen), aber es wird kein Vergleich gemacht. Kann mir bitte jemand erklären was und warum das passiert. Hier ist mein Code:

dg :: Int->Int->Int 
dg 0 0 = 0 
dg x y = if (c==2) then 23 else 24 -- c = common digits 
    where c = digits (x `div` 10) (y `div` 10) + if (x `mod` 10 == y `mod` 10) then 1 else 0   

betreibe ich Umarmungen Löschen der „if“ Bedingung, Eingang geben 10 10 ist der Ausgang 2, aber wenn ich es auf verlassen und erneut ausführen es, es geht bis 24 (während 23 korrekt ist). Ich bin wirklich verwirrt.

+0

Ich würde drehen Sie beide Zahlen in '[Char]' und dann verglichen glücklich die Listen, smth wie 'gemeinsame l1 l2 = [ e1 | e1 <- l1, elem e1 l2] ', obwohl es eine O (n^2) -Leistung hat. Der Vergleich der Listen ist besonders effizient, wenn Sie nur die Menge der gemeinsamen Elemente und nicht die Reihenfolge beachten. Sie können die beiden Listen sortieren. – 9000

+0

Was sind 'Ziffern'? Und warum benutzt du Umarmungen? – melpomene

Antwort

1

Um herauszufinden, wie viele Stellen zwei Int gemeinsam haben, die String-Darstellung mit nicht allzu schlecht ist (Es ist wirklich schrecklich, siehe Update unten).

commonDigits :: Int -> Int -> Int 
commonDigits a b = length . filter id $ zipWith (==) (reverse $ show a) (reverse $ show b) 

reverse wird benötigt, um sicherzustellen, dass die Ziffern richtig ausgerichtet sind.

Wenn Sie in Punkt-freie Art sind:

import Data.Function 

commonDigits :: Int -> Int -> Int 
commonDigits = fmap (length . filter id) . zipWith (==) `on` reverse . show 

Dann, wenn Sie eine spezielle Int je nach Ergebnis der commonDigits zurückkehren möchten, können Sie eine separate Funktion:

specialResult :: Int -> Int -> Int 
specialResult a b = 
    case commonDigits a b of 
    2 -> 23 
    3 -> 48 
    _ -> 256 

Update: Für negative ganze Zahlen ist diese Methode nicht gut. Wenn nur eines der Argumente negativ ist, sollte sich diese Funktion wie Ihre mod 10 Version verhalten. Wenn beide negativ sind, besteht die Möglichkeit, dass das Zeichen '-' als Ziffer gezählt wird.

Verwenden wir eine digits Funktion, die eine Ziffernliste für positive und negative Zahlen von den niedrigstwertigen bis zu den signifikantesten Ziffern enthält. Was passiert, wenn die Nummer 0 als Eingabe angegeben wird, sollten wir eine leere Liste oder [0] zurückgeben? Ihr Anruf bei diesem, aber ich gehe davon aus, Sie wollen [0].

digits :: Int -> [Int] 
digits 0 = [0] 
digits n = digits' (abs n) 
    where 
    digits' 0 = [] 
    digits' n = n `mod` 10 : digits' (n `div` 10) 

Mit dieser neuen digits Funktion wir commonDigits umschreiben kann:

commonDigits :: Int -> Int -> Int 
commonDigits = fmap (length . filter id) . zipWith (==) `on` digits 
Verwandte Themen