I have a problem with returning to Haskell, I know how to perform recursive functions, but I have problems when I try to get some solutions or better (reverse search).
There is a list with some lines, then I need to get solutions to go from line to line, changing one letter from a line, I will get a list, the first line and the last. If there is a solution, return the counter of the steps that he took; if there is no solution, it returns -1 . here is an example:
wordF ["spice","stick","smice","stock","slice","slick","stock"] "spice" "stock"
Then I have my list, and I need to start with "spice" and go to "stock" and the best solution is ["spice","slice","slick","stick","stock"] with four steps for transition from "spice" to "stock" . then it returns 4 .
Another solution is ["spice","smice","slice","slick","stick","stock"] with five steps to get to "stock" , then it returns `5. But this is the wrong decision, because there is another one that is better with fewer steps than this.
I'm having problems with the countdown to get a better solution, because I don’t know how to make my code look for other solutions and just not one.
Here is the code I tried to do, but I am getting some errors. By the way, I don’t know if my way to “roll back” is good, or if there are some errors that I don’t see.
wordF :: [String] -> String -> String -> (String, String, Int) wordF [] ab = (a, b, -1) wordF list ab | (notElem a list || notElem b list) = (a, b, -1) | otherwise = (a, b, (wordF2 list ab [a] 0 (length list))) wordF2 :: [String] -> String -> String -> [String] -> Int -> Int -> Int wordF2 list ab 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 ab 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)
My first wordF2 function gets a list, start, end, auxiliary list to get the current solution with the first element that will always be there ( [a] ), a counter with 0 and the maximum size of the counter ( length list ) ..
and the second function check_word2 checks if the word can go to another word, for example, "spice" - "slice" , if it does not match "spice" before "spoca" , it returns "ThisWRONG" .
This solution receives a pattern matching error
Program error: pattern match failure: wordF2 ["slice","slick"] "slice" "slick" ["slice"] 0 1
I tried with small cases and nothing, and I limit that I get the wrong position of the list with the score and the maximum value.
Or maybe I don’t know how to implement backtracking on haskell to get multiple solutions, a better solution, etc.
UPDATE: I made a decision, but did not return
wordF :: [String] -> String -> String -> (String, String, Int) wordF [] ab = (a, b, -1) wordF list ab | (notElem a list || notElem b list) = (a, b, -1) | otherwise = (a, b, (wordF1 list ab)) wordF1 :: [String] -> String -> String -> Int wordF1 list ab | ((map length (wordF2 (subconjuntos2 (subconjuntos list) ab))) == []) = -1 | (calculo > 0) = calculo | otherwise = -1 where calculo = (minimum (map length (wordF2 (subconjuntos2 (subconjuntos list) ab))))-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 [] ab = [] subconjuntos2 (x:xs) ab | (length x <= 1) = subconjuntos2 xs ab | ((head x == a) && (last x == b)) = (x:subconjuntos2 xs ab) | ((head x /= a) || (last x /= b)) = (subconjuntos2 xs ab) subconjuntos :: [a] -> [[a]] subconjuntos [] = [[]] subconjuntos (x:xs) = [x:ys | ys <- sub] ++ sub where sub = subconjuntos xs
Mmm may be ineffective, but at least he makes a decision. I look for all possible solutions, I compare head == "slice" and last == "stock", then filter those that are solution and print shorter ones, thanks, and if you guys suggest saying that :)