How would one do the following in Haskell:
Return all permutations of a list where one element comes before the another element (cannot assume that elements of the list can be ordered)?
My solution was to do:
sLeftOf l r lss =
[ ls
| ls <- lss
, DL.findIndex (l==) ls <= DL.findIndex (r==) ls
]
for somewhere to the left of and
sDirectLeftOf l r lss =
[ls
| ls <- lss
, DL.findIndex (l==) ls == fmap (\x-> x - 1) (DL.findIndex (r==) ls)
]
for directly to the left of which works,
*Main Lib> sLeftOf 2 3 (permutations [1..3])
[[1,2,3],[2,1,3],[2,3,1]]
*Main Lib> sDirectLeftOf 2 3 (permutations [1..4])
[[1,2,3,4],[2,3,1,4],[4,2,3,1],[2,3,4,1],[4,1,2,3],[1,4,2,3]]
But I don't like these. The findIndex
seems un-Haskelly and the fmap
on the result of findIndex
feels just wrong. Anyone has better ways to do this? For two lists there is a nice method using guard
/zip
and elem
.
mylist = do
x <- permutations ["a","b","c"]
y <- permutations ["1","2","3"]
leftOf "b" x "3" y
return $ zip x y
where
leftOf x xs y ys = guard $ (x,y) `elem` zip xs (tail ys)
leftOf' x xs y ys = guard $ (x,y) `elem` (aux xs (tail ys))
aux a b@(_:ys) = (zip a b) ++ aux a ys
aux _ [] = []
reqA = (map (map fst )) mylist
reqB = (map (map snd )) mylist
required = zip reqA reqB
The first leftOf
is immediately to left of and the second is somewhere to the left of; but this won't work for a single list.
DL
is. \$\endgroup\$