HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

"Vc" as in Vancouver, or Valencia?

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
vancouvervalenciastackoverflow

Problem

It is common to shorten city names when writing, or at least in Sweden.

  • "Göteborg" (Gothenburg) is often referred to as "Gbg"



  • "Uddevalla" is commonly written as "Ua"



  • "Trollhättan" is often written as "Thn"



  • ...and a whole lot of other city names are often shortened



"Uddevalla" could also be shortened as "Uva", "Uvalla", or even "Udl" (although I've never seen anyone actually type that, according to my rules here it would be allowed). "vd" however would not be allowed as the letters must appear in order, "dv" would be allowed as an abbreviation for "Uddevalla" as "v" comes after "d".

Given a list of cities (or more generally: Strings) and a search string, print the city names that can be constructed by using these abbreviation rules.

Example cities (my townnames.txt file):

Strömstad
Skee
Överby
Tanum
Rabbalshede
Hällevadsholm
Dingle
Munkedal
Uddevalla
Ljungskile
Svenshögen
Stenungsund
Stora Höga
Kode
Ytterby
Göteborg
Trollhättan
Vänersborg
Varberg
Stockholm
Simrishamn


These are cities in Sweden, mostly in around my area. With the above list and the search string "Sm" the following cities are printed:

["Strömstad", "Stockholm", "Simrishamn"]


Instead given the string "Vbg" the results are:

["Vänersborg", "Varberg"]


After looking at the review I got from my previous Haskell question I wrote the following code to accomplish this:

module Main
   where

nameMatch :: [Char] -> [Char] -> Bool
nameMatch [] [] = True
nameMatch s [] = False
nameMatch [] s = True
nameMatch search@(s:restSearch) (c:city)
   | c == s    = nameMatch restSearch city
   | otherwise = nameMatch search city

main = do
  putStrLn "Loading list of towns..."
  text <- readFile "townnames.txt"
  putStrLn "Enter search phrase:"
  search <- getLine
  let cities = lines text
  putStrLn $ show $ filter (nameMatch search) cities


Any possible improvements or suggestions welcome.

Solution

[Char] is usually written as String.

You have a redundant base case: nameMatch [] [].

The parameter names are a bit off. A common convention for naming the head and tail is x:xs.

nameMatch :: String -> String -> Bool
nameMatch [] _      = True
nameMatch abbrev [] = False
nameMatch abbrev@(a:as) word@(w:ws)
   | a == w    = nameMatch as ws
   | otherwise = nameMatch abbrev ws


For printing the output, if you want each result to be on a separate line rather than as a list (which would produce output like ["Trollh\228ttan"]), then write

mapM putStrLn $ filter (nameMatch search) cities

Code Snippets

nameMatch :: String -> String -> Bool
nameMatch [] _      = True
nameMatch abbrev [] = False
nameMatch abbrev@(a:as) word@(w:ws)
   | a == w    = nameMatch as ws
   | otherwise = nameMatch abbrev ws
mapM putStrLn $ filter (nameMatch search) cities

Context

StackExchange Code Review Q#111957, answer score: 6

Revisions (0)

No revisions yet.