Mam problem z nawracaniem na Haskell, wiem, jak wykonywać funkcje rekursywne, ale pojawia się problem, gdy próbuję uzyskać wiele rozwiązań lub najlepszy (cofanie).Implementacja śledzenia wstecznego na Haskell
Istnieje lista z pewnymi ciągami, a następnie muszę uzyskać rozwiązania, aby uzyskać ciąg od innego do zmieniającego jedną literę z ciągu, otrzymam listę, pierwszy ciąg i ostatni. Jeśli istnieje rozwiązanie zwraca liczbę kroków, które zrobił, jeśli nie ma rozwiązania, zwraca -1
. Oto przykład:
wordF ["spice","stick","smice","stock","slice","slick","stock"] "spice" "stock"
Wtedy mam listę i muszę zacząć "spice"
i dostać się do "stock"
i najlepszym rozwiązaniem jest ["spice","slice","slick","stick","stock"]
z czterech kroków, aby dostać się z "spice"
do "stock"
. następnie zwraca 4
.
Kolejne rozwiązanie to ["spice","smice","slice","slick","stick","stock"]
z pięcioma krokami, aby uzyskać "stock"
, a następnie zwraca `5. Ale jest to niewłaściwe rozwiązanie, ponieważ istnieje inny, który jest lepszy przy mniejszych krokach niż ten.
Mam kłopoty dokonywania Backtracking aby uzyskać najlepsze rozwiązanie, bo nie wiedzą, jak sprawić, że moje wyszukiwanie kodu innego rozwiązania i nie tylko jeden ..
Oto kod, który próbowałem zrobić, ale ja dostać jakieś błędy, btw ja nie wiem, czy mój sposób, żeby „zrobić” wycofywania jest dobre lub jeśli istnieją pewne błędy, które im nie widząc ..
wordF :: [String] -> String -> String -> (String, String, Int)
wordF [] a b = (a, b, -1)
wordF list a b | (notElem a list || notElem b list) = (a, b, -1)
| otherwise = (a, b, (wordF2 list a b [a] 0 (length list)))
wordF2 :: [String] -> String -> String -> [String] -> Int -> Int -> Int
wordF2 list a b list_aux cont maxi | (cont==maxi) = 1000
| (a==b) = length list_aux
| (a/=b) && (cont<maxi) && notElemFound && (checkin /= "ThisWRONG") && (wording1<=wording2) = wording1
| (a/=b) && (cont<maxi) && notElemFound && (checkin /= "ThisWRONG") && (wording1>wording2) = wording2
| (a/=b) && (checkin == "ThisWRONG") = wordF2 list a b list_aux (cont+1) maxi
where
checkin = (check_word2 a (list!!cont) (list!!cont) 0)
wording1 = (wordF2 list checkin b (list_aux++[checkin]) 0 maxi)
wording2 = (wordF2 list checkin b (list_aux++[checkin]) 1 maxi)
notElemFound = ((any (==(list!!cont)) list_aux) == False)
check_word2 :: String -> String -> String -> Int -> String
check_word2 word1 word2 word3 dif | (dif > 1) = "ThisWRONG"
| ((length word1 == 1) && (length word2 == 1) && (head word1 == head word2)) = word3
| ((length word1 == 1) && (length word2 == 1) && (head word1 /= head word2) && (dif<1)) = word3
| ((head word1) == (head word2)) = check_word2 (tail word1) (tail word2) word3 dif
| otherwise = check_word2 (tail word1) (tail word2) word3 (dif+1)
Moja pierwsza funkcja wordF2
uzyskać listę, początek , koniec, lista pomocnicza, aby uzyskać aktualne rozwiązanie z pierwszym elementem, który zawsze będzie tam ([a]
), licznik wi p 0
, a maksymalny rozmiar licznika (length list
) ..
i drugiej funkcji check_word2
sprawdza czy słowo może przejść do innego słowa, jak "spice"
do "slice"
jeśli cant jak "spice"
do "spoca"
powraca "ThisWRONG"
.
To rozwiązanie staje się naruszenia wzór meczu awarii
Program error: pattern match failure: wordF2 ["slice","slick"] "slice" "slick" ["slice"] 0 1
Próbowałam z małych spraw i nic, a ja ograniczając że dostanę złą pozycję na liście z obliczeniem i max.
Albo może być nie wiem jak zaimplementować wycofywania Haskell dostać wiele rozwiązań najlepszym rozwiązaniem, etc ..
UPDATE: Zrobiłem rozwiązaniem, ale jej nie backtracking
wordF :: [String] -> String -> String -> (String, String, Int)
wordF [] a b = (a, b, -1)
wordF list a b | (notElem a list || notElem b list) = (a, b, -1)
| otherwise = (a, b, (wordF1 list a b))
wordF1 :: [String] -> String -> String -> Int
wordF1 list a b | ((map length (wordF2 (subconjuntos2 (subconjuntos list) a b))) == []) = -1
| (calculo > 0) = calculo
| otherwise = -1
where
calculo = (minimum (map length (wordF2 (subconjuntos2 (subconjuntos list) a b))))-1
wordF2 :: [[String]] -> [[String]]
wordF2 [[]] = []
wordF2 (x:xs) | ((length xs == 1) && ((check_word x) == True) && ((check_word (head xs)) == True)) = x:xs
| ((length xs == 1) && ((check_word x) == False) && ((check_word (head xs)) == True)) = xs
| ((length xs == 1) && ((check_word x) == True) && ((check_word (head xs)) == False)) = [x]
| ((length xs == 1) && ((check_word x) == False) && ((check_word (head xs)) == False)) = []
| ((check_word x) == True) = x:wordF2 xs
| ((check_word x) == False) = wordF2 xs
check_word :: [String] -> Bool
check_word [] = False
check_word (x:xs) | ((length xs == 1) && ((check_word2 x (head xs) 0) == True)) = True
| ((length xs >1) && ((check_word2 x (head xs) 0) == True)) = True && (check_word xs)
| otherwise = False
check_word2 :: String -> String -> Int -> Bool
check_word2 word1 word2 dif | (dif > 1) = False
| ((length word1 == 1) && (length word2 == 1) && (head word1 == head word2)) = True
| ((length word1 == 1) && (length word2 == 1) && (head word1 /= head word2) && (dif<1)) = True
| ((head word1) == (head word2)) = check_word2 (tail word1) (tail word2) dif
| otherwise = check_word2 (tail word1) (tail word2) (dif+1)
subconjuntos2 :: [[String]] -> String -> String -> [[String]]
subconjuntos2 [] a b = []
subconjuntos2 (x:xs) a b | (length x <= 1) = subconjuntos2 xs a b
| ((head x == a) && (last x == b)) = (x:subconjuntos2 xs a b)
| ((head x /= a) || (last x /= b)) = (subconjuntos2 xs a b)
subconjuntos :: [a] -> [[a]]
subconjuntos [] = [[]]
subconjuntos (x:xs) = [x:ys | ys <- sub] ++ sub
where sub = subconjuntos xs
Mmm może być jego nieefektywnym rozwiązaniem, ale przynajmniej rozwiązuje ... Przeszukuję wszystkie możliwe rozwiązania, porównuję głowę == "plaster" i ostatnią == "zapasy", a następnie filtruję te, które są rozwiązaniem i wypiszę krótszy, dzięki a jeśli macie jakieś sugestie, to powiedzcie: