[Haskell-cafe] testing for same characters in lists of strings

Dan Weston westondan at imageworks.com
Tue Apr 8 00:10:58 EDT 2008


I don't know how to calibrate my response to what you are really asking 
for. Depending on how "new" you are, maybe all you want is just "working 
syntax" to get you started. Here is a structurally similar problem, if 
it helps. (And if you are more advanced, try the extra credit!)


Find the "average" of a string, i.e. the Char with the average ascii 
value of the string: e.g. (avgChar "ac") == 'b' and (avgChar "ffff") == 'f'.

Things to watch out for:

1) What if the string is empty? [I will error out]
2) What if the average is not an integer? [Just use div to truncate]

You should also provide guarantees to the caller in your documentation, 
if you can (and ideally, automated checks for them):

3) If the string is nonempty and contains only lowercase letters, is the 
average always a lowercase letter?
4) If I permute the string (e.g. sort it), does it give the same average?

[Extra credit: can you prove 3 and 4 are true or false?]

Here is one solution to the above problem. Save the code below to a file 
Avg.hs, then compile: ghc --make Avg

When you run Avg, you should get 'j', the average of "hello".

-------------------------------------------------------------------
main = putStrLn . show $ avg "hello"
-- Should print 'j'

-- How to convert a Char to its ascii value:
charToAscii :: Char -> Int
charToAscii c = fromEnum c

-- Convert each element of the string:
stringToAsciiList :: String -> [Int]
stringToAsciiList s = map charToAscii s

-- Get the average of a list of ints:
avgIntListValue :: [Int] -> Int
avgIntListValue [] = error "Dummy! I can't handle an empty list"
avgIntListValue xs  = sum xs `div` length xs

-- Now convert the ascii back to a Char:
asciiToChar :: Int -> Char
asciiToChar i = toEnum i

-- Now put it all together. Remember that the composition operator (.)
-- works backwards: given two functions f :: a -> b and g :: b -> c,
-- then g . f :: a -> c

avgChar :: String -> Char
avgChar s = (asciiToChar . avgIntListValue . stringToAsciiList) s

-- NOTE: I could have left the argument off and defined the functions
-- in a "point-free" style. For example, you can also write:
avgChar' = asciiToChar . avgIntListValue . stringToAsciiList

-------------------------------------------------------------------

Others have provided suggestions more specific to your particular 
assignment.

Dan

Jackm139 wrote:
> I'm new to Haskell, and I'm finding it is very different from any other
> language I have worked with.
> 
> I have an assignment to make a program to test whether two lists use the
> same characters for each string.
> e.g.
> 
> sameCharacter ["rock", "cab"] ["cork", "abc"]
> True
> 
> My plan to tackle this was to use:
> nub to eliminate duplications,
> sort to put the characters in order,
> and map to put characters together.. and then somehow check to see if these
> characters are the same.
> 
> My problem right now is just figuring out how to make a function that uses
> these three functions to give me a list of tuples.
> 
> I know this is an awfully newbish question, and I'm not trying to get an
> answer to my homework problem.
> I just need some sort of working example syntax to off of.
> 
> Any help would be appreciated!
> Thanks.
> 
> 




More information about the Haskell-Cafe mailing list