I want to make a function that deletes only a single minimum element in a list

About my question: as the title says so.

e.g. [234,2,2,4123,54] -> [234,2,4123,54]

Here's my code trying to make that function but failed:

--sorry for messy comments

delMinimum ar = map fst [x|x <- arr, x /= toDel2]
    where
    let arr = zip ar [1..] {- Firstly, let all the array elements are separately recognizable,
    even when there's couple or more items having same value. -}
    let toDel = [x|x <- arr, fst x = minimum ar] {- collect tuple elements, where first item of those
    elements is having minimum of ar -}
    let toDel2 = head (map snd toDel) {- sellect one of the tuples of toDel -}

    --lastly, delete toDel2 in arr, and after that, get all first items of each tuples in arr.

Showing my code without the messy comments that I used to try to explain my code:

delMinimum ar = map fst [x|x <- arr, x /= toDel2]
    where
    let arr    = zip ar [1..]
    let toDel  = [x | x <- arr, fst x = minimum ar]
    let toDel2 = head (map snd toDel)

Upvotes: 1

Views: 146

Answers (2)

Zemyla
Zemyla

Reputation: 478

We can use lazy knot-tying to get this done in a single pass.

deleteMin ls = nls where
  -- Get the new list (which is a thunk at this point) and the index of the minimum value, passing in
  -- the starting index, starting minimum index, and current minimum.
  (nls, nmin) = foldr app end ls 0 (-1 :: Int) Nothing

  -- Take the current index, current minimum index, and current minimum, calculate the
  -- new best minimum, and pass that down, using the result to lazily generate a list with the
  -- minimum element removed.
  app _ _ i mc mMin
    -- Force the arguments so thunks don't pile up here.
    | i `seq` nc `seq` mMin `seq` False = undefined
  app x r i mc mMin = let
    -- Calculate the new minimum index and minimum.
    (mc', mMin') = case mMin of
      Just xm | x >= xm = (mc, mMin)
      _ -> (i, Just x)
    -- Get the lazy list and best minimum found to pass forward.
    (cls', nk) = r (i + 1) mc' mMin'
    -- Push the current value on if it's not at the index to remove.
    nls' = if i == nmin then cls' else x:cls'
    -- And pass it all forward.
    in (nls', nk)

  -- At the end, only pass forward the empty list and index of the minimum.
  end _ mc _ = mc ``seq` ([], mc)

Upvotes: 1

ƛƛƛ
ƛƛƛ

Reputation: 892

take a look at this.

import Data.List (delete, minimum)

r1 xs = delete (minimum xs) xs

Upvotes: 3

Related Questions