I have decided to take up f# as my functional language.
My problem: Give a bunch of 50digits in a file, get the first 10 digits of the sum of each line. (euler problem for those who know)
for example (simplified):
1234567890
The sum is 45
The first "ten" digits or in our case the "first" digit is 4.
Heres my problem,
I read my file of numbers,
I can split it using "\n" and now i have each line, and then I try to convert it to an char array, but the problem comes here. I can't access each element of that array.
let total =
lines.Split([|'\n'|])
|> Seq.map (fun line -> line.ToCharArray())
|> Seq.take 1
|> Seq.to_list
|> Seq.length
I get each line, convert it to array, i take the first array (for testing only), and i try to convert it to list, and then get the length of the list. But this length is the length of how many arrays i have (ie, 1). It should be 50 as thats how many elements there are in the array.
Does anyone know how to pipeline it to access each char?
Seq.take is still returning a seq<char array>. To get only the first array you could use Seq.nth 0.
My final answer:
let total =
lines.Split([|'\n'|])
|> Seq.map (fun line -> line.ToCharArray() |> Array.to_seq)
|> Seq.map (fun eachSeq -> eachSeq
|> Seq.take 50 //get rid of the \r
|> Seq.map (fun c -> Double.Parse(c.ToString()))
|> Seq.skip 10
|> Seq.sum
)
|> Seq.average
is what i got finally and it's working :).
Bascially after I convert it to charArray, i make it a sequence. So now i have a sequence of sequence. Then I can loop through each seqquence.
I'm not 100% sure what you're asking for, but I believe you're trying to write something like this:
lines.Split([|'\n'|) |> Seq.map (fun line -> line.Length)
This converts each line to a sequence of integers representing the length of each line.
Here's my solution:
string(Seq.sumBy bigint.Parse (data.Split[|'\n'|])).Substring(0, 10)
I copied the data into a string, each line separated by x. Then the answer is one line (wrapped for SO):
let ans13 = data |> String.split ['x'] |> Seq.map Math.BigInt.Parse
|> Seq.reduce (+)
If you are reading it from a file, you'd add the file reading code:
let ans13 = IO.File.ReadAllLines("filename") |> Seq.map Math.BigInt.Parse
|> Seq.reduce (+)
Edit: Actually, I'm not sure we're talking about the same Euler problem -- this is for 13, but your description sounds slightly different. To get the first 10 digits after the summing, do:
printfn "%s" <| String.sub (string ans13) 0 10
Related
I'm going through a mutable ConcurrentDictionary to remove old entries.
let private cache = ConcurrentDictionary<Instrument * DateTimeOffset, SmallSet>()
and since I can't remove entries while iterating through the keys, I was wondering if this would be a good use for Seq.cache:
let old = DateTimeOffset.UtcNow.AddHours(-1.)
cache.Keys
|> Seq.filter (fun x -> snd x <= old)
|> Seq.cache
|> Seq.iter (fun x -> cache.TryRemove x |> ignore)
I have never used Seq.cache, and I assume it creates a separation between the two loops. Am I understanding how it works correctly?
In the scenario you described I don't see any reason why you need to iterate the collection multiple times. You can just go over the KeyValuePairs inside the dictionary and analyze each KeyValuePair if it matches your condition or no.
So, something like this should do the job:
cache |> Seq.iter(function
| x when snd x.Key <= old -> cache.TryRemove(x.Key) |> ignore
| _ -> ())
I am new to programming and F# is my first .NET language.
I would like to read the contents of a text file, count the number of occurrences of each word, and then return the 10 most common words and the number of times each of them appears.
My questions are: Is using a dictionary encouraged in F#? How would I write the code if I wish to use a dictionary? (I have browsed through the Dictionary class on MSDN, but I am still puzzling over how I can update the value to a key.) Do I always have to resort to using Map in functional programming?
While there's nothing wrong with the other answers, I'd like to point out that there's already a specialized function to get the number of unique keys in a sequence: Seq.countBy. Plumbing the relevant parts of Reed's and torbonde's answers together:
let countWordsTopTen (s : string) =
s.Split([|','|])
|> Seq.countBy (fun s -> s.Trim())
|> Seq.sortBy (snd >> (~-))
|> Seq.truncate 10
"one, two, one, three, four, one, two, four, five"
|> countWordsTopTen
|> printfn "%A" // seq [("one", 3); ("two", 2); ("four", 2); ("three", 1); ...]
My questions are: Is using a dictionary encouraged in F#?
Using a Dictionary is fine from F#, though it does use mutability, so it's not quite as common.
How would I write the code if I wish to use a dictionary?
If you read the file, and have a string with comma separated values, you could
parse using something similar to:
// Just an example of input - this would come from your file...
let strings = "one, two, one, three, four, one, two, four, five"
let words =
strings.Split([|','|])
|> Array.map (fun s -> s.Trim())
let dict = Dictionary<_,_>()
words
|> Array.iter (fun w ->
match dict.TryGetValue w with
| true, v -> dict.[w] <- v + 1
| false, _ -> dict.[w] <- 1)
// Creates a sequence of tuples, with (word,count) in order
let topTen =
dict
|> Seq.sortBy (fun kvp -> -kvp.Value)
|> Seq.truncate 10
|> Seq.map (fun kvp -> kvp.Key, kvp.Value)
I would say an obvious choice for this task is to use the Seq module, which is really one of the major workhorses in F#. As Reed said, using dictionary is not as common, since it is mutable. Sequences, on the other hand, are immutable. An example of how to do this using sequences is
let strings = "one, two, one, three, four, one, two, four, five"
let words =
strings.Split([|','|])
|> Array.map (fun s -> s.Trim())
let topTen =
words
|> Seq.groupBy id
|> Seq.map (fun (w, ws) -> (w, Seq.length ws))
|> Seq.sortBy (snd >> (~-))
|> Seq.truncate 10
I think the code speaks pretty much for itself, although maybe the second last line requires a short explanation:
The snd-function gives the second entry in a pair (i.e. snd (a,b) is b), >> is the functional composition operator (i.e. (f >> g) a is the same as g (f a)) and ~- is the unary minus operator. Note here that operators are essentially functions, but when using (and declaring) them as functions, you have to wrap them in parentheses. That is, -3 is the same as (~-) 3, where in the last case we have used the operator as a function.
In total, what the second last line does, is sort the sequence by the negative value of the second entry in the pair (the number of occurrences).
Since functions in FSharp with multiple parameters get curried inherently into functions with only one parameter, should the signature of Seq.filter have to be
Seq.filter predicate source
?
How different will it be from
Seq.filter source predicate
Thanks
The first order (predicate, sequence) is more appropriate for chaining sequence combinators via the |> operator. Typically, you have a single sequence to which you apply a number of operations/transformations, consider something like
xs |> Seq.map ... |> Seq.filter ... |> Seq. ...
etc. Reversing the order of the parameters to (source, predicate) would prohibit that (or at least make it much more awkward to express). That (and maybe also partial application) is why for (almost) all the default Seq combinators the last parameter is the sequence the operation is applied to.
The reason it is
Seq.filter predicate source
instead of
Seq.filter soure predicate
is so that you can do this
source
|> Seq.filter predicate
Since you are more likely to build a new function using Seq.filter predicate
let isEven = Seq.filter (fun x -> x % 2 = 0)
you can now do
source |> isEven
There are functions in F# where the order of parameters are not done like this because of it's history of coming from OCaml. See: Different argument order for getting N-th element of Array, List or Seq
Yes Seq.filter takes the predicate followed by the sequence to filter. If you want to provide them in the other order you could write a function to reverse the arguments:
let flip f a b = f b a
then you could write
(flip Seq.filter) [1..10] (fun i -> i > 3)
The existing order is more convenient however since it makes partial application more useful e.g.
[1..3] |> Seq.map ((*)2) |> Seq.filter (fun i -> i > 2)
and you have also ||> for piping functions accepting two arguments signature, or partially apply 2 arguments to a wider signature. : )
I have a sequence of floats in F#, and I need to get a sequence defined of (Math.Log currentElement)/(Math.Log previousElement). Obviously it will be shorter than the original sequence by one element.
What is the most elegant way to achieve this in F#? I was thinking to use a seq{} expression with a for loop inside, but even then handling the first element in a reasonably nice way seems difficult...
items |> Seq.pairwise |> Seq.map (fun (x, y) -> log y / log x)
Or if you prefer:
let f (x, y) = (log y) / (log x)
let ans = s |> Seq.pairwise |> Seq.map f
I'm quite (very) new to F# and I'm scratching my head over a little problem. I have a string list list that I'm trying to manipulate and transform. This is probably trivial.
The following data is being read in from a CSV file:
1,ABC,3
1,DEF,3
1,XYZ,1
2,ABC,2
2,XYZ,1
3,DEF,2
3,XYZ,2
Which right or wrong, I'm reading into a string list list. This data represents a non-normalized set of data, where the field at index 0 on each record is an Identifier field. At the moment I'm just trying to split the outer-list up so that I end up with a string list list list representing the following:
1,ABC,3 2,ABC,2 3,DEF,2
1,DEF,3 2,XYZ,1 3,XYZ,2
1,XYZ,1
The results above will then be pushed into my Typed model and fed into the rest of the application.
In your code:
csvRecords
|> Seq.groupBy (fun record -> (record.Item 0))
|> List.ofSeq
|> List.map(toTypedModel)
record.Item 0 isn't a good way to get the first element of a list. You should either use List.head or pattern matching for that purpose.
Your example would look like:
csvRecords
|> Seq.groupBy List.head
|> Seq.map toTypedModel
|> List.ofSeq
I also changed the order to use toTypedModel with sequence, it helps to avoid allocating an unnecessary list.
Use Seq.groupby -
input
|> Seq.groupBy (fun (a,b,c) -> a)
|> Seq.toList