Haskell输入txt文件

时间:2015-11-27 21:39:17

标签: haskell input

我正在研究一个程序,用指数2得到最接近的素数,这是在一个区间之间。

module Main where

import Data.Char
import System.IO
import Control.Monad (liftM)

data PGetal =  G Bool | P Int
instance Show PGetal where
          show (P n) = show n
          show (G False) = "GEEN PRIEMGETAL GEVONDEN"

mPriem::(Int, Int) -> PGetal
mPriem (x,y) | (x > y) = G False
         | (x > 1000000) = G False
         | (y > 1000000) = G False
         | (null (getAllPriem(x,y))) = G False
         | otherwise = P (kleinsteVerschilF(getAllPriem(x,y),1000000,1))


kleinsteVerschilF:: ([Int], Int , Int) -> Int
kleinsteVerschilF ([],_, priemGetal) = priemGetal
kleinsteVerschilF (priem1:priemcss, kleinsteVerschil,priemGetal)=
                                        if(kleinsteVerschil <= kleinsteVerschilMetLijst (priem1,(getMachtenVanTwee(0)),1000000))then kleinsteVerschilF(priemcss, kleinsteVerschil,priemGetal)
                                                                                                                          else kleinsteVerschilF (priemcss,kleinsteVerschilMetLijst(priem1,(getMachtenVanTwee(0)),1000000), priem1)



kleinsteVerschilMetLijst :: (Int,[Int],Int) -> Int
kleinsteVerschilMetLijst ( _,[],kleinsteVerschil) = kleinsteVerschil
kleinsteVerschilMetLijst (x,tweeMachten1:tweeMachtencss,kleinsteverschil)=
                         if((abs(x-tweeMachten1)) < kleinsteverschil)
                                                  then kleinsteVerschilMetLijst(x,tweeMachtencss, (abs(x-tweeMachten1)))
                                                  else kleinsteVerschilMetLijst(x,tweeMachtencss, kleinsteverschil)


getAllPriem :: (Int, Int) ->[Int]
getAllPriem (x,y) = filter isPriem [x..y]


getMachtenVanTwee ::(Int) -> [Int]
getMachtenVanTwee (macht)
                  |(functieMachtTwee(macht)< 1000000) = (functieMachtTwee(macht)) : (getMachtenVanTwee ((macht+1)))
                  | otherwise = []

functieMachtTwee:: (Int) -> Int
functieMachtTwee (x) = 2^x


isPriem n = (aantalDelers n)==2

aantalDelers n = telAantalDelersVanaf n 1
telAantalDelersVanaf n kandidaatDeler
  | n == kandidaatDeler       = 1
  | mod n kandidaatDeler == 0
      = 1 + telAantalDelersVanaf n (kandidaatDeler+1)
  | otherwise
      = telAantalDelersVanaf n (kandidaatDeler+1)

aantalDelers2 getal = telDelers getal 1 0
  where telDelers n kandidaat teller
          | n == kandidaat = 1+teller
          | mod n kandidaat == 0
              = telDelers n (kandidaat+1) (teller+1)
          | otherwise
              = telDelers n (kandidaat+1) teller

transform :: [String] -> [PGetal]
transform [] = []
transform (cs:css) =
  let (a : b: _ ) = words cs
     in (mPriem ((read(a)),(read(b))): transform css)

main :: IO ()
main = do
  n <- read `liftM` getLine :: IO Int
  lss <- lines `liftM` getContents

  let cases = take n lss
  let vs = (transform (lss))

  putStr $ unlines $ map show vs

当我使用mPriem函数时,它工作正常。 但它需要使用输入txt文件,所以我使用ghc命令创建了一个.exe文件。我还在文件夹中添加了这个.txt文件。

10
1 1
1 3
1 100
200 250
14 16
5 10
20 31
16 50
100 120
5200 7341

当我在命令行中使用此命令时,它什么都不做。没有输出。我不能用CTRL + C来停止程序,所以我觉得它崩溃了。但我不知道出了什么问题。

type invoer.txt | programma.exe

1 个答案:

答案 0 :(得分:2)

你的程序有效,但效率不高,而且个人觉得它不那么优雅(对不起:S),因为你引入了很多&#34;噪音&#34;。因此,在写入输出之前需要花费很多时间。

如果我正确理解问题陈述,每一行(第一行除外)都包含两个整数,你需要计算这两个数字之间的素数(包括边界?)

首先,你可以通过定义一个函数来更优雅地做到这一点:cPrime :: Int -> Int -> Int将两个数字作为输入并返回素数的数量:

cPrime :: Int -> Int -> Int
cPrime a b = count $ filter isPrime [a .. b]

您可以通过改进主要检查算法来提高性能。首先,您不需要检查1是否为除数,因为1始终是除数。此外,您可以在数学上证明没有除 sqrt(n) n 除外)的除数除以 n ;除非有另一个小于 sqrt(n)的分隔符。这意味着你可以简单地枚举2sqrt n之间的所有数字,并且从其中一个是除数的那一刻起,你可以停止:你已经证明这个数字不是素数:

isPrime :: Int -> Bool
isPrime 1 = False
isPrime 2 = True
isPrime n = all ((0 /=) . mod n) (2:[3,5..m])
    where m = floor $ sqrt $ fromIntegral n

现在我不确定你打算用kleinsteVerschilF做什么。