2015-03-30 18 views
9

Jestem nowy w Haskell i próbuję zastosować funkcję (gcd) do wprowadzania na standardowej w, która jest rozdzielana liniowo i każda linia zawiera nie mniej lub więcej niż dwie liczby. Oto przykład z mojego wejścia:Haskell - Próba zastosowania funkcji do linii o wielu numerach

 
3 
10 4 
1 100 
288 240 

Jestem obecnie rozbijając każdy wiersz w krotce obu liczb, ale mam problemy z zastanawianie się, jak rozdzielić te krotki i zastosować funkcję do nich. Oto, co mam do tej pory:

import Data.List 

main :: IO() 
main = do 
    n <- readLn :: IO Int 
    content <- getContents 
    let 
    points = map (\[x, y] -> (x, y)). map (map (read::String->Int)). map words. lines $ content 
    ans = gcd (fst points :: Int) (snd points :: Int) 
    print ans 

Wszelkie informacje jako dwa dobre miejsce do rozpoczęcia poszukiwania tej odpowiedzi byłyby mile widziane. Przeczytałem samouczek Learning Haskell i nie znalazłem żadnych informacji o tym konkretnym problemie.

+1

Spróbuj napisać czystą funkcję 'f :: string -> Int', że zajmuje linię swojego wejścia i oblicza najpierw gcd. W drugim kroku zastosuj tę funkcję do wejścia wewnątrz 'main'. Spójrz także na 'uncurry :: (a -> b -> c) -> ((a, b) -> c)' z Prelude. – sjakobi

Odpowiedz

3

Jesteś całkiem blisko. Nie ma powodu do konwersji na krotkę lub listę krotek przed wywołaniem gcd.

main = do 
    contents <- getContents 
    print $ map ((\[x,y] -> gcd (read x) (read y)) . words) . lines $ contents 

wszystkich ciekawych rzeczy jest między print i contents. lines podzieli zawartość na wiersze. map (...) stosuje funkcję do każdej linii. words dzieli linię na słowa. \[x,y] -> gcd (read x) (read y) będzie pasować do listy dwóch ciągów znaków (i podać inny błąd - nie jest to dobra praktyka w ogóle, ale w porządku dla prostego programu takiego jak ten), przeczytaj te ciągi znaków jako Integer s i oblicz ich GCD.

Jeśli chcesz skorzystać z leniwego IO, aby wydrukować każdy wynik po wprowadzeniu każdej linii, możesz zmienić ją w następujący sposób.

main = do 
    contents <- getContents 
    mapM_ (print . (\[x,y] -> gcd (read x) (read y)) . words) . lines $ contents 
+0

Musisz pominąć pierwszy wiersz, który składa się tylko z pojedynczej liczby kolejnych wpisów. – Yuuri

+0

Dziękuję wszystkim za szybkie odpowiedzi. Dokładnie widzę, co to teraz robi, i będę musiał spojrzeć na niepokój w preludium. – midnightconman

0

Lub, można to zrobić w bardziej bezwzględnej styl:

import Control.Monad 

main = do 
    n <- readLn 
    replicateM_ n $ do 
     [x, y] <- (map read . words) `liftM` getLine 
     print $ gcd x y 
Powiązane problemy