The code below finds the index of the lowest unique integer on each line of the file. The numbering starts at 1, and when there's no unique value, the 0
should be output.
The sample input looks like this:
3 3 9 1 6 5 8 1 5 3
9 2 9 9 1 8 8 8 2 1 1
And the sample output is this:
5
0
I wonder if this code can be simplified or made more elegant and idiomatic in any way. It's also interesting to me, could I get by w/o the IntMap
and solve the problem with i.e. lists beautifully.
module Main where
import Prelude hiding (filter)
import Control.Applicative ((<$>))
import Data.IntMap (IntMap, alter, empty, filter, findMin, fromList, size)
import System.Environment
counts :: [(Int, Int)] -> IntMap [Int]
counts = foldl f empty
where f m (i,v) = alter f' v m
where f' :: Maybe [Int] -> Maybe [Int]
f' (Just is) = Just (i:is)
f' (Nothing) = Just [i]
g :: IntMap [Int] -> Int
g a = i
where rs = filter ((== 1) . length) a
h m | size m == 0 = fromList [(0, [0])]
| otherwise = m
(_, [i]) = findMin $ h rs
minUnique :: [Int] -> Int
minUnique l = g r
where r = counts (zip [1..] l)
main =
head <$> getArgs >>= readFile >>=
putStrLn . unlines . map (show . minUnique . map read . words) . lines