2013年11月8日金曜日

開発環境

初めてのコンピュータサイエンス(Jennifer CampbellPaul GriesJason MontojoGreg Wilson(著)長尾 高弘(翻訳))の6章(条件分岐)、6.5(練習問題)、9をHaskellで解いてみる。

その他参考書籍

6.5(練習問題)、9.

コード(BBEdit)

Sample.hs

{-# OPTIONS -Wall -Werror #-}

main :: IO ()
main = do
    mapM_ putStr $ "Celsius ":map (++" ") units
    putStrLn ""
    mapM_ putStrLn $
          map (\(a:b:c:d:e:f:g:h:[]) -> strFormat a 7 2 ++
                                      ' ':strFormat b 10 2 ++
                                      ' ':strFormat c 6 2 ++
                                      ' ':strFormat d 7 2 ++
                                      ' ':strFormat e 7 2 ++
                                      ' ':strFormat f 6 2 ++
                                      ' ':strFormat g 7 2 ++
                                      ' ':strFormat h 7 2) $
              map (\t -> t:map (temperatures t "Celsius")
                               units)
                  [300.00, 290.00.. -260.00]

temperatures :: Double -> String -> String -> Double
temperatures t source = fromCelsius $ toCelsius t source

toCelsius :: Double -> String -> Double
toCelsius t "Kelvin" = t - 273.15
toCelsius t "Celsius" = t
toCelsius t "Fahrenheit" = (t - 32) * 5 / 9
toCelsius t "Rankine" = (t - 491.67) * 5 / 9
toCelsius t "Delisle" = 100 - t * 2 / 3
toCelsius t "Newton" = t * 100 / 33
toCelsius t "Reasumur" = t * 5 / 4
toCelsius t "Romer" = (t - 7.5) * 40 / 21
toCelsius _ s = error $ s ++"は摂氏に変換できない。"

fromCelsius :: Double -> String -> Double
fromCelsius t "Kelvin" = t + 273.15
fromCelsius t "Celsius" = t
fromCelsius t "Fahrenheit" = t * 9 / 5 + 32
fromCelsius t "Rankine" = (t + 273.15) * 9 / 5
fromCelsius t "Delisle" = (100 - t) * 3 / 2
fromCelsius t "Newton" = t * 33 / 100
fromCelsius t "Reaumur" = t * 4 / 5
fromCelsius t "Romer" = t * 21 / 40 + 7.5
fromCelsius _ s = error $ "摂氏から" ++ s ++ "に変換できない。"

units :: [String]
units = ["Fahrenheit", "Kelvin", "Rankine", "Delisle", "Newton", "Reaumur",
         "Romer"]

strFormat :: Double -> Int -> Int -> String
strFormat a m n =
    let s = show $ myRound a n
    in replicate (m - length s) ' ' ++ s

myRound :: Double -> Int -> Double
myRound a n | a >= 0 =  (fromInteger $ round $ a * 10 ^ n) / 10 ^ n
            | otherwise =
                -1 * (fromInteger $ round $ (abs a) * 10 ^ n / 10 ^ n)

入出力結果(Terminal, runghc)

$ runghc Sample.hs
Celsius Fahrenheit Kelvin Rankine Delisle Newton Reaumur Romer 
  300.0      572.0 573.15 1031.67  -300.0   99.0   240.0   165.0
  290.0      554.0 563.15 1013.67  -285.0   95.7   232.0  159.75
  280.0      536.0 553.15  995.67  -270.0   92.4   224.0   154.5
  270.0      518.0 543.15  977.67  -255.0   89.1   216.0  149.25
  260.0      500.0 533.15  959.67  -240.0   85.8   208.0   144.0
  250.0      482.0 523.15  941.67  -225.0   82.5   200.0  138.75
  240.0      464.0 513.15  923.67  -210.0   79.2   192.0   133.5
  230.0      446.0 503.15  905.67  -195.0   75.9   184.0  128.25
  220.0      428.0 493.15  887.67  -180.0   72.6   176.0   123.0
  210.0      410.0 483.15  869.67  -165.0   69.3   168.0  117.75
  200.0      392.0 473.15  851.67  -150.0   66.0   160.0   112.5
  190.0      374.0 463.15  833.67  -135.0   62.7   152.0  107.25
  180.0      356.0 453.15  815.67  -120.0   59.4   144.0   102.0
  170.0      338.0 443.15  797.67  -105.0   56.1   136.0   96.75
  160.0      320.0 433.15  779.67   -90.0   52.8   128.0    91.5
  150.0      302.0 423.15  761.67   -75.0   49.5   120.0   86.25
  140.0      284.0 413.15  743.67   -60.0   46.2   112.0    81.0
  130.0      266.0 403.15  725.67   -45.0   42.9   104.0   75.75
  120.0      248.0 393.15  707.67   -30.0   39.6    96.0    70.5
  110.0      230.0 383.15  689.67   -15.0   36.3    88.0   65.25
  100.0      212.0 373.15  671.67     0.0   33.0    80.0    60.0
   90.0      194.0 363.15  653.67    15.0   29.7    72.0   54.75
   80.0      176.0 353.15  635.67    30.0   26.4    64.0    49.5
   70.0      158.0 343.15  617.67    45.0   23.1    56.0   44.25
   60.0      140.0 333.15  599.67    60.0   19.8    48.0    39.0
   50.0      122.0 323.15  581.67    75.0   16.5    40.0   33.75
   40.0      104.0 313.15  563.67    90.0   13.2    32.0    28.5
   30.0       86.0 303.15  545.67   105.0    9.9    24.0   23.25
   20.0       68.0 293.15  527.67   120.0    6.6    16.0    18.0
   10.0       50.0 283.15  509.67   135.0    3.3     8.0   12.75
    0.0       32.0 273.15  491.67   150.0    0.0     0.0     7.5
  -10.0       14.0 263.15  473.67   165.0   -3.0    -8.0    2.25
  -20.0       -4.0 253.15  455.67   180.0   -7.0   -16.0    -3.0
  -30.0      -22.0 243.15  437.67   195.0  -10.0   -24.0    -8.0
  -40.0      -40.0 233.15  419.67   210.0  -13.0   -32.0   -14.0
  -50.0      -58.0 223.15  401.67   225.0  -16.0   -40.0   -19.0
  -60.0      -76.0 213.15  383.67   240.0  -20.0   -48.0   -24.0
  -70.0      -94.0 203.15  365.67   255.0  -23.0   -56.0   -29.0
  -80.0     -112.0 193.15  347.67   270.0  -26.0   -64.0   -34.0
  -90.0     -130.0 183.15  329.67   285.0  -30.0   -72.0   -40.0
 -100.0     -148.0 173.15  311.67   300.0  -33.0   -80.0   -45.0
 -110.0     -166.0 163.15  293.67   315.0  -36.0   -88.0   -50.0
 -120.0     -184.0 153.15  275.67   330.0  -40.0   -96.0   -56.0
 -130.0     -202.0 143.15  257.67   345.0  -43.0  -104.0   -61.0
 -140.0     -220.0 133.15  239.67   360.0  -46.0  -112.0   -66.0
 -150.0     -238.0 123.15  221.67   375.0  -50.0  -120.0   -71.0
 -160.0     -256.0 113.15  203.67   390.0  -53.0  -128.0   -76.0
 -170.0     -274.0 103.15  185.67   405.0  -56.0  -136.0   -82.0
 -180.0     -292.0  93.15  167.67   420.0  -59.0  -144.0   -87.0
 -190.0     -310.0  83.15  149.67   435.0  -63.0  -152.0   -92.0
 -200.0     -328.0  73.15  131.67   450.0  -66.0  -160.0   -98.0
 -210.0     -346.0  63.15  113.67   465.0  -69.0  -168.0  -103.0
 -220.0     -364.0  53.15   95.67   480.0  -73.0  -176.0  -108.0
 -230.0     -382.0  43.15   77.67   495.0  -76.0  -184.0  -113.0
 -240.0     -400.0  33.15   59.67   510.0  -79.0  -192.0  -118.0
 -250.0     -418.0  23.15   41.67   525.0  -82.0  -200.0  -124.0
 -260.0     -436.0  13.15   23.67   540.0  -86.0  -208.0  -129.0
$

{-# OPTIONS -Wall -Werror #-}を記述してるから、細かく型を指定(:: Double)しないと警告がいっぱい出た。慣れるまでは{-# OPTIONS -Wall -Werror #-}の記述を消さずに細かく型を指定していくことに。

0 コメント:

コメントを投稿