F# Finding the Missing element between 2 arrays/lists - arrays

`So, I am very new to F#. I hope the issue is simple. I have been doing research and looking around. I have an "Incomplete structured construct at or before this point in expression" error. I feel like it might be something simple or I am way off.
The objective is:
There is an array of non negative integers. A second array is
formed by shuffling the elements of the first
array and deleting a random element. Given these two arrays, find which element is missing in the second
array. Linear searching is not allowed.
let FindMiss list =
match list with
| [] ->
[]
|firstElem::otherElements ->
let rand = new Random
let shuffle (arr : 'a array) =
let array = Array.copy arr
let n = array.Length
for x in 1..n do
let i = n-x
let j = rand.Next(i+1)
let tmp = array.[i]
array.[i] <- array.[j]
array.[j] <- tmp
array
return array
array.[rand].delete
|array::list ->
let d=collections.defaultdict(int)
for num in list do
d[num] +=1
for num in array1 do
if d[num]==0 then return num
else d[num]-=1
printfn "The missing Number is: %A" (FindMiss[4;2;1;7;5;6;3;2])

The task is to reimplement List.except?
If not, just use that 'except' then:
[1;2;3] |> List.except [1;2]
Or was the task "random removal of element in list"? Then this is "the answer": https://stackoverflow.com/a/2889972/5514938

For a start, for more readability, you can take the shuffling and deleting a random element in a separate function. For arrays, they may look like this:
let Shuffle arr =
let rand = System.Random()
arr |> Array.sortBy(fun _ -> rand.Next())
let RemoveRandom arr =
let rand = System.Random()
let lng = arr |> Array.length
let index = rand.Next lng
[|0..lng - 1 |]
|> Array.choose(fun x -> if x = index then None else Some(arr.[x]))
|> Shuffle
Further define the search function:
let FindMiss arr1 arr2 =
let sum1 = arr1 |> Array.sum
let sum2 = arr2 |> Array.sum
sum1 - sum2
Example:
let first = [| 4;2;1;7;5;6;3;2 |]
first |> printfn "%A"
let second = first |> RemoveRandom
second |> printfn "%A"
FindMiss first second |> printfn "Missing value is %i"
Print:
[|4; 2; 1; 7; 5; 6; 3; 2|]
[|2; 2; 3; 7; 1; 5; 6|]
Missing value is 4
Link:
https://dotnetfiddle.net/g6wKUX

Related

Assign variable to array element where variable and array can be modified independently in ocaml

Here is the problem I can't get around, I'm working in ocaml to copy the elements of an array to a new array. I want to be able to modify these arrays independently from each other, but no matter what I try, a change to one array is reflected in the other array as well.
Here is a simplified example:
type sampleType = { a : int; b : int array };;
let x = {a = 5; b = [|1, 2, 3|] };;
let y = x.b;;
Array.set y 1 6;;
After running these commands I want:
y - : int array = [|1; 6; 3|]
x - : sampleType = {a = 5; b = [|1; 2; 3|]}
Instead x is being changed along with y, and
x - : sampleType = {a = 5; b = [|1; 6; 3|]}
Any solutions to this problem?
As you see from your experiments, this code:
let y = x.b
makes y refer to the very same array as x.b. It doesn't create an independent array. To create an independent array, you need to copy:
let y = Array.copy x.b
I was specifically using 3d arrays, realized I had to apply Array.copy at the lowest level of the 3d array, rather than at the top level.
let arr = Array.init 3 (fun _ -> Array.init 3 (fun _ -> (Array.init 3 (fun _ -> {faces = [|0;1;2;3;4|]}))));;
let drr = Array.init 3 (fun i -> Array.init 3 (fun j -> Array.copy arr.(i).(j)));;
This gave me the result I needed.

f# Finding the difference between 2 obj[]lists

I have 2 obj[]lists list1 and list2. List1 has a length of 8 and list2 has a length of 10. There are arrays in list1 that only exist in list1. That also goes the same for list2. But there are array that exist in both. I'm wondering how to get the arrays that exist in list1. At the moment when I run my code I get a list of the arrays that exist in both lists, but it's missing the data unique to list1. I'm wondering how to get that unique list1 data. Any suggestions?
let getProdOnly (index:int)(list1:obj[]list)(list2:obj[]list) =
let mutable list3 = list.Empty
for i = 0 to list1.Length-1 do
for j = 0 to list2.Length-1 do
if list1.Item(i).GetValue(index).Equals(list2.Item(j).GetValue(index)) then
System.Diagnostics.Debug.WriteLine("Exists in List 1 and 2")
else
list3 <- list1.Item(i)
Something like this:
let ar1 = [|1;2;3|]
let ar2 = [|2;3;4|]
let s1 = ar1 |> Set.ofArray
let s2 = ar2 |> Set.ofArray
Set.difference s1 s2
//val it : Set<int> = set [1]
There are also a bunch of Array related functions, like compareWith, distinct, exists if you want to work with Arrays directly.
But as was pointed out in previous answers, this type of imperative code is not very idiomatic. Try to avoid mutable variables, try to avoid loops. It could probably rewritten with Array.map for example.
If you want the elements unique to one list, this is the easiest way to do it in F# 4.0:
list1
|> List.except list2
which will remove all the elements of list2 from list1. Note that except also calls a distinct, so you might need to watch out for that.
First I took your code with minor changes and added some printf debuging to see what is does.
let getProdOnly2 (index:int)(list1:obj[] list)(list2:obj[] list) =
let mutable list3 : obj[] list= list.Empty
for i = 0 to list1.Length-1 do
for j = 0 to list2.Length-1 do
if list1.[i].[index] = list2.[j].[index] then
printfn "equal"
System.Diagnostics.Debug.WriteLine("Exists in List 1 and 2")
list3
else
printfn "add %A %A" (list1.Item(i)) (list2.Item(j))
list3 <- list1.Item(i) :: list3
list3
list3
And it does adding an element each time it finds an element not equal the current element.
So my attempt is to take the list1 and just ceep or better filter the elements that are not part of list2.
let getProdOnly3 (index:int)(list1:obj[] list)(list2:obj[] list) =
list1
|> List.filter (fun el1 ->
list2
|> List.fold (fun acc el2 -> acc && (el2<>el1)) true )
I tested the code with the following lists
let list1 = [ [| 1;2;3;4|]
[| 1;2;3;4|]
[| 2;3;4|]
[| 3;4;5|] ] |> List.map (fun a -> a |> Array.map (fun e -> box e))
let list2 = [ [| 2;3;4|]
[| 3;4;5|] ] |> List.map (fun a -> a |> Array.map (fun e -> box e))
In difference to s952163 my result will have double entries if list1 has double entries, do not know if that is wanted or unwanted beahyuvier.

In-array comparison in F#

Let's say that I want to do some in-array comparison in F#, e.g. determine whether a given integer array arr contains integers in strictly increasing order. I would do it like this:
let arri =
arr
|> Array.mapi (fun i e -> i, e)
let isArrStrictlyIncreasing =
arri
|> Array.tryFind (fun e ->
if fst e = arri.Length - 1 then
false
else
snd e >= snd arri.[1 + fst e])
|> Option.isNone
However, I am wondering if there is a more concise, "functional" way of making such in-array comparisons without the use of Array.mapi and if-else?
One simple way:
let isincr arr =
arr
|> Array.fold (fun (a,b) (c) -> ((b<c && a)),c) (true,System.Int32.MinValue)
|> fst
Couldn't you just do the following?
let expected = [| candidate.[0] .. candidate.[0] + candidate.Length - 1 |]
candidate = expected
This simply builds the array you'd expect, and uses F#'s Structural Equality to compare the two arrays.
A more general alternative might be this:
let isOrdered arr = arr |> Array.sort = arr
let hasDistinctMembers (arr : 'a array) =
let distinct = arr |> Seq.distinct |> Seq.toArray
distinct.Length = arr.Length
let isStrictlyIncreasing arr = arr |> isOrdered && arr |> hasDistinctMembers
Usage:
> isStrictlyIncreasing [| 7; 11; 8 |];;
val it : bool = false
> isStrictlyIncreasing [| 7..33 |];;
val it : bool = true
> isStrictlyIncreasing [| 7; 8; 11 |];;
val it : bool = true
> isStrictlyIncreasing [| 7; 7; 8; 11 |];;
val it : bool = false

How to Generate A Specific Number of Random Indices for Array Element Removal F#

So sCount is the number of elements in the source array, iCount is the number of elements I want to remove.
let indices = Array.init iCount (fun _ -> rng.Next sCount) |> Seq.distinct |> Seq.toArray |> Array.sort
The problem with the method above is that I need to specifically remove iCount indices, and this doesn't guarantee that.
I've tried stuff like
while indices.Count < iCount do
let x = rng.Next sCount
if not (indices.Contains x) then
indices <- indices.Add x
And a few other similar things...
Every way I've tried has been extremely slow though - I'm dealing with source arrays of sizes up to 20 million elements.
What you're doing should be fine if you need a set of indices of negligible size compared to the array. Otherwise, consider doing a variation of a Knuth-Fisher-Yates shuffle to get the first i elements in a random permutation of 1 .. n:
let rndSubset i n =
let arr = Array.zeroCreate i
arr.[0] <- 0
for j in 1 .. n-1 do
let ind = rnd.Next(j+1)
if j < i then arr.[j] <- arr.[ind]
if ind < i then arr.[ind] <- j
arr
I won't give you F# code for this (because I don't know F#...), but I'll describe the approach/algorithm that you should use.
Basically, what you want to do is pick n random elements of a given list list. This can be done in pseudocode:
chosen = []
n times:
index = rng.upto(list.length)
elem = list.at(index)
list.remove-at(index)
chosen.add(elem)
Your list variable should be populated with all possible indices in the source list, and then when you pick n random values from that list of indices, you have random, distinct indices that you can do whatever you want with, including printing values, removing values, knocking yourself out with values, etc...
is iCount closer to the size of the array or closer to 0? That will change the algorithm which you will use.
If closer to 0, then keep track of the previously generated numbers and check if additional numbers have already been generated.
If closer to the size of the array then use the method as described by #feralin
let getRandomNumbers =
let rand = Random()
fun max count ->
Seq.initInfinite (fun _ -> rand.Next(max))
|> Seq.distinct
|> Seq.take count
let indices = Array.init 100 id
let numToRemove = 10
let indicesToRemove = getRandomNumbers (indices.Length - 1) numToRemove |> Seq.toList
> val indicesToRemove : int list = [32; 38; 26; 51; 91; 43; 92; 94; 18; 35]

Array initialization in F#

How do I create and initialize an array in F# based on a given record type?
Suppose I want to create an Array of 100 record1 records.
e.g.
type record1 = {
value1:string;
value2:string
}
let myArray = Array.init 100 ?
But it appears the Array.init does not allow for this, is there a way to do this?
Edited to add:
Of course I could do something like this:
let myArray = [|for i in 0..99 -> { value1="x"; value2="y" }|]
You can use also Array.create, which creates an array of a given size, with all its elements initialized to a defined value:
let myArray = Array.create 100 {value1="x"; value2="y"}
Give a look to this list of array operations.
This should do what you need. Hope it helps.
type record1 = {
value1:string;
value2:string
}
let myArray = Array.init 100 (fun x -> {value1 = "x"; value2 = "y"})
or using Generics
let myArray = Array.init<record1> 100 (fun x -> {value1 = "x"; value2 = "y"})
Or you can create a sequence, instead of creating an array, like this:
// nItems, given n and an item, returns a sequence of item repeated n times
let rec nItems n item =
seq {
match n with
| n when n > 0 -> yield item; yield! nItems (n - 1) item
| _ -> ()
}
type Fnord =
{ foo: int }
printfn "%A" (nItems 99999999 {foo = 3})
// seq [{foo = 3;}; {foo = 3;}; {foo = 3;}; {foo = 3;}; ...]
printfn "%A" (nItems 3 3 |> Seq.toArray)
[|3; 3; 3|]
The nice thing about the sequence, instead of an array, is that it creates items as you need them, rather than all at once. And it's simple to go back and forth between sequences and arrays if you need to.

Resources