[SPOILER] Easy QOTW #2005 - Two Haskell Solutions
Shlomi Fish <shlomif-ik1l9ssToec+JF/[email protected]> Sat, 5 Feb 2005 16:30:45 +0200
| Newsgroups | gmane.comp.lang.perl.qotw.discuss |
|---|---|
| Message-ID | <[email protected]> |
My personal Haskell style is to write recursive solutions that do not make too
much use of the built-in functions. I had in mind a recursive solution, but
when I tried to write it in Haskell, I kept becoming confused. Eventually I
decided to write it in Perl first, and this proved to be easier and I was
able to reach a working solution. Then I translated it into Haskell, which
was quite straightforward.
The code in Perl appeared in the previous message about the test suite and is:
<<<<<<<<<<<<<<
sub recursive_perl
{
my $string = shift;
my $recurse;
my @chars = split(//, $string);
$recurse = sub {
my ($arg) = (@_);
my ($rest_of_chars) = [ @$arg];
if (@$rest_of_chars == 0)
{
return ("", 0);
}
my $head = shift(@$rest_of_chars);
my $tail = $rest_of_chars;
my ($processed_string, $was_period_found) = $recurse->($tail);
if ($was_period_found)
{
return ((($head eq "." ? "" : $head) . $processed_string), 1);
}
else
{
return ($head . $processed_string, ($head eq "."));
}
};
return +($recurse->([@chars]))[0];
}
>>>>>>>>>>>>>>
The code in Haskell is:
<<<<<<<<<<<<<<<<
module Main where
import System
main :: IO ()
main = do args <- getArgs
putStr (rem_periods (head args))
putStr "\n"
rem_periods :: String -> String
rem_periods mystring = (fst (recurse mystring)) where
recurse :: String -> (String,Bool)
recurse [] = ([],False)
recurse (a:as) = (if was_period_found
then ((ret_string a), True)
else ((a:processed_string), (a == '.'))
) where
(processed_string,was_period_found) = (recurse as)
ret_string :: Char -> String
ret_string '.' = processed_string
ret_string _ = a:processed_string
>>>>>>>>>>>>>>>>
(note that it includes some wrappers to make it into an executable which
accepts the string as a single argument on the command line and prints the
modified string (and a newline) to STDOUT).
Then I wanted to create a similar function only using the Haskell built-in
functions, so it will be shorter. I eventually had a basic algorithm in mind,
but did not know what functions exist that I could use to implement it with,
so I asked the people on Freenode's #haskell channel. They were very helpful.
So here is the other Haskell solution:
<<<<<<<<<<<<<<<<<<<<<<<
rem_periods :: String -> String
rem_periods mystring = (reverse (if (end == "")
then start
else complex_val
)) where
(start,end) = (break ('.'==) (reverse mystring))
complex_val = start ++ ((head end):(filter (/= '.') (tail end)))
>>>>>>>>>>>>>>>>>>>>>>>
What it does is:
1. reverse the string
2. Split it into two parts according to the first period.
3. Filter all periods from the second part.
4. Concatenate them.
5. Reverse the string again.
Regards,
Shlomi Fish
---------------------------------------------------------------------
Shlomi Fish shlomif-ik1l9ssToec+JF/[email protected]
Homepage: http://www.shlomifish.org/
Knuth is not God! It took him two days to build the Roman Empire.