I can't seem to get the FSCheck shrinker to work. Say I have this
let arb_chars =
Arb.fromGenShrink(
Arb.generate<char[]>,
fun cs -> seq {
printfn "shrinking..."
for i in 0..(cs.Length) do
printfn " shrink %d" i
yield [| cs.[0] |]
})
let prop_len() = gen {
//let! a = Arb.generate<char[]> // this doesn't work either...
let! a = arb_chars.Generator
let len = a.Length
printfn "a.Length = %A" len
return (len <> 5)
}
:
Check.One(config, prop_len)
When I run it, I always get 0 shrinks. Here's a typical run:
a.Length = 0
a.Length = 4
a.Length = 1
a.Length = 0
a.Length = 4
a.Length = 7
a.Length = 6
a.Length = 7
a.Length = 19
a.Length = 18
a.Length = 5
Falsifiable, after 11 tests (0 shrinks) (StdGen (19971972,296557937)):
Original:
<null>
Use Prop.forAll to define your property and use the custom generator/shrinker. Something like this (sorry typing from memory but should be close)
let prop_len = Prop.forAll (arb_chars)
(fun a ->
let len = a.Length
printfn "a.Length = %A" len
return (len <> 5)
)
Related
I need to add 1 to each element in an array, and if it goes out of range, I need to start over.
let arr = [| 1; 2; 3 |]
for i = 0 to Array.length arr - 1 do
arr.[i] <- arr.[i] + 1
printfn "i %A" (arr.[i])
I want to add 5 points to the array, so that it iterates over the array and gives one point in each element, so the array would partially be [| 2; 3; 4 |] and iterate through the array again and end up being arr = [| 3; 4; 4 |]
Actually you can calculate exactly how much you should add to each element of array. So you can solve the problem by going through the array in only one time.
let addPoints arr points =
let len = arr |> Array.length
let added = points / len
let extraCount = points % len
arr
|> Array.mapi (fun i x ->
if i < extraCount then x + added + 1
else x + added)
addPoints [| 1; 2; 3 |] 5
|> printfn "%A" // [|3; 4; 4|]
Mutating the array or not, it's up to you.
Rather than mutating the array, a more idiomatic F# approach is to create a new array with the newly calculated results. You can use the built-in Array.map function to do apply the same transformation to each element of the array. To increment all by one, you can write:
let arr = [| 1; 2; 3 |]
arr |> Array.map (fun v -> v + 1)
If you want to restrict the maximal value to 4, you'll need to do that in the body of the function, i.e. v + 1. To make it easier to do this repeatedly, it's helpful to define a function.
let step arr =
arr |> Array.map (fun v -> min 4 (v + 1))
Here, step is a function you can call to do one step of the transformation. min 4 (v + 1) ensures that when v + 1 is more than 4, you get just 4 as the result. Now you can run step repeatedly using |>:
let arr1 = arr |> step
let arr2 = arr |> step |> step
I agree with #TomasPetricek in that the way to go should be to create new arrays using map. However, if you must mutate the array, the following loop-based approach should work just fine:
let incArrayElements n (a : _ []) =
let rec loop k i =
if k > 0 then
a.[i] <- a.[i] + 1
let ii = i + 1
if ii >= a.Length then 0 else ii
|> loop (k - 1)
if n > 0 then loop n 0
If required, this can also be easily modified to include a parameter for the starting index.
Trying to learn F#, by solving some programming puzzles. I don't want to add too many details about the problem as I don't want to spoil the fun for others.
Basically, the issue is to find all 4-uples { (i,j,k,l) | i ^ j ^ k ^ l != 0 } with no repetition (eg., (1,1,1,2) and (1,1,2,1) are the same and should be counted just once).
I have found a O(n^3) approach which works, please see countImperative(a,b,c,d) below. But I also tried to refactor the code as to get rid of the nested for loops. However, I could not do so without a significant performance penalty. It was my impression that F#'s syntactic sugar would allow a more concise style (using pipes and folds), letting the compiler do the heavy-lifting to produce comparably fast code (compared to my nested for loops). The big performance hit comes from the calculation of the partial2 sum.
Here's the code:
open System
open System.Diagnostics
open System.Collections
module quadruples =
[<EntryPoint>]
let main argv =
let input = "2000 2000 2000 2000"
let ordered = [ for x in input.Split([|' '|]) -> Convert.ToInt32(x) ] |> List.sort
let a,b,c,d = ordered.[0], ordered.[1], ordered.[2], ordered.[3]
let inner(a,b) = a * (a-1) / 2 + a * (b-a)
let sw = new Stopwatch()
sw.Start()
let partial1 = [ 1.. b ] |> List.fold (fun acc j -> acc + (int64 ((min a j) * inner(c-j+1, d-j+1)))) 0L
sw.Stop()
let elapsed1 = (sw.ElapsedMilliseconds |> double) / 1000.0
printfn "Partial1: %f s" elapsed1
sw.Restart()
let combinations = [ for i in 1..a do for j in i+1..b do yield (j,i^^^j) ]
let range = [ 1..c ]
let partial2 = combinations |> List.fold(fun acc (j,x) -> acc + (range |> List.skip(j-1) |> List.fold(fun acc k -> if k ^^^ x < k || k ^^^ x > d then acc + 1L else acc) 0L)) 0L
sw.Stop()
let elapsed2 = (sw.ElapsedMilliseconds |> double) / 1000.0
printfn "Partial2: %f s" elapsed2
printfn "Functional: %d, Elapsed: %f s" (partial1 + partial2) (elapsed1 + elapsed2)
// "imperative" approach
let countImperative(a,b,c,d) =
let mutable count = seq { 1..b } |> Seq.fold (fun acc j -> acc + (int64 ((min a j) * inner(c-j+1, d-j+1)))) 0L
for i in 1..a do
for j in i+1..b do
let x = i ^^^ j
for k in j..c do
let y = x ^^^ k
if y < k || y > d then
count <- count + 1L
count
sw.Restart();
let count = countImperative(a,b,c,d)
sw.Stop()
printfn "Imperative: %d, Elapsed: %f s" count ((sw.ElapsedMilliseconds |> double) / 1000.0)
0 // return an integer exit code
So my question was, if there is any way to speed up the code (specifically the calculation of partial2) while maintaining F#'s nice syntax.
I'm recently new to F# so please bear with me. The problem i have is I'm trying to find only prime numbers.
I've write this code:
let isPrime n =
let rec check i =
i > n/2 || (n % i <> 0 && check (i + 1))
check 2;;
let listNums = List.filter isPrime >> List.length;;
let nums = [ 16; 17; 3; 4; 2; 5; 11; 6; 7; 18; 13; 14; ];;
let countPrimes (x:int) = x |> List.ofSeq |> listNums;;
trying to call
countPrimes nums;;
but this is failed with message:
The type 'int' is not compatible with the type 'seq<'a>'
any help would be appreciated
I found the solution
let isPrime n =
let rec check i =
i > n/2 || (n % i <> 0 && check (i + 1))
check 2;;
let listNums = List.filter isPrime >> List.length;;
let nums = [| 16; 17; 3; 4; 2; 5; 11; 6; 7; 18; 13; 14; |];;
let countPrimes (x:int[]) = x |> List.ofSeq |> listNums;;
countPrimes nums;;
Thanks all!
x |> List.ofSeq
seems to be the problem to me. You are passing an int into a function that requires a list. List.toSeq changes a list into a sequence. You want the function countPrimes to take a List of integers, not simply an integer. Although Carsten is right, listNums already takes a List of integers (edit: and computes the value you want provided isPrime is correct).
You do not need to countPrimes separately. Enough to remove and will work:
let isPrime n =
let rec check i =
i > n/2 || (n % i <> 0 && check (i + 1))
check 2
let nums = [ 16; 17; 3; 4; 2; 5; 11; 6; 7; 18; 13; 14; ]
let listPrime lst =
lst |> List.filter isPrime
nums |> listPrime |> printfn "%A"
Out:
[17; 3; 2; 5; 11; 7; 13]
Link:
https://dotnetfiddle.net/nVXwZ5
I have a string which should only contain alphabets. To check that I have written the following code
let isCorrectString(str:string) =
let isInRange x = (x > 64 && x < 91 ) || (x > 96 && x < 123) || x = 32
not (str.Any(fun ch -> not (isInRange (ch :?> int)) ))
I am obviously using LINQ's `Any' extension method here. Is there any better way to write the above code ?
If you want to just verify that it's correct, you could do:
let isCorrectString(str:string) =
let isInRange x = (x > 64 && x < 91 ) || (x > 96 && x < 123) || x = 32
let bad =
str
|> Seq.map (fun c -> isInRange(int c))
|> Seq.exists (fun b -> b = false)
not bad
Note that this may be a simpler alternative:
let isCorrectString(str:string) =
str
|> Seq.forall (fun c -> System.Char.IsLetter(c) || c = ' ')
Or, if you prefer:
let isCorrectString(str:string) =
str
|> Seq.tryFind (fun c -> not(System.Char.IsLetter(c) || c = ' '))
|> Option.isNone
Ok, this looks like it should be easy, but I'm just not getting it. If I have a sequence of numbers, how do I generate a new sequence made up of the running totals? eg for a sequence [1;2;3;4], I want to map it to [1;3;6;10]. In a suitably functional way.
Use List.scan:
let runningTotal = List.scan (+) 0 >> List.tail
[1; 2; 3; 4]
|> runningTotal
|> printfn "%A"
Seq.scan-based implementation:
let runningTotal seq' = (Seq.head seq', Seq.skip 1 seq') ||> Seq.scan (+)
{ 1..4 }
|> runningTotal
|> printfn "%A"
Another variation using Seq.scan (Seq.skip 1 gets rid of the leading zero):
> {1..4} |> Seq.scan (+) 0 |> Seq.skip 1;;
val it : seq<int> = seq [1; 3; 6; 10]
> Seq.scan (fun acc n -> acc + n) 0 [1;2;3;4];;
val it : seq<int> = seq [0; 1; 3; 6; ...]
With lists:
> [1;2;3;4] |> List.scan (fun acc n -> acc + n) 0 |> List.tail;;
val it : int list = [1; 3; 6; 10]
Edit: Another way with sequences:
let sum s = seq {
let x = ref 0
for i in s do
x := !x + i
yield !x
}
Yes, there's a mutable variable, but I find it more readable (if you want to get rid of the leading 0).
Figured it was worthwhile to share how to do this with Record Types in case that's also what you came here looking for.
Below is a fictitious example demonstrating the concept using runner laps around a track.
type Split = double
type Lap = { Num : int; Split : Split }
type RunnerLap = { Lap : Lap; TotalTime : double }
let lap1 = { Num = 1; Split = 1.23 }
let lap2 = { Num = 2; Split = 1.13 }
let lap3 = { Num = 3; Split = 1.03 }
let laps = [lap1;lap2;lap3]
let runnerLapsAccumulator =
Seq.scan
(fun rl l -> { rl with Lap = l; TotalTime = rl.TotalTime + l.Split }) // acumulator
{ Lap = { Num = 0; Split = 0.0 }; TotalTime = 0.0 } // initial state
let runnerLaps = laps |> runnerLapsAccumulator
printfn "%A" runnerLaps
Not sure this is the best way but it should do the trick
let input = [1; 2; 3; 4]
let runningTotal =
(input, 0)
|> Seq.unfold (fun (list, total) ->
match list with
| [] ->
None
| h::t ->
let total = total + h
total, (t, total) |> Some)
|> List.ofSeq