let compareDiagonal p x y =
System.Math.Abs((int)(x - (fst p))) <> System.Math.Abs((int)(y - (snd p)));;
let isAllowed p = function
| [] -> true
| list -> List.forall (fun (x, y) -> fst p <> x && snd p <> y && (compareDiagonal p x y)) list;;
let rec solve col list =
let solCount : int = 0
match col with
| col when col < 8 ->
for row in [0 .. 7] do
solCount = solCount + if isAllowed (row, col) list then solve (col + 1) ((row, col) :: list) else 0
solCount
| _ -> 1;;
let solCount = solve 0 [];;
solCount;;
I am getting the error
solCount = solCount + if isAllowed (row, col) list then (solve (col + 1) ((row, col) :: list)) else 0
------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
stdin(335,13): warning FS0020: This expression should have type 'unit', but has type 'bool'. If assigning to a property use the syntax 'obj.Prop <- expr'.
Why am I not able to return the number?
There are two related problems.
By default in F# variable are immutable. If you want a mutable variable, you have to declare it, like this:
let mutable solCount : int = 0
And then when you assign values to it instead of using = you have to use <- like this:
solCount <- solCount + if isAllowed (row, col) list then solve (col + 1) ((row, col) :: list) else 0
A complete example followed.
HOWEVER, this is not the correct functional way to do something like this. Instead of using a loop to add up values, use a recursive function to return the cumulative value as you go. Using F# the way functional programs are designed to be used will almost always yield better results, although it takes some getting used to.
Your original example with mutable, not the "functional way":
let compareDiagonal p x y =
System.Math.Abs((int)(x - (fst p))) <> System.Math.Abs((int)(y - (snd p)));;
let isAllowed p = function
| [] -> true
| list -> List.forall (fun (x, y) -> fst p <> x && snd p <> y && (compareDiagonal p x y)) list;;
let rec solve col list =
let mutable solCount : int = 0
match col with
| col when col < 8 ->
for row in [0 .. 7] do
solCount <- solCount + if isAllowed (row, col) list then solve (col + 1) ((row, col) :: list) else 0
solCount
| _ -> 1;;
let solCount = solve 0 [];;
solCount;;
Related
Let's say I have a list in F# like this: [5,-2, -6, 7, -2, 2, 14, 2]
I want to write a function that will use List.fold to return a new list such as [5, -8, 7, -2, 18]
My template looks like this:
let sumAdjacentOfSameSign (lst :int list) : int list =
let f x y =
if x.Length = 0 then
[y]
elif System.Math.Sign(x) = System.Math.Sign(y) then ...
else y :: x
List.fold f [] lst
I need to fill in the ... part but can't quite say how.
Making the fewest changes to your code, I would do this:
let sumAdjacentOfSameSign (lst :int list) : int list =
let f (x : int list) (y : int) =
if x.Length = 0 then
[y]
elif System.Math.Sign(x.Head) = System.Math.Sign(y) then
(x.Head + y) :: x.Tail
else y :: x
List.fold f [] lst
|> List.rev // note that you have to reverse the resulting list
But I would suggest simplifying f to:
let f (x : int list) (y : int) =
match x with
| head :: tail when
System.Math.Sign(head) = System.Math.Sign(y) ->
(head + y) :: tail
| _ -> y :: x
I'm trying to write a function that takes a list for example
let list = [5;23;29;1]
let x = max list // This will return 2 because 29 will be the max value and it's "indexed" at position 2
I'm not sure about how to go about writing the max function
Since my list will only contain four elements I currently have some code like this
let list = (1, newMap1 |> getScore) :: (2, newMap2 |> getScore) :: (3, newMap3 |> getScore) :: (4, newMap4 |> getScore) :: []
I consider this a terrible approach but I'm still stuck on how to return (x, _) after I find the max of (_, y). I'm very confident with imperative approaches but I'm stumped on how to do this functionally
There is a couple of ways to do this. At the low-level, you can write a recursive function to iterate and pattern match over a list. This is good exercise if you are learning F#.
Similarly, you can implement this using the fold function. Here, the idea is that we keep some state, consisting of the "best value" and the index of the best value. At each step, we either keep the original information, or update it:
let _, maxValue, maxIndex =
list |> List.fold (fun (index, maxSoFar, maxIndex) v ->
if v > maxSoFar then (index+1, v, index+1)
else (index+1, maxSoFar, maxIndex)) (-1, System.Int32.MinValue, -1)
Finally, the shortest option I can think of is to use mapi and maxBy functions:
list
|> Seq.mapi (fun i v -> i, v)
|> Seq.maxBy snd
Here's an answer only using pattern matching and recursion.
let list = [5;23;29;1]
let rec findIndexOfMaxValue (maxValue:int) indexOfMaxValue currentIndex aList =
match aList with
| [] -> indexOfMaxValue
| head::tail -> match head with
| head when head > maxValue -> findIndexOfMaxValue head currentIndex (currentIndex + 1) tail
| _ -> findIndexOfMaxValue maxValue indexOfMaxValue (currentIndex + 1) tail
[<EntryPoint>]
let main argv =
let indexOfMaxValue = findIndexOfMaxValue 0 0 0 list
printfn "The index of the maximum value is %A." indexOfMaxValue
//The index of the maximum value is 2.
0
Out of interest, I made a timing script comparing my algorithm with the other ones provided:
open System.Diagnostics
let n = 5000
let random = System.Random 543252
let randomlists =
[for i in [1..n] -> [ for i in [1..n] -> random.Next (0, n*n)]]
let stopWatch =
let sw = Stopwatch ()
sw.Start ()
sw
let timeIt (name : string) (a : int list -> 'T) : unit =
let t = stopWatch.ElapsedMilliseconds
let v = a (randomlists.[0])
for i = 1 to (n - 1) do
a randomlists.[i] |> ignore
let d = stopWatch.ElapsedMilliseconds - t
printfn "%s, elapsed %d ms, result %A" name d v
let rec findIndexOfMaxValue (maxValue:int) indexOfMaxValue currentIndex aList =
match aList with
| [] -> indexOfMaxValue
| head::tail -> match head with
| head when head > maxValue -> findIndexOfMaxValue head currentIndex (currentIndex + 1) tail
| _ -> findIndexOfMaxValue maxValue indexOfMaxValue (currentIndex + 1) tail
let findIndexOfMaxValueFoldAlg list =
let _, maxValue, maxIndex =
list |> List.fold (fun (index, maxSoFar, maxIndex) v ->
if v > maxSoFar then (index+1, v, index+1)
else (index+1, maxSoFar, maxIndex)) (-1, System.Int32.MinValue, -1)
maxIndex
let findIndexOfMaxValueSimpleSeq list = list
|> Seq.mapi (fun i v -> i, v)
|> Seq.maxBy snd
|> fst
let findIndexOfMaxValueSimpleList list =
list
|> List.mapi (fun i x -> i, x)
|> List.maxBy snd
|> fst
[<EntryPoint>]
let main argv =
timeIt "recursiveOnly" (findIndexOfMaxValue 0 0 0)
timeIt "simpleSeq" findIndexOfMaxValueSimpleSeq
timeIt "simpleList" findIndexOfMaxValueSimpleList
0
The results I get are:
recursiveOnly, elapsed 356ms, result 3562
foldAlgorithm, elapsed 1602ms, result 3562
simpleSeq, elapsed 4504ms, result 3562
simpleList, elapsed 4395ms, result 3562
I have these functions in my helper library:
module List =
let maxIndexBy projection list =
list
|> List.mapi (fun i x -> i, projection x)
|> List.maxBy snd
|> fst
let maxIndex list = maxIndexBy id list
Returns the index of the max element, optionally using a given projection function. You can write the same functions for the Seq and Array modules easily by replacing the "List" part and renaming the arguments.
I am seeking help, mainly because I am very new to F# environment. I need to use F# stream to generate an infinite stream of Armstrong Numbers. Can any one help with this one. I have done some mambo jumbo but I have no clue where I'm going.
type 'a stream = | Cons of 'a * (unit -> 'a stream)
let rec take n (Cons(x, xsf)) =
if n = 0 then []
else x :: take (n-1) (xsf());;
//to test if two integers are equal
let test x y =
match (x,y) with
| (x,y) when x < y -> false
| (x,y) when x > y -> false
| _ -> true
//to check for armstrong number
let check n =
let mutable m = n
let mutable r = 0
let mutable s = 0
while m <> 0 do
r <- m%10
s <- s+r*r*r
m <- m/10
if (test n s) then true else false
let rec armstrong n =
Cons (n, fun () -> if check (n+1) then armstrong (n+1) else armstrong (n+2))
let pos = armstrong 0
take 5 pos
To be honest your code seems a bit like a mess.
The most basic version I could think of is this:
let isArmstrong (a,b,c) =
a*a*a + b*b*b + c*c*c = (a*100+b*10+c)
let armstrongs =
seq {
for a in [0..9] do
for b in [0..9] do
for c in [0..9] do
if isArmstrong (a,b,c) then yield (a*100+b*10+c)
}
of course assuming a armstrong number is a 3-digit number where the sum of the cubes of the digits is the number itself
this will yield you:
> Seq.toList armstrongs;;
val it : int list = [0; 1; 153; 370; 371; 407]
but it should be easy to add a wider range or remove the one-digit numbers (think about it).
general case
the problem seems so interesting that I choose to implement the general case (see here) too:
let numbers =
let rec create n =
if n = 0 then [(0,[])] else
[
for x in [0..9] do
for (_,xs) in create (n-1) do
yield (n, x::xs)
]
Seq.initInfinite create |> Seq.concat
let toNumber (ds : int list) =
ds |> List.fold (fun s d -> s*10I + bigint d) 0I
let armstrong (m : int, ds : int list) =
ds |> List.map (fun d -> bigint d ** m) |> List.sum
let leadingZero =
function
| 0::_ -> true
| _ -> false
let isArmstrong (m : int, ds : int list) =
if leadingZero ds then false else
let left = armstrong (m, ds)
let right = toNumber ds
left = right
let armstrongs =
numbers
|> Seq.filter isArmstrong
|> Seq.map (snd >> toNumber)
but the numbers get really sparse quickly and using this will soon get you out-of-memory but the
first 20 are:
> Seq.take 20 armstrongs |> Seq.map string |> Seq.toList;;
val it : string list =
["0"; "1"; "2"; "3"; "4"; "5"; "6"; "7"; "8"; "9"; "153"; "370"; "371";
"407"; "1634"; "8208"; "9474"; "54748"; "92727"; "93084"]
remark/disclaimer
this is the most basic version - you can get big speed/performance if you just enumerate all numbers and use basic math to get and exponentiate the digits ;) ... sure you can figure it out
I'm new to F# and I'm curious if this can still be optimized further. I am not particularly sure if I've done this correctly as well. I'm curious particularly on the last line as it looks really long and hideous.
I've searched over google, but only Roman Numeral to Number solutions only show up, so I'm having a hard time comparing.
type RomanDigit = I | IV | V | IX
let rec romanNumeral number =
let values = [ 9; 5; 4; 1 ]
let capture number values =
values
|> Seq.find ( fun x -> number >= x )
let toRomanDigit x =
match x with
| 9 -> IX
| 5 -> V
| 4 -> IV
| 1 -> I
match number with
| 0 -> []
| int -> Seq.toList ( Seq.concat [ [ toRomanDigit ( capture number values ) ]; romanNumeral ( number - ( capture number values ) ) ] )
Thanks for anyone who can help with this problem.
A slightly shorter way of recursively finding the largest digit representation that can be subtracted from the value (using List.find):
let units =
[1000, "M"
900, "CM"
500, "D"
400, "CD"
100, "C"
90, "XC"
50, "L"
40, "XL"
10, "X"
9, "IX"
5, "V"
4, "IV"
1, "I"]
let rec toRomanNumeral = function
| 0 -> ""
| n ->
let x, s = units |> List.find (fun (x,s) -> x <= n)
s + toRomanNumeral (n-x)
If I had to use a Discriminated Union to represent the roman letters I would not include IV and IX.
type RomanDigit = I|V|X
let numberToRoman n =
let (r, diff) =
if n > 8 then [X], n - 10
elif n > 3 then [V], n - 5
else [], n
if diff < 0 then I::r
else r # (List.replicate diff I)
Then, based in this solution you can go further and extend it to all numbers.
Here's my first attempt, using fold and partial application:
type RomanDigit = I|V|X|L|C|D|M
let numberToRoman n i v x =
let (r, diff) =
if n > 8 then [x], n - 10
elif n > 3 then [v], n - 5
else [], n
if diff < 0 then i::r
else r # (List.replicate diff i)
let allDigits (n:int) =
let (_, f) =
[(I,V); (X,L); (C,D)]
|> List.fold (fun (n, f) (i, v) ->
(n / 10, fun x -> (numberToRoman (n % 10) i v x) # f i)) (n, (fun _ -> []))
f M
Here's a tail-recursive version of #Philip Trelford's answer:
let toRomanNumeral n =
let rec iter acc n =
match n with
| 0 -> acc
| n ->
let x, s = units |> List.find (fun (x, _) -> x <= n)
iter (acc + s) (n-x)
iter "" n
My code (below) falls over with a stack overflow exception. Im assuming F# isnt like haskell and dosent play well with recursive lists. Whats the correct way of dealing with recursive lists like this in F# ? Should i pass it an int so it has a determined size?
let rec collatz num =
match num with
|x when x % 2 = 0 ->num :: collatz (x/2)
|x -> num :: collatz ((x * 3) + 1)
let smallList = collatz(4) |> Seq.take(4)
For an infinite list like this, you want to return a sequence. Sequences are lazy; lists are not.
let rec collatz num =
seq {
yield num
match num with
| x when x % 2 = 0 -> yield! collatz (x/2)
| x -> yield! collatz ((x * 3) + 1)
}
let smallList =
collatz 4
|> Seq.take 4
|> Seq.toList //[4; 2; 1; 4]
let collatz num =
let next x = if x % 2 = 0 then x / 2 else x * 3 + 1
(num, next num)
|>Seq.unfold (fun (n, x) -> Some (n, (x, next x)))