2015-03-30 9 views
9

Sono nuovo di Haskell e sto cercando di applicare una funzione (gcd) per l'input su standard in, che è separato dalla linea e ogni riga contiene nientemeno che due numeri. Ecco un esempio del mio ingresso:Haskell - Cercando di applicare una funzione alle righe di più numeri

 
3 
10 4 
1 100 
288 240 

Attualmente sto rompendo ogni linea in una tupla di entrambi i numeri, ma sto avendo difficoltà a capire come separare queste tuple e applicare una funzione a loro. Ecco quello che ho finora:

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 

Qualsiasi informazione come due un buon posto per iniziare la ricerca di questa risposta sarebbe molto apprezzato. Ho letto il tutorial di Learning Haskell e non ho trovato alcuna informazione su questo particolare problema.

+1

provare a scrivere una funzione di puro 'f :: String -> Int', che prende una linea del vostro input e calcola la prima gcd. In una seconda fase, applica quella funzione all'input all'interno di 'main'. Dai anche un'occhiata a 'uncurry :: (a -> b -> c) -> ((a, b) -> c)' dal Preludio. – sjakobi

risposta

3

Sei molto vicino. Non vi è alcun motivo per convertire una tupla o una lista di tuple prima di chiamare gcd.

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

Tutta la roba interessante è tra print e contents. lines dividerà il contenuto in linee. map (...) applica la funzione a ciascuna linea. words divide la linea in parole. \[x,y] -> gcd (read x) (read y) corrisponderà a un elenco di due stringhe (e genererà un errore in caso contrario - non una buona pratica in generale ma va bene per un programma semplice come questo), leggere tali stringhe come Integer s e calcolare il loro GCD.

Se si desidera utilizzare l'IO pigro, per stampare ogni risultato dopo aver inserito ciascuna riga, è possibile modificarlo come segue.

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

È necessario saltare la prima riga che consiste in un solo numero di voci consecutive. – Yuuri

+0

Grazie a tutti per le risposte veloci. Vedo esattamente cosa sta facendo ora e dovrò anche guardare inespressivo al preludio. – midnightconman

0

In alternativa, si può fare in uno stile più imperativo:

import Control.Monad 

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