Ternary operator to choose an Array index - f#

Unexpected ']' in expression
I have successfully managed to get the first part of the code working and now want to find the players real score using the index stored inside the member. I am using playersTurn and checking if its odd or even to represent the players turn.
The issue I am having now is using a ternary operator to get the score in the following line of code:
let score = this.scoring[this.playersTurn % 2 = 0 ? this.playerOneScore : this.playerTwoScore]
Any help would be brilliant, here is the full code:
open System
type Game(playerOne, playerTwo) =
member this.playersTurn = 0
member this.playerOneName = playerOne
member this.playerOneScore = 0
member this.playerTwoName = playerTwo
member this.playerTwoScore = 0
member this.scoring = [|0; 15; 30; 40|]
member this.takeTurn() =
let name = this.playersTurn % 2 = 0 ? this.playerOneName : this.playerTwoName
let score = this.scoring[this.playersTurn % 2 = 0 ? this.playerOneScore : this.playerTwoScore]
printfn name |> "%d is now taking their turn."
if((new System.Random()).Next(0, 15) > 8) then
if (this.playersTurn % 2 = 0) then incr this.playerOneScore
else incr this.playerTwoScore
printfn name |> "%d scored a point!"
else
printfn name |> "%d did not score a point!"
incr this.playersTurn
let tennis = new Game("Player1", "Player2")
tennis.takeTurn()
tennis.takeTurn()

To make the code work, you'll need to do a few more changes. Most importantly, you are using class with members, but those are read-only getter properties in F#. You could make them mutable, but that's not idiomatic; better option is to change the function so that it returns the new game state.
If you are learning F#, then I think it's better to make more changes and avoid using classes (they are not used that frequently in F#) and also go for a solution that does not need mutation. The following is close to what you had.
I extracted the common definitions into ordinary let values - you can later define a record (simple data type) to keep them, but for now, this is the easiest option:
open System
let scoring = [|0; 15; 30; 40|]
let playerOne = "Player1"
let playerTwo = "Player2"
let rnd = new System.Random()
I turned your method into a function that takes number of turns and initial scores as a tuple and returns new state. The syntax (playersTurn, (playerOneScore, playerTwoScore)) defines a tuple with number of turns and a nested tuple with the two scores (I choose this because the two scores are logically related, so it's nice to store them together):
let takeTurn (playersTurn, (playerOneScore, playerTwoScore)) =
let name = if playersTurn % 2 = 0 then playerOne else playerTwo
let score = scoring.[if playersTurn % 2 = 0 then playerOneScore else playerTwoScore]
printfn "%s is now taking their turn." name
let newOneScore, newTwoScore =
if (rnd.Next(0, 15) > 8) then
printfn "%s scored a point!" name
if (playersTurn % 2 = 0) then playerOneScore + 1, playerTwoScore
else playerOneScore, playerTwoScore + 1
else
printfn "%s did not score a point!" name
playerOneScore, playerTwoScore
playersTurn+1, (newOneScore, newTwoScore)
Now you can define an initial state and call takeTurn repeatedly to get the next state (and the next state and so on):
let start = 0, (0, 0)
let step1 = takeTurn start
let step2 = takeTurn step1
You'll obviously want to run this in a loop - which you can do in the functional way using recursion, or using a function such as Seq.unfold.

You're using the C# syntax for a ternary operator in F#. You really need:
this.scoring.[if this.playersTurn % 2 = 0 then this.playerOneScore else this.playerTwoScore]

Related

Using F# and SIMD to search for index of value

I'm working on putting together an algorithm for searching through an array to find the index of a given value. I'm trying to follow a similar technique found in the .NET Core CLR.
Where I am confused is the value for the idx that is returned by the call to BitOperations.TrailingZeroCount. When I search for 2 it should return an index value of 1 for the data that I am searching. What I get is a 4. Do I need to do some conversion from the byte offset back to whatever the actual type is? Is this the most efficient way to write this? There are not many docs on using intrinsics with .NET.
open System
open System.Runtime.Intrinsics.X86
open System.Runtime.Intrinsics
open System.Numerics
#nowarn "9"
#nowarn "20"
[<EntryPoint>]
let main argv =
let searchSpace : Span<int32> = Span [| 1 .. 8 |]
let pSearchSpace = && (searchSpace.GetPinnableReference ())
let search = Sse2.LoadVector128 (pSearchSpace)
let value = 2
let values = Vector128.Create value
let comparison = Sse2.CompareEqual (values, search)
let matches = Sse2.MoveMask (comparison.AsByte())
if matches > 0 then
let idx = BitOperations.TrailingZeroCount matches
printfn "%A" idx // <--- This prints 4 instead of 1
0 // return an integer exit code
Sse2.MoveMask (comparison.AsByte()) (i.e. vpmovmskb) gives you 4 mask bits per int32 match result, one from each Byte like you asked for.
Either use vmovmskps (perhaps MoveMask(cmp.AsFloat()), if that's how F# does it?) or deal with the byte instead of element indices you get from bsf / tzcnt.

How to access the first element of a tuple in a list?

I am trying to make a collision method in a class in f#.
The collision method should have one input which is time.
The method should check a number of drones that should be moving with time and whether some of them will collide. A collision is defined as being within 5 "blocks" of each other.
I have so far this code for the method.
type Airspace(drones:Drone list) =
let mutable drones = drones
member x.Drones with get() = drones
member x.Collision(time:int) =
for d = 1 to time do
for i = 1 to drones.Length do
for j = 1 to drones.Length do
if drones.Item(i).Position.Item1 - drones.Item(j).Position.Item1 >= -5.0 || drones.Item(i).Position.Item1 - drones.Item(j).Position.Item1 <= 5.0
then if drones.Item(i).isFinished() = True && drones.Item(j).isFinished() = True then printfn "Drone: %A will collide with %A" (drones.Item(i)) (drones.Item(j))
By the way drones is a list of Drones and a drone has a current position as a tuple floatfloat, a destination also as a floatfloat and speed which is a float.
I am pretty sure this is wrong
drones.Item(i).Position.Item1
But I am not sure how I can access the first i'th element in a list and then take only the first element of the tuple and compare it with another one. How can I do this?
Well, it's not 100% wrong, it might work but yes, the recommendation is not to use ItemX and instead to pattern match the tuple elements, so you can do this:
let (xi, _) = drones.Item(i).Position
let (xj, _) = drones.Item(j).Position
if xi - xj >= -5.0 || xi - xj <= 5.0
Btw, if you don't really need to use the index you can also change the loops to:
for di in drones do
for dj in drones do
let (xi, _) = di.Position
let (xj, _) = dj.Position
Also note that you can use the function List.allPairs piped to List.tryFind instead of for loops.

Why is there a parse error in this Haskell 'else if' statement?

I am looking for a hint or explanation as to why this chunk of code keeps getting a parse error on the first else if statement in the block. It says it may be a problem with indentation or parenthesis but I cant seem to find them. So I was looking for another set of experienced eyes to set me on the right course. I feel like there is something very small I am overlooking, but I just cant seem to find it. This is for a sudoku solver(Ill admit the whole sudoku solver is a class assignment. This is my first time posting so Im not 100% certain if this is an acceptable question, please let me know if it is not).
This function is to take a sudoku game board (Which is basically a list of lists) and two ints which are the coordinates for the 3x3 section of the board you are looking at and then return the sequence of numbers from that 3x3 section of board.
I know this isnt the haskelian way to solve this problem (I sort of brute forced it in the end), Im really only been learning Haskell for a few weeks, but I wanted to figure out why the else if keeps popping up as an error.
getBox :: Board -> Int -> Int -> Sequence
getBox b x y = do
let i = x
let j = y
let x0 = b!!0
let x1 = b!!1
let x2 = b!!2
let x3 = b!!3
let x4 = b!!4
let x5 = b!!5
let x6 = b!!6
let x7 = b!!7
let x8 = b!!8
if (i==0 && j==0)
then let z = [x0!!0, x0!1, x0!!2, x1!!0 x1!!1, x1!!2, x2!!0, x2!!1, x2!!2]
else if (i==0 && j==1)
then let z = [x0!!3, x0!4, x0!!5, x1!!3 x1!!4, x1!!5, x2!!3, x2!!4, x2!!5]
else if (i==0 && j==2)
then let z = [x0!!6, x0!7, x0!!8, x1!!6 x1!!7, x1!!8, x2!!6, x2!!7, x2!!8]
else if (i==1 && j==0)
then let z = [x3!!0, x3!!1, x3!!2, x4!!0, x4!!1, x4!!2, x5!!0, x5!!1, x5!!2]
else if (i==1 && j==1)
then let z = [x3!!3, x3!!4, x3!!5, x4!!3, x4!!4, x4!!5, x5!!3, x5!!4, x5!!5]
else if (i==1 && j==2)
then let z = [x3!!6, x3!!7, x3!!8, x4!!6, x4!!7, x4!!8, x5!!6, x5!!7, x5!!8]
else if (i==2 && j==0)
then let z = [x6!!0, x6!!1, x6!!2, x7!!0, x7!!1, x7!!2, x8!!0, x8!!1, x8!!2]
else if (i==2 && j==1)
then let z = [x6!!3, x6!!4, x6!!5, x7!!3, x7!!4, x7!!5, x8!!3, x8!!4, x8!!5]
else let z = [x6!!6, x6!!7, x6!!8, x7!!6, x7!!7, x7!!8, x8!!6, x8!!7, x8!!8]
Just delete let z = everywhere it appears, and you'll be on your way to your next error.
A let expression has a binding and a body. A prototypical let expression is:
let x = 2 in x + x
^^^^^ ^^^^^
binding body
Which just means substitute 2 for x in the body. That's all let ever means (that is, you could always get rid of the let manually by substituting). It is a bit obscured by the allowed syntax for let within a do block, which may give the impression that it is like a mutable variable in an imperative language, but it is not.
do
let i = x
let j = y
pure (i + j)
Means
let i = x in
let j = y in
pure (i + j)
That is, the body of the let is the remainder of the do block.
Any variable can be traced back to a single unique definition or function parameter. A variable can't be defined by multiple different let statements dynamically, as you are trying to do. You need to define z only once. In your case, this can be done with guards, which is a way to make conditional definitions.
let z
| i == 0 && j == 0 = [x0!!0, x0!!1, -- oh my god I am not typing this
| i == 0 && j == 1 = [x0!!3, x0!!4, -- more?
| ...
You could have also done it without guards, you just need to move your chain of ifs inside the let:
let z = if i == 0 && j == 0 then [...]
else if i == 0 && j == 1 then [...]
...
I hope this helps. May the pains of your brute-force solutions be amortized.

F# how to write a function which provides a counter number in serial order

So if you go to a bank there is a device from which you can pull a number out.
I want to write a function like that. So everytime this function is called we get a next number in the series.
So if this function is called first time, we get 1. second time we get 2.... so on and so forth.
this is what I have written so far
let X =
let myseq = seq {1 .. 100}
let GetValue =
Seq.head (Seq.take 1 myseq)
GetValue;;
let p = X;;
p;;
p;;
p;;
But it always return 1. My hope was that since the sequence is a closure, everytime I do a take, I will get the next number.
I also tried this
let X =
let mutable i = 1
let GetValue =
i <- i + 1
i
GetValue;;
let p = X;;
p;;
p;;
p;;
This one only prints 2...
You have to return a function. And to it, you have to pass something every time, i.e. your +1 has to be deferred.
let factory =
let counter = ref 0
fun () ->
counter.Value <- !counter + 1
!counter
and now you get
> factory();;
val it : int = 1
> factory();;
val it : int = 2
doing it this way has the nice side-effect, that you completely hide the mutable reference cell inside the function and thus there is no way to somehow tamper with your counter.
Just for a reference, if you wanted a version that uses sequences (just like the first approach in your question), you can do that using the IEnumerable interface:
let factory =
// Infinite sequence of numbers & get enumerator
let numbers = Seq.initInfinite id
let en = numbers.GetEnumerator()
fun () ->
// Move to the next number and return it
en.MoveNext() |> ignore
en.Current
It behaves the same way as factory in Daniel's answer. This still uses mutable state - but it is hidden inside the enumerator (which keeps the current state of the sequence between MoveNext calls).
In this simple case, I'd use Daniel's version, but the above might be handy if you want to iterate over something else than just increasing numbers.
You need to move the variable outside the declaration. You also need to declare a function so that it gets evaluated each time it is called.
let mutable i = 1
let X() =
i <- i + 1
i
This ensures that the function is called each time and that the variable is correctly incremented.

retrieving all results in RavenDB

I thought I could force to retrieve all results through multiple page and skip, using the statistics function
type Linq.IRavenQueryable<'T>
with member q.getAll() = let mutable stat = Linq.RavenQueryStatistics()
let total = stat.TotalResults
let a = q.Statistics(&stat)
let rec addone n = seq { yield q.Skip(n*1024).Take(1024).ToArray()
if n*1024 < total then
yield! addone (n + 1) }
addone 0 |> Array.concat
It works when you do
let q = session.Query<productypfield>()
let r = q.getAll()
but breaks with
let q = session.Query<productypfield>().Where(System.Func ....)
let r = q.getAll()
As the type Linq.IRavenQueryable is not idempotent through Linq composition : If I use Linq, I get an IEnumerable on which no q.Statistics(&stat) is defined.
I read the doc, and I dont see anyway to keep the type through Linq composition.
IS the only way to loop a fixed (high) amount of times, or set a high servepagesize, and take(a lot of elements) ?
edit : actually, even the code above does not work as apparently, to get a valid count, you need to run the query once. one has to call Take(0) to trigger it.
use session = store.OpenSession()
let q = session.Query<productypfield>()
let mutable s = Linq.RavenQueryStatistics()
let a = q.Statistics(&s)
s.TotalResults = 0 //true
printfn "%A" a //triggers evaluation
s.TotalResults = 0 //false
Can you change your 2nd code sample to this (I'm not familiar with F#):
let q = session.Query<productypfield>().Where(Expression<System.Func<....>>)
let r = q.getAll()
that should let you keep the IQueryable that you need

Resources