Find unique array of tuples - collections

I have 4 arrays of different data. For the first array of string, I want to delete the duplicate element and get the results of array of unique tuples with 4 elements.
For example, let's say the arrays are:
let dupA1 = [| "A"; "B"; "C"; "D"; "A" |]
let dupA2 = [| 1; 2; 3; 4; 1 |]
let dupA3 = [| 1.0M; 2.0M; 3.0M; 4.0M; 1.0M |]
let dupA4 = [| 1L; 2L; 3L; 4L; 1L |]
I want the result to be:
let uniqueArray = [| ("A", 1, 1.0M, 1L); ("B", 2, 2.0M, 2L); ("C", 3, 3.0M, 3L); ("D",4, 4.0M, 4L) |]

You will first need to write a zip4 function which will zip the arrays:
// the function assumes the 4 arrays are of the same length
let zip4 a (b : _ []) (c : _ []) (d : _ []) =
Array.init (Array.length a) (fun i -> a.[i], b.[i], c.[i], d.[i])
Then a distinct function for arrays, using Seq.distinct:
let distinct s = Seq.distinct s |> Array.ofSeq
And the result would be:
> zip4 dupA1 dupA2 dupA3 dupA4 |> distinct;;
val it : (string * int * decimal * int64) [] =
[|("A", 1, 1.0M, 1L); ("B", 2, 2.0M, 2L); ("C", 3, 3.0M, 3L);
("D", 4, 4.0M, 4L)|]

let zip4 s1 s2 s3 s4 =
Seq.map2 (fun (a,b)(c,d) ->a,b,c,d) (Seq.zip s1 s2)(Seq.zip s3 s4)
let uniqueArray = zip4 dupA1 dupA2 dupA3 dupA4 |> Seq.distinct |> Seq.toArray

Related

Flatten a Map<Vec<u8>, Vec<u8>> into a Vec<u8> and then return it to a Map<Vec<u8>, Vec<u8>>

I've have data in a HashMap<Vec<u8>, Vec<u8>> and I want to write that data to a file as a byte buffer (a single Vec<u8>) and then read it back from the file and reconstruct the HashMap structure.
Is there an established algorithm for flattening and recovering maps like this? I could write metadata into the file to distinguish where the data partitions etc. I can't use structured serialization because of the nature of this project — I am encrypting the data and the file.
You may store this with the following format:
value1_len | value1_bytes | key1_len | key1_bytes | value2_len | value2_bytes | key2_len | key2_bytes | ...
what can be fairly easily done with the standard library (playground):
use std::collections::HashMap;
use std::convert::TryInto;
fn serialize(map: &HashMap<Vec<u8>, Vec<u8>>) -> Vec<u8> {
map.iter().fold(Vec::new(), |mut acc, (k, v)| {
acc.extend(&k.len().to_le_bytes());
acc.extend(k.as_slice());
acc.extend(&v.len().to_le_bytes());
acc.extend(v.as_slice());
acc
})
}
fn read_vec(input: &mut &[u8]) -> Vec<u8> {
let (len, rest) = input.split_at(std::mem::size_of::<usize>());
let len = usize::from_le_bytes(len.try_into().unwrap());
let (v, rest) = rest.split_at(len);
*input = rest;
v.to_vec()
}
fn deserialize(bytes: &Vec<u8>) -> HashMap<Vec<u8>, Vec<u8>> {
let mut map = HashMap::new();
let mut left = &bytes[..];
while left.len() > 0 {
let k = read_vec(&mut left);
let v = read_vec(&mut left);
map.insert(k, v);
}
map
}
fn main() {
let mut map = HashMap::new();
map.insert(vec![1, 2, 3], vec![4, 5, 6]);
map.insert(vec![4, 5, 6], vec![1, 2, 3]);
map.insert(vec![1, 5, 3], vec![4, 2, 6]);
let array = serialize(&map);
let recovered_map = deserialize(&array);
assert_eq!(map, recovered_map);
}

F#: Attributes on discriminated union fields?

I can do this:
type AttrAttribute () =
inherit Attribute ()
type MyDU =
| [<Attr>]A of bool
| [<Attr>]B of int * string
| [<Attr>]C of byte * char * int64
... but is there any way to do this?
type MyDU =
| A of [<Attr>]bool
| B of int * [<Attr>]string
| C of [<Attr>]byte * char * [<Attr>]int64
Apparently, the case values are just fields (e.g. let v = B (13, "oops") in (Microsoft.FSharp.Reflection.FSharpValue.GetUnionFields (v, v.GetType ()) |> fst).GetFields ()), so I'm hoping this is doable, somehow.
This is quite contrived:
type A_ = { [<Attr>] Item1 : int }
type B_ = { [<Attr>] Item1 : int; [<Attr>] Item2 : string }
type MyDU =
| A of A_
| B of B_
And
let v = A({Item1 = 1})
let record = ((FSharpValue.GetUnionFields (v, v.GetType ()) |> fst).GetFields ()) |> Array.head
let attrs = record.PropertyType.GetProperties() |> Array.collect(fun p -> p.GetCustomAttributes(false))

Recursively unpack list into elements

I have a list and would like to return each element from it individually. Basically like popping from a stack. For example:
let rnd = new System.Random()
let rnds = List.init 10 (fun _ -> rnd.Next(100))
List.iter (fun x -> printfn "%A"x ) rnds
However instead of iterating, I would actually like to return each integer one after the other until the list is empty. So basically something along the lines of:
List.head(rnds)
List.head(List.tail(rnds))
List.head(List.tail(List.tail(rnds)))
List.head(List.tail(List.tail(List.tail(List.tail(rnds)))))
Unfortunately my attempts at a recursive solution or even better something using fold or scan were unsuccessful. For example this just returns the list (same as map).
let pop3 (rnds:int list) =
let rec pop3' rnds acc =
match rnds with
| head :: tail -> List.tail(tail)
| [] -> acc
pop3' [] rnds
Would uncons do what you need?
let uncons = function h::t -> Some (h, t) | [] -> None
You can use it to 'pop' the head of a list:
> rnds |> uncons;;
val it : (int * int list) option =
Some (66, [17; 93; 33; 17; 21; 1; 49; 5; 96])
You can repeat this:
> rnds |> uncons |> Option.bind (snd >> uncons);;
val it : (int * int list) option = Some (17, [93; 33; 17; 21; 1; 49; 5; 96])
> rnds |> uncons |> Option.bind (snd >> uncons) |> Option.bind (snd >> uncons);;
val it : (int * int list) option = Some (93, [33; 17; 21; 1; 49; 5; 96])
This seems like a good oppurtunity for a class
type unpacker(l) =
let mutable li = l
member x.get() =
match li with
|h::t -> li<-t;h
|_ -> failwith "nothing left to return"

F# adding polynomials recursively

I'm trying to write a function in F# that adds polynomials recursively. My polynomials can be represented as a list of tuples.
For example, 2x^4 + 3x^2 + x + 5 is equal to [(2.0,4);(3.0,2);(1.0,1);(5.0,0)]
All polynomials are properly structured (no repeated terms with the same degree, no terms with zero coefficients unless it is the zero polynomial, terms sorted by decreasing exponent no empty input list).
I'm having trouble doing this. Here is my code
type term = float * int
type poly = term list
let rec atp(t:term,p:poly):poly =
match p with
| [] -> []
| (a, b) :: tail -> if snd t = b then (fst t + a, b) :: [] elif snd t > b then t :: [] else ([]) :: atp(t, tail)
(* val atp : t:term * p:poly -> poly *)
let rec addpolys(p1:poly,p2:poly):poly =
match p1 with
| [] -> []
| (a,b) :: tail -> atp((a,b), p2) # addpolys(tail, p2)
I have two polynomials
val p2 : poly = [(4.5, 7); (3.0, 4); (10.5, 3); (2.25, 2)]
val p1 : poly = [(3.0, 5); (2.0, 2); (7.0, 1); (1.5, 0)]
and when I call the function, my result is
val p4 : poly =
[(4.5, 7); (3.0, 5); (3.0, 4); (3.0, 5); (10.5, 3); (3.0, 5); (4.25, 2)]
When the correct answer is
[(4.5, 7); (3.0, 5); (3.0, 4); (10.5, 3); (4.25, 2); (7.0, 1); (1.5, 0)]
Unfortunately your code does not compile therefore it is difficult for me to understand your intentions. But I've got an own implementation for your problem. Maybe it will help you:
// addpoly: (float * 'a) list -> (float * 'a) list -> (float * 'a) list
let rec addpoly p1 p2 =
match (p1, p2) with
| [], p2 -> p2
| p1, [] -> p1
| (a1, n1)::p1s, (a2, n2)::p2s ->
if n1 < n2 then (a2, n2) :: addpoly p1 p2s
elif n1 > n2 then (a1, n1) :: addpoly p1s p2
else (a1+a2, n1) :: addpoly p1s p2s
let p1 = [(3.0, 5); (2.0, 2); ( 7.0, 1); (1.5, 0)]
let p2 = [(4.5, 7); (3.0, 4); (10.5, 3); (2.25, 2)]
let q = addpoly p1 p2
// val q : (float * int) list =
// [(4.5, 7); (3.0, 5); (3.0, 4); (10.5, 3); (4.25, 2); (7.0, 1); (1.5, 0)]
I would like to make a little note. When you change the representation of the
polynomials a little bit then you can simplify the implementation of your function. You can express a polynomial as a list of its coefficients.
For example when you have this polynomial
p1 = 5.0x^5 + 2.0x^2 + 7.0x
you can write it also like this
p1 = 1.5x^0 + 7.0x^1 + 2.0x^2 + 0.0x^3 + 0.0x^4 + 5.0x^5
Therefore you are able to define the polynomial with this list:
let p1 = [1.5; 7.0; 2.0; 0.0; 0.0; 5.0]
Here are two functions which operates on the representation. polyval calculates the result for a given value and polyadd adds two polynomials. There implementation are rather simple:
// p1 = 1.5x^0 + 7.0x^1 + 2.0x^2 + 0.0x^3 + 0.0x^4 + 5.0x^5
let p1 = [1.5; 7.0; 2.0; 0.0; 0.0; 5.0]
// p2 = 0.0x^0 + 0.0x^1 + 2.25x^2 + 10.5x^3 + 3.0x^4 + 0.0x^5 + 0.0x^6 + 4.5x^7
let p2 = [0.0; 0.0; 2.25; 10.5; 3.0; 0.0; 0.0; 4.5]
// polyval: float list -> float -> float
let rec polyval ps x =
match ps with
| [] -> 0.0
| p::ps -> p + x * (polyval ps x)
// polyadd: float int -> float int -> float int
let rec polyadd ps qs =
match (ps, qs) with
| [], ys -> ys
| xs, [] -> xs
| x::xs, y::ys -> (x+y)::polyadd xs ys
let v = polyval p1 2.3
// val v : float = 349.99715
let p = polyadd p1 p2
// val p : float list = [1.5; 7.0; 4.25; 10.5; 3.0; 5.0; 0.0; 4.5]
Here's a completely generic, tail-recursive implementation:
let inline addPolys xs ys =
let rec imp acc = function
| (coeffx, degx)::xt, (coeffy, degy)::yt when degx = degy ->
imp ((coeffx + coeffy, degx)::acc) (xt, yt)
| (coeffx, degx)::xt, (coeffy, degy)::yt when degx > degy ->
imp ((coeffx, degx)::acc) (xt, (coeffy, degy)::yt)
| xs, yh::yt -> imp (yh::acc) (xs, yt)
| xh::xt, [] -> imp (xh::acc) (xt, [])
| [], yh::yt -> imp (yh::acc) ([], yt)
| [], [] -> acc
imp [] (xs, ys) |> List.rev
It has the type:
xs:( ^a * 'b) list -> ys:( ^a * 'b) list -> ( ^a * 'b) list
when ^a : (static member ( + ) : ^a * ^a -> ^a) and 'b : comparison
Since float has the member +, and int supports comparison, the type float * int matches these generic constraints:
> addPolys p1 p2;;
val it : (float * int) list =
[(4.5, 7); (3.0, 5); (3.0, 4); (10.5, 3); (4.25, 2); (7.0, 1); (1.5, 0)]

Pattern match against existing variables

I have a structure of nested maps:
[<RequireQualifiedAccess>]
type NestedMap =
| Object of Map<string,NestedMap>
| Value of int
I need to prune the structure.
The purpose of the code is to maintain intact the nested structure of the maps and of the map where the key value pair is found, pruning the branches where the key value pair is not found.
Here is the test NestedMap:
let l2' = NestedMap.Object ( List.zip ["C"; "S"; "D"] [NestedMap.Value(10); NestedMap.Value(20); NestedMap.Value(30)] |> Map.ofList)
let l3 = NestedMap.Object ( List.zip ["E"; "S"; "F"] [NestedMap.Value(100); NestedMap.Value(200); NestedMap.Value(300)] |> Map.ofList)
let l2'' = NestedMap.Object ( List.zip ["G"; "H"; "I"; "S"] [NestedMap.Value(30); l3; NestedMap.Value(40); NestedMap.Value(50)] |> Map.ofList)
let l1 = NestedMap.Object ( List.zip ["Y"; "A"; "B"] [NestedMap.Value(1); l2'; l2''] |> Map.ofList)
This is my code:
let rec pruneWithKeyValue (keyvalue: string * int) (json: NestedMap) =
let condition ck cv =
let tgtKey = (fst keyvalue)
let tgtVal = (snd keyvalue)
match (ck, cv) with
| (tgtKey, NestedMap.Value(tgtVal)) ->
printfn ">>> Found match : "
printfn " ck = %s " ck
printfn " tgtKey and tgtVal == %s, %i" tgtKey tgtVal
true
| _ -> false
match json with
| NestedMap.Object nmap ->
if (nmap |> Map.exists (fun k v -> condition k v)) then
json
else
printfn "Expanding w keyvalue: (%s,%i): " (fst keyvalue) (snd keyvalue)
let expanded = nmap |> Map.map (fun k v -> pruneWithKeyValue keyvalue v)
NestedMap.Object(expanded |> Map.filter (fun k v -> v <> NestedMap.Object (Map.empty)))
| _ -> NestedMap.Object (Map.empty)
let pruned = pruneWithKeyValue ("S",20) l1
let res = (pruned = l1)
The result is not what desired:
>>> Found match :
ck = Y
tgtKey and tgtVal == Y, 1
val pruneWithKeyValue : string * int -> json:NestedMap -> NestedMap
val pruned : NestedMap =
Object
(map
[("A", Object (map [("C", Value 10); ("D", Value 30); ("S", Value 20)]));
("B",
Object
(map
[("G", Value 30);
("H",
Object
(map [("E", Value 100); ("F", Value 300); ("S", Value 200)]));
("I", Value 40); ("S", Value 50)])); ("Y", Value 1)])
val remainsTheSame : bool = true
The code says that the output data structure remains unchanged (val remainsTheSame : bool = true). Even more interestingly, somehow the keyvalue tuple that contains the key-value pair the function is searching got modified:
>>> Found match :
ck = Y
tgtKey and tgtVal == Y, 1
This is the problem. In fact, if I hardcode the keyvalue tuple:
let rec pruneWithKeyValue (keyvalue: string * int) (json: NestedMap) =
let condition ck cv =
let tgtKey = (fst keyvalue)
let tgtVal = (snd keyvalue)
match (ck, cv) with
| ("S", NestedMap.Value(20)) ->
printfn ">>> Found match : "
printfn " ck = %s " ck
printfn " tgtKey and tgtVal == %s, %i" tgtKey tgtVal
true
| _ -> false
match json with
| NestedMap.Object nmap ->
if (nmap |> Map.exists (fun k v -> condition k v)) then
json
else
printfn "Expanding w keyvalue: (%s,%i): " (fst keyvalue) (snd keyvalue)
let expanded = nmap |> Map.map (fun k v -> pruneWithKeyValue keyvalue v)
NestedMap.Object(expanded |> Map.filter (fun k v -> v <> NestedMap.Object (Map.empty)))
| _ -> NestedMap.Object (Map.empty)
let pruned = pruneWithKeyValue ("S",20) l1
let remainsTheSame = (pruned = l1)
results in (yeah) the desired result:
Expanding w keyvalue: (S,20):
>>> Found match :
ck = S
tgtKey and tgtVal == S, 20
Expanding w keyvalue: (S,20):
Expanding w keyvalue: (S,20):
val pruneWithKeyValue : string * int -> json:NestedMap -> NestedMap
val pruned : NestedMap =
Object
(map
[("A", Object (map [("C", Value 10); ("D", Value 30); ("S", Value 20)]))])
val remainsTheSame : bool = false
It may be trivial but I don't understand where and how keyvalue ends up being modified, preventing me from getting the right output with parametric key-value tuple.
You can't pattern match against existing variables, in your original code tgtKey and tgtVal will be new bindings, not related to the existing ones which will be shadowed.
So change your match:
match (ck, cv) with
| (tgtKey, NestedMap.Value(tgtVal)) ->
to:
match (ck, cv) with
| (k, NestedMap.Value v) when (k, v) = (tgtKey, tgtVal) ->
or just:
match (ck, cv) with
| x when x = (tgtKey, NestedMap.Value(tgtVal)) ->

Resources