Home > Net >  Solve the algorithmic problem with an end recursive form
Solve the algorithmic problem with an end recursive form

Time:01-07

Input: List xs with arbitrary numeric elements, xs has at least two elements / Output: smallest distance between adjacent elements in the list.

-- Input: List xs with at least two numeric elements & its implementation an end recursive function. -- Erg: Returns the smallest distance of adjacent elements from the output list.

minimumdistance :: [Int] -> Int
minimumdistance [] = error "Empty list".
minimumdistance [_] = error "Requirement is not met".
minimumdistance [a,b] = abs (a - b)
minimaldistance (x:y:xs) = helper (abs (x - y)) xs where 
   helper :: Int -> [Int] -> Int 
   helper acc [] = acc
   helper acc (z:zs) = if (abs (y - z)) < acc then helper (abs (y - z)) zs else helper 
   acc zs 

Is the function endrecursive because that we are supposed to solve the task endrecursive and I am sure because I do not have the definition yet correctly, but I also on other pages, the endrecursive representation not understood

CodePudding user response:

Your code has several issues mentioned in comments.

I suggest you break this down into smaller problems. We can write a tail-recursive function to get pairs of adjacent numbers from the list.

pairs [] = error "Not long enough"
pairs [_] = error "Not long enough"
pairs lst = aux lst []
 where
  aux (a:b:c) acc = aux (b:c) ((a, b):acc)
  aux _ acc = acc

Now, if we test this:

ghci> pairs [1, 3, 6, 7, 10]
[(7,10),(6,7),(3,6),(1,3)]

We can use map to get the differences.

ghci> map (\(a, b) -> abs (a - b)) $ pairs [1, 3, 6, 7, 10]
[3,1,3,2]

Now we just need to reduce that down to the minimum.

ghci> foldl1 min $ map (\(a, b) -> abs (a - b)) $ pairs [1, 3, 6, 7, 10]
1

CodePudding user response:

In your code for the helper function, the y variable does not get updated at all. Hence it remains equal to the second element of the initial input list in all successive scopes. This is probably not what you want.

It is more reliable to just include the previous list element into your state/accumulator, together with the smallest distance seen so far. This gives the following code:

minimumDistance :: [Int] -> Int
minimumDistance []       =  error "Empty list."
minimumDistance [_]      =  error "Requirement is not met."
minimumDistance (x:y:xs) =  helper  (abs (x-y), y)  xs  where
        helper (mnd,u)  []     =  mnd
        helper (mnd,u) (z:zs)  =  let  d1 = abs (u-z)
                                  in   if (d1 < mnd)  then  helper (d1,  z)  zs
                                                      else  helper (mnd, z)  zs

Sanity check:

We can generate a small random list, and compare the result of our minimumDistance function with the one obtained by just combining a few suitable library functions. Like this:

$ ghci
GHCi, version 8.10.7: https://www.haskell.org/ghc/  :? for help
...
 λ> 
 λ> :load q75011741.hs
 [1 of 1] Compiling Main             ( q75011741.hs, interpreted )
 Ok, one module loaded.
 λ> 
 λ> :type minimumDistance
 minimumDistance :: [Int] -> Int
 λ> 
 λ> import System.Random (randomRs, mkStdGen)
 λ> 
 λ> g0 = mkStdGen 42
 λ> 
 λ> xs = take 20 $ randomRs (0,500) g0
 λ> 
 λ> xs
 [48,151,95,271,208,466,401,23,139,95,500,306,187,389,398,297,248,94,348,91]
 λ> 
 λ> minimumDistance xs
 9
 λ> 
 λ>
 λ> zip xs (tail xs)
 [(48,151),(151,95),(95,271),(271,208),(208,466),(466,401),(401,23),(23,139),(139,95),(95,500),(500,306),(306,187),(187,389),(389,398),(398,297),(297,248),(248,94),(94,348),(348,91)]
 λ> 
 λ> map (\(a,b) -> abs(a-b)) $ zip xs (tail xs) 
 [103,56,176,63,258,65,378,116,44,405,194,119,202,9,101,49,154,254,257]
 λ> 
 λ> minimum $ map (\(a,b) -> abs(a-b)) $ zip xs (tail xs) 
 9
 λ> 

So it looks OK.

  • Related