Skip to content

Instantly share code, notes, and snippets.

@SPY
Created March 12, 2015 08:18
Show Gist options
  • Save SPY/01e0a27261850624ab41 to your computer and use it in GitHub Desktop.
Save SPY/01e0a27261850624ab41 to your computer and use it in GitHub Desktop.
import Control.Applicative ((<$>))
import Text.Printf (printf)
type Solution = Maybe [Double]
gauss :: [[Double]] -> Solution
gauss [[a, b]] = return [b / a]
gauss (h@(x : xs) : t) = do
let minor = transform h t
if any isNull minor
then Nothing
else do
solutions <- gauss minor
return $ (xs ^*^ (solutions ++ [-1.0])) / (negate x) : solutions
isNull :: [Double] -> Bool
isNull [x] = True
isNull (x:xs) = if x == 0 then isNull xs else False
transform :: [Double] -> [[Double]] -> [[Double]]
transform row = map $ elliminate row
where
elliminate :: [Double] -> [Double] -> [Double]
elliminate (x : xs) (y : ys) =
let factor = negate (y / x) in
zipWith (+) (map (* factor) xs) ys
transpose :: Eq a => [[a]] -> [[a]]
transpose xs
| all (== []) xs = []
| otherwise = let (col, rest) = multiHead xs in col : transpose rest
multiHead :: [[a]] -> ([a], [[a]])
multiHead = let splitHead (x:xs) = (x, xs) in unzip . map splitHead
(^*^) :: Num a => [a] -> [a] -> a
(^*^) xs ys = sum $ zipWith (*) xs ys
makeSystem :: [[Double]] -> [[Double]]
makeSystem vs =
let makeEq n = let e = vs !! n in map (^*^ e) vs in
let l = length vs - 1 in
map makeEq [0 .. l-1]
readNumList :: String -> [Double]
readNumList = map read . words
printSolution :: [Double] -> IO ()
printSolution = putStrLn . unwords . map (printf "%.8f")
main :: IO ()
main = do
[n, m] <- readNumList <$> getLine
inp <- map readNumList <$> (sequence $ replicate (floor n) getLine)
case gauss . makeSystem $ transpose inp of
Just solutions -> printSolution solutions
Nothing -> putStrLn "NO"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment