60 Days of Euler in F# - Problem 22

The Problem

Using names.txt (right click and 'Save Link/Target As...'), a 46K text file containing over five-thousand first names, begin by sorting it into alphabetical order. Then working out the alphabetical value for each name, multiply this value by its alphabetical position in the list to obtain a name score.

For example, when the list is sorted into alphabetical order, COLIN, which is worth 3 + 15 + 12 + 9 + 14 = 53, is the 938th name in the list. So, COLIN would obtain a score of 938 × 53 = 49714.

What is the total of all the name scores in the file?

The Solution

This one isn't very hard, no matter what language you choose.

First, we'll implement the scoring function from the problem definition.

let score (s : string) = 
    s 
    |> Seq.map (fun c -> (int c) - int('A'))
    |> Seq.sum

Strings can be treated as Seq<char>. We convert each character in the string to its numeric value, then sum the result.

Now we'll solve the problem.

let splitByMany (c : char[]) (s : string) = 
    s.Split(c, System.StringSplitOptions.RemoveEmptyEntries)

let input = System.IO.File.ReadAllText(@"C:\Development\ProjectEuler\FSharpSolutions\NamesProblem22.txt")

input
|> splitByMany [|'"';','|]
|> Seq.sort
|> Seq.mapi (fun i name -> (i+1) * score name)
|> Seq.sum

The splitByMany function is a pipeline-friendly version of String.Split. I say it's pipeline-friendly because the parameters are designed such that you can pipe the parameters into it. In this particular case, we're piping the string input into it and specifying the text delimiters. This gives us the list of names.

Next, we sort the list alphabetically, then compute a value for the name based on its position in the list.

Finally, we sum those values and get our answer.

Other Posts in This Series