Haskell Contest Program


So I'm playing around a little more with Haskell.. There's something very exotic about it that's fun to toy around with -- but I think it will stay a toy for the simple reasons that very basic I/O and conversion functions are woefully documented and painful to use and that expressions become incomprehensibly long.

I used one of the contest questions for practice. Compare the functional Haskell code on top with the slightly more traditional imperative code on the bottom. I think Haskell would win any beauty or brevity contests in the logic section, but it just can't compare to C and its progeny for simple I/O.
    QUESTION 4 - HANGOVER

    How far can you make a stack of cards overhang a table? If you have one card, you can create a maximum overhang of half a card length. (We're assuming that the cards must be perpendicular to the table.) With two cards you can make the top card overhang the bottom one by half a card length, and the bottom one overhang the table by a third of a card length, for a total maximum overhang of 1/2 + 1/3 = 5/6 card lengths. In general you can make n cards overhang by 1/2 + 1/3 + 1/4 + ... + 1/(n + 1) card lengths, where the top card overhangs the second by 1/2, the second overhangs the third by 1/3, the third overhangs the fourth by 1/4, etc., and the bottom card overhangs the table by 1/(n + 1). This is illustrated in the figure below.


    INPUT:
    An input file named "dataFile4.txt", containing a single line with a positive floating-point number c whose value is at least 0.01 and at most 5.20; c will contain exactly three digits.

    OUTPUT:
    A single number that is the minimum number of cards necessary to achieve an overhang of at least c card lengths. Use the exact output format shown in the examples.


    EXAMPLE

    Input: Output:

    1.00 3 card(s)
    3.71 61 card(s)
    0.04 1 card(s)
    5.19 273 card(s)
Haskell
main :: IO()
main = do
	-- Hugs might not be able to find the file unless the path is specified
	file <- readFile "q3.txt"	
	
	-- Read in the first line of the file, convert it to Float, plug it the program
	putStr (show (getCardsForOverhang (fst (head( readFloat (head (lines (file))))))))
	return ()

-- Start the stack rolling
getCardsForOverhang :: Float -> Integer
getCardsForOverhang x = compareDistance x 1

-- See if we have enough cards to create the overhang
compareDistance :: Float -> Integer -> Integer
compareDistance x y = if overhang y >= x then y
	else compareDistance x (y+1)

-- Sum the inverses of 2 to x+1
overhang :: Integer -> Float
overhang 0 = 0
overhang x = sum (map inv(map intToFloat [2..x+1]))

-- Invert a Float
inv :: Float -> Float
inv x = 1 / x

-- Evidently there isn't a built in conversion function
intToFloat :: Integer -> Float
intToFloat n = fromInteger (toInteger n)


C#
using System;
using System.IO;

namespace Question4 {

	class Class1 {
		public static int numCards(float overhang) {
			int i = 0;

			while (numCards(i) < overhang) {
				i++;
			}

			Console.WriteLine(i + " card(s)");

			return i;
		}

		public static float numCards(int number) {

			float tot = 0;
			float denom = 2;
			int i = 0;

			while (i < number) {
				tot += 1.0f / denom;
				denom += 1.0f;
				i++;
			}

			return tot;
		}

		static void Main(string[] args)	{
		
			if (!File.Exists("dataFile4.txt")) {
				Console.WriteLine("Input file not found");
				return;
			}

			StreamReader sr = File.OpenText("dataFile4.txt");

			string input = sr.ReadLine();

			try {
				float num = (float)Double.Parse(input);
				numCards(num);
			} catch (FormatException fe) {
				Console.WriteLine("Invalid input: " + fe);
				return;
			}
		}
	}
}