Beräkna ord i Haskell
Så jag har fått en uppgift där jag ska beräkna antalet ord i strängar med Haskell.
Orden är sammanhängande bokstäver i alfabetet, så strängen "h3llo th3re" skulle ha 4 ord totalt. Hade lätt kunnat lösa denna uppgift med ett imperativt språk men eftersom Haskell är funktionellt vet jag inte hur jag ska bära mig åt.
Vet hur jag ska iterera genom strängen rekursivt men är helt lost på hur jag ska "identifiera" orden i strängarna jag behandlar.
Finns det något smidigt sätt att göra detta på som inte kräver att jag importerar en massa paket?
Tack på förhand!
Gör det för hand i ditt exempel. Hur kom du fram till att det skulle bli fyra ord?
Okej så för strängen "h3llo th3re", kollar jag först 'h', vilket är en bokstav, men efterföljande tecken är en siffra, så då har jag 1 ord. Därefter kollar jag 'l', där de två efterföljande tecknen 'l' och 'o' också är bokstäver. Så då får jag ett till ord, osv osv.
Jag förstår dock inte hur jag ska implementera detta rekursivt.
Tänker att svansrekursion med guards skulle kunna fungera, typ:
words :: String -> Int
words [] = 0
words(x:xs)
|isAlpha 1 + words xs
|otherwise words xs
Men då beräknar jag antalet bokstäver i strängen. :(
Låt bli att räkna upp på ditt andra L och på O.
Exakt, men hur skulle jag göra det funktionellt? Kan ju inte ha någon counter eller liknande i Haskell.
Det går väl att minnas om förra tecknet var en bokstav eller inte?
På något sätt, men vet inte riktigt hur. Tänker att jag kan droppa alla icke-bokstäver efter första bokstaven och fortsätta så, rekursivt.
Det här borde fungera i vilket språk som helst
Om Läs_en_variabel isAlpha
New_word = Last_char_was_not_Alpha
Last_char_was_not_Alpha = False
else
Last_char_was_not_Alpha = True
end if
if New_word then
Number_of_words = Number_of_words + 1
end if
Får inte tilldela värden till variabler i Haskell, tyvärr, det är det som gör det så klurigt. :(
Jag har aldrig programmerat i Haskell, så detta kanske är en ful lösning som tusan, men jag löste det genom följande
isLetter :: Char -> Bool
isLetter n = (||) (n >= 'a' && n <= 'z') (n >= 'A' && n <= 'Z')
eatWord :: String -> String
eatWord (x:xs)
| isLetter x = eatWord xs
| otherwise = x : xs
eatWord "" = ""
countWords :: String -> Int
countWords (x:xs)
| isLetter x = 1 + (countWords (eatWord xs))
| otherwise = countWords xs
countWords "" = 0
Är mest imponerad över hur du kom fram till den lösningen, ska försöka göra min egen implementation.
Tack för svar!