I am busy learning Haskell, but I ran into the following problem:
A sample string consist of the text "123abc456". Now I want to derive
the number of numbers in this string, which is 2 in this example
("123" and "456")
How can I program this is a simple manner, using the type definition
NumberOfDeci::String->Int?
Any help appreciated.
Kind Regards,
ActiveX
I won't write the code for you, but I'll give you a few hints..
You can use isDigit to determine if a character is a decimal digit.
You can use dropWhile to delete leading leading digits or non-digits
as required.
If you start by deleting any leading non-digits, then either..
the resulting string is [], so NumberOfDeci=0
or..
the resulting string is not [] (begins with a digit), so NumberOfDeci
is one more than the NumberOfDeci you get after deleting the leading digits
from this string
Regards
--
Adrian Hey
> I am busy learning Haskell, but I ran into the following problem:
> A sample string consist of the text "123abc456". Now I want to derive
> the number of numbers in this string, which is 2 in this example
> ("123" and "456")
> How can I program this is a simple manner, using the type definition
> NumberOfDeci::String->Int?
The following functions may prove useful:
Char.isDigit
List.group
and
filter
id
length
map
--
Glynn Clements <glynn.c...@virgin.net>
Hi,
Thank you for your help.
I've now got the following which is ok until the +1:
NumberofDeci::String->Int
NumberofDeci string
| dropWhile isAlpha string=/[]=+1 AND dropWhile isDigit string
| dropWhile isAlpha string==[] = 0
How can I add 1 each time this is entered, and how can I let the
function proceed with dropWhili isDigit string?
Any help appreciated!!
Kind regards,
Marko
> > > I am busy learning Haskell, but I ran into the following problem:
> > > A sample string consist of the text "123abc456". Now I want to derive
> > > the number of numbers in this string, which is 2 in this example
> > > ("123" and "456")
> > > How can I program this is a simple manner, using the type definition
> > > NumberOfDeci::String->Int?
> >
> > The following functions may prove useful:
> >
> > Char.isDigit
> > List.group
> > and
> > filter
> > id
> > length
> > map
>
> Thank you for your help.
> I've now got the following which is ok until the +1:
> NumberofDeci::String->Int
> NumberofDeci string
> | dropWhile isAlpha string=/[]=+1 AND dropWhile isDigit string
> | dropWhile isAlpha string==[] = 0
>
> How can I add 1 each time this is entered, and how can I let the
> function proceed with dropWhili isDigit string?
Let me put it another way. You can write the function you require
using nothing more than the functions which I listed previously, in
conjunction with the "." (composition) operator. You don't need to
write your own recursion.
Some more clues:
1. Start by feeding your string to "map isDigit". You only care
whether or not a character is a digit; any other distinctions are
irrelevant.
2. List.group does the "real work".
--
Glynn Clements <glynn.c...@virgin.net>
Ok, I really can't get out of it. Would you be so kind to give me the
answer, so I can reverse engineer the whole thing and learn something
from it.
thanks,
marko
> Ok, I really can't get out of it. Would you be so kind to give me the
> answer, so I can reverse engineer the whole thing and learn something
> from it.
I'm not him and very new to haskell, too. However, that's what I can
come up with:
count :: String -> Int
count s = length $ filter (any (== True)) $ group $ map isDigit s
I can't resist making it shorter ;)
count s = length $ filter (any (== True)) $ group $ map isDigit s
count s = length $ filter (any id) $ group $ map isDigit s
count s = length $ filter and $ group $ map isDigit s
count = length . filter and . group . map isDigit
Best regards,
Tom
--
.signature: Too many levels of symbolic links
> I'm not him and very new to haskell, too. However, that's what I can
> come up with:
> count :: String -> Int
> count s = length $ filter (any (== True)) $ group $ map isDigit s
Since the cat is out of the bag, here are some small (arguably?)
improvements:
You don't need to name the parameter:
count = length . filter (any (== True)) . group . map isDigit
(== True) is the same as id on Bools:
count = length . filter (any id) . group . map isDigit
or you could perhaps just use a boolean operator like and or or (I
think which one you choose can affect efficiency, and depends on the
data):
count = length . filter or . group . map isDigit
For max efficiency, you only really need to look at the head, of
course. (We know that no empty strings will be returned, right?):
count = length . filter head . group . map isDigit
-kzm
--
If I haven't seen further, it is by standing in the footprints of giants
So seeing as ActiveX has made an attempt with the solution I suggested (and
I can't be bothered with more hints:-) here's what I think is a simple
solution for a learner to grok ..
numberOfDeci :: String -> Int
numberOfDeci str = case dropWhile isNonDigit str of
[] -> 0
_:cs -> 1 + numberOfDeci (dropWhile isDigit cs)
where isNonDigit c = not (isDigit c)
Regards
--
Adrian Hey
> Ok, I really can't get out of it. Would you be so kind to give me the
> answer, so I can reverse engineer the whole thing and learn something
> from it.
My solution was:
count = length . filter id . map and . group . map isDigit
[Essentially the same as Martin's/Tomasz' solutions, although slightly
more verbose.]
Let's break it down:
> map isDigit $ "123abc456"
[True,True,True,False,False,False,True,True,True]
> group . map isDigit $ "123abc456"
[[True,True,True],[False,False,False],[True,True,True]]
> map and . group . map isDigit $ "123abc456"
[True,False,True]
> filter id . map and . group . map isDigit $ "123abc456"
[True,True]
> length . filter id . map and . group . map isDigit $ "123abc456"
2
--
Glynn Clements <glynn.c...@virgin.net>
Thank you all for the reactions.
I'm now busy with Glynn's answer, since this is the easiest in my
opinion, although the solution with recursion is very helpfull as
well!
Now I want to determine the maximum length of the number of deci, so
"123abc1234" returns the maximum length, which is 1234.
I've tried to following:
maximum. length. filter id. map and. group. map isDigit
But I think the problem is that isDigit converts the real numbers into
a boolean value.
Am I on the good way with this solution?
Next I want to get the real maximum (highest number), which should be
a simplification of the above statement I have made:
maximum. filter id. map and. group. map isDigit
Is this right also?
Thank you all!
Kind regards,
Marko
> Thank you all for the reactions.
> I'm now busy with Glynn's answer, since this is the easiest in my
> opinion, although the solution with recursion is very helpfull as
> well!
> Now I want to determine the maximum length of the number of deci, so
> "123abc1234" returns the maximum length, which is 1234.
Let's see how much we can recycle:
>> > map isDigit $ "123abc456"
>> [True,True,True,False,False,False,True,True,True]
Yep, the lengths are preserved.
>> > group . map isDigit $ "123abc456"
>> [[True,True,True],[False,False,False],[True,True,True]]
Yes, each list still has the correct length, and the ones containing
True correspond to numbers.
>> > map and . group . map isDigit $ "123abc456"
>> [True,False,True]
..but here we lost information we need.
> maximum. length. filter id. map and. group. map isDigit
> Am I on the good way with this solution?
Also you need to watch out, since you're working on lists of lists,
operations that you really want to apply to each element can
inadvertently be applied to the whole list instead.
Fire up Hugs or GHCi and toy around!
For problem#2, I've found the solution myself:
maxlengthDeci::String->Int
maxlengthDeci=maximum.map length. filter (any(==True)).group.map isDigit....
So far for this example!
But my following question: since isDigit converts all real numbers to
Booleans, how can I derive the maximum of NumberofDeci.
So input "123abc124" returns 124 since this is the largest number.
I've tried the following:
groupBy (\x y -> isDigit x&& isDigit y)
which converts "123abc124" into ["123", "a","b","c","124"]
Now I should filter for isDigits, so I get the following :(how??? tried map
isDigit.groupBy (\x y -> isDigit x&& isDigit y), but isn;t working):
["123","124"]
And the next problem is: maximum ["123","124"] returns "124" which is not an
integer.
So the problem can be split up in two parts:
-How can I Filter digits out of ["123", "a","b","c","124"]
-How van I Convert maximum ["123","124"] into maximum of type integer.
Please help me!
Solutions are welcome!
Thanks,
ActiveX
"Ketil Malde" <ke...@ii.uib.no> schreef in bericht
news:egfz8c0...@havengel.ii.uib.no...
> So the problem can be split up in two parts:
> -How can I Filter digits out of ["123", "a","b","c","124"]
What you want is not a direct property of the string, e.g. "123" or "b". You
need to look at one or more elements within the string.
> -How van I Convert maximum ["123","124"] into maximum of type integer.
'read' will convert a String to nearly any type you could wish.
Because of the following:
[abc1abc12] will be converted by the code to:
["a","b","c","1","a","b","c","12"]
When I check for one element or more, the "1" will be filtered out as well,
together with a,b,c.
Any better solutions available??
Kind regards,
ActiveX
"Scott Turner" <ne...@pkturner.org> schreef in bericht
news:ydqdndVGx8l...@comcast.com...
> But my following question: since isDigit converts all real numbers to
> Booleans, how can I derive the maximum of NumberofDeci.
> So input "123abc124" returns 124 since this is the largest number.
>
> I've tried the following:
> groupBy (\x y -> isDigit x&& isDigit y)
> which converts "123abc124" into ["123", "a","b","c","124"]
>
> Now I should filter for isDigits, so I get the following :(how??? tried map
> isDigit.groupBy (\x y -> isDigit x&& isDigit y), but isn;t working):
You probably want:
\x y -> isDigit x == isDigit y
I.e. True if either both are digits or neither are digits, False if
one is a digit and the other isn't.
> ["123","124"]
>
> And the next problem is: maximum ["123","124"] returns "124" which is not an
> integer.
>
> So the problem can be split up in two parts:
> -How can I Filter digits out of ["123", "a","b","c","124"]
"all" tests whether all elements of a list (strings are just lists of
characters) possess a given property, so "all isDigit" will return
True for a string composed entirely of digits and False otherwise.
> -How van I Convert maximum ["123","124"] into maximum of type integer.
"read".
--
Glynn Clements <glynn.c...@virgin.net>
> I'm not sure the point free solution that's been suggested going to be much
> help to a new bee. I think it's easier to understand recursion and use of
> inductive reasoning first, even if Haskellers try to avoid using it :-)
Both must be learned. Although in theory learning both at the same
time is overwhelming, I see in practice lots of students taking two
courses or more at the same time --- including one on recursion and
another on Unix shell scripting --- with no problem.
But what makes Unix shell scripting special anyway?
Sample Unix shell command:
grep '^X-Spam-Level' | sort | unique | wc -l
Sample Haskell function:
length . nub . sort . filter (isPrefixOf "X-Spam-Level")
(isPrefixOf and nub are from the List module)
<sarcasm>
Pointfree combinator programming is very intimidating, abstract, and
is no more than a theoretical curiosity --- you always put the points
back in real programs. Unix shell pipelining is very intuitive,
down-to-earth, and is a matter of bread-and-butter --- it is
impractical to create, track, and clean up temporary files in real
applications.
</sarcasm>
"Ketil Malde" <ke...@ii.uib.no> a écrit dans le message de
news:eglli54...@havengel.ii.uib.no...
It's still useful to study a function that has been condensed to a minimum
of characters, because it is likely to demonstrate techniques which are
effective but unusual.
> Is it an intellectual exercise to iteratively condense such a function to
> make it shorter and shorter, or do you do such process when you develop real
> world programs?
Both, to some extent.
>>> count :: String -> Int
>>> count s = length $ filter (any (== True)) $ group $ map isDigit s
>> You don't need to name the parameter:
>>
>> count = length . filter (any (== True)) . group . map isDigit
I generally do this.
>> (== True) is the same as id on Bools:
>>
>> count = length . filter (any id) . group . map isDigit
>> count = length . filter or . group . map isDigit
I would consider these intermediate steps, leading to
>> count = length . filter head . group . map isDigit
which I think is not so hard to understand: turn to booleans, group
them, filter out the ones whose head is True, and count the result.
Perhaps the 'filter head' could be replaced by
'filter (==True) . map head' if you feel that is clearer?
> Seems to me it obfuscates the code and makes it harder to maintain, but
> again, I'm not really fluent, and there might be really common FP idioms
> that allow proficient readers to browse easily through condensed (more
> "elegant" ;) ) forms.
You could say the same about using i++ instead of i=i+1 in C. It
isn't obfuscated when you're used to the idiom. Good naming and
conventions/idioms are important.