君ならどう書く2.0

import Data.List

data Oke = Oke {limit::Int, amount::Int} deriving (Show, Eq) 

type Oke3 = (Oke,Oke,Oke)

(.<.) x1@(Oke l1 a1) x2@(Oke l2 a2) | l1 == a1       = Nothing
                                    | a2 == 0        = Nothing
                                    | l1 < (a1 + a2) = Just (Oke l1 l1, Oke l2 (a2 - (l1 - a1)))
                                    | otherwise      = Just (Oke l1 (a1 + a2), Oke l2 0)

f :: [Oke3] -> Oke3 -> [(Int,Int,Int)]
f history oke@(x,y,z) | o == finish = [finish]
                      | otherwise   = case find (== oke) history of
                                        Just _  -> []
                                        Nothing -> o:g [f1,f2,f3,f4,f5,f6]
  where o  = (amount x, amount y, amount z)
        h  = history ++ [(x,y,z)]
        f1 = case x .<. y of Just (a1,a2) -> f h (a1,a2,z); Nothing -> []
        f2 = case x .<. z of Just (b1,b3) -> f h (b1,y,b3); Nothing -> []
        f3 = case y .<. x of Just (c2,c1) -> f h (c1,c2,z); Nothing -> []
        f4 = case y .<. z of Just (d2,d3) -> f h (x,d2,d3); Nothing -> []
        f5 = case z .<. x of Just (e3,e1) -> f h (e1,y,e3); Nothing -> []
        f6 = case z .<. y of Just (g3,g2) -> f h (x,g2,g3); Nothing -> []
        finish = (5,5,0)
        g xs = let ys = (filter ((== finish) . last) $ filter (/= []) xs) 
               in if ys == [] then []
                  else minimumBy (\x y -> length x `compare` length y) ys