masfenix
masfenix

Reputation: 8006

Char value in F#

Lets say I have a string "COLIN".

The numeric value of this string would is worth:

3 + 15 + 12 + 9 + 14 = 53.

So

A = 1, B = 2, C = 3, and so on.

I have no idea how to even start in F# for this.

let mutable nametotal = 0
let rec tcalculate name =
    name.ToString().ToCharArray()
    |> Seq.length

Here is what I have so far. The seq.length is just there for testing to see if the toCharArray actually worked.

Upvotes: 3

Views: 11807

Answers (6)

HerbM
HerbM

Reputation: 571

let sumOfChar name =                                                // F# functional answer
  name 
  |> List.ofSeq                                                     // to char array 
  |> List.map (fun c -> int (System.Char.ToUpper c) - int 'A' + 1)  // to value
  |> List.fold (+) 0                                                // sum

sumOfChar "Herb"                                                    // 33

// Or simply this version:
let sumOfCharBy name =
  let value c = int (System.Char.ToUpper c) - int 'A' + 1
  List.sumBy value (List.ofSeq name)

sumOfCharBy "HerbM"                                                 // 46

// or simply:
let sumOfCharBy name =
  name |> Seq.sumBy (fun c -> int (System.Char.ToUpper c) - int 'A' + 1)

sumOfCharBy "HMartin"                                              // 83

Upvotes: 0

jrk
jrk

Reputation: 696

I realize this is very old but I am recently learning F# and playing with the ideas in this question. Maybe someone will find it useful:

let table = 
  Seq.zip ['A'..'Z'] (Seq.initInfinite((+) 1)) 
  |> Map.ofSeq

let calc (input : string) =
  let s = input.ToUpper()
  match s with
  | _ when Seq.forall System.Char.IsLetter s ->
    Some (Seq.sumBy (fun c -> table.[c]) s)
  | _ -> None

Upvotes: 0

Brian
Brian

Reputation: 118865

If the 'mapping' is more arbitrary, you could use a strategy like the code below, where you can specify a data structure of what value each letter maps to.

#light

let table = [
    'C', 3
    'O', 15
    'L', 12
    'I', 9
    'N', 14
    ]

let dictionary = dict table

let Value c = 
    match dictionary.TryGetValue(c) with
    | true, v -> v
    | _ -> failwith (sprintf "letter '%c' was not in lookup table" c)

let CalcValue name =
    name |> Seq.sum_by Value

printfn "COLIN = %d" (CalcValue "COLIN")

Upvotes: 3

Brian
Brian

Reputation: 118865

What you have is decent; here's another version:

#light

let Value (c:char) = 
    (int c) - (int 'A') + 1

let CalcValue name =
    name |> Seq.sum_by Value

printfn "COLIN = %d" (CalcValue "COLIN")
// may be of interest:
printfn "%A" ("COLIN" |> Seq.map Value |> Seq.to_list)

It assumes the original input is uppercase. "int" is a function that converts a char (or whatever) to an int; Seq.sum_by is perfect for this.

I also show an example of using map, not sure what you're interested in.

Upvotes: 10

Samuel
Samuel

Reputation: 17171

all you need to do, is make the string lowercase, turn it into a char array like you have done, loop through each letter, take the value of each char and subtract the value of 'a' and add one. that will make each letter have the value of its position in the alphabet.

Upvotes: 1

masfenix
masfenix

Reputation: 8006

I've found a hackish way to do this using the ascii value of the character, and getting the number from there but i think there might be a better way.

let tcalculate name =
    name.ToString().ToLower().ToCharArray()
    |> Seq.map (fun char -> Convert.ToInt32 char - 96)
    |> Seq.sum 

work's beautifully and maybe even more efficient then "mapping" but I'd like to view the solution I asked for

thanks all.

Upvotes: 1

Related Questions