recursive function for 2D list - f#

I'm very new to f# so please forgive my ignorance. I have a 2D list of int. I'm trying to make a function that will return another 2D list which will contain only the lowest tail items. Something like this:
[[2, 3]
[2, 4]
[2, 5] [[2, 3]
[3, 8] => [3, 2]
[3, 6] [4, 1]]
[3, 2]
[4, 1]]
I can find min value of 1D list with
let findMin items =
match items with
| [] -> ()
| head :: tail ->
let rec recMin minSoFar items =
match items with
| [] -> minSoFar
| head :: tail ->
if head < minSoFar then
recMin head tail
else
recMin minSoFar tail
recMin head tail
which I copied from this answer. Any help would be appreciated.

You are talking about 2D lists, but your sample input is actually a list of lists of tuples (where each list contains just a single tuple value). I assume this is a typo and you wanted to write ; rather than ; and create an actual 2D list:
let input =
[ [2; 3]
[2; 4]
[2; 5]
[3; 8]
[3; 6]
[3; 2]
[4; 1] ]
Now, the three items that you want to get as the result seem to be the three sub-lists with the smallest last element in the list. The easiest way for obtaining those would be to sort the list of lists by the last element of sub-lists and then take top 3:
input
|> List.sortBy List.last
|> List.take 3
This returns the three sub-lists you want, but not in the original order. If you wanted them in the original order, then you could first find the third smallest last element and then use that to filter the original list:
let last =
input
|> List.map List.last
|> List.sort
|> List.item 2
input
|> List.filter (fun l -> List.last l <= last)
Note that my code does not correctly handle cases such as input smaller than 3 or empty lists, but it should give you an idea about one way of solving this problem.

Related

F# removing the first occurrence of an element in a list

I want to remove the first occurrence of a given element in a list that has possible duplicates.
For example, a list with [1; 6; 1]. I only want to remove 1 once and returns the list [6;1]. My current implementation:
let rec remove l x =
match l with
| [] -> []
| h::t when h = x -> t
| h::t -> h::(remove l h)
this works only for lists that the number I am trying to remove is the first element. For a list like [6; 7; 6] if I wanted to remove the number 7 and return [6; 6]. It does not traverse the list and remove 7 with my current implementation. What can I do to traverse the entire list and remove only the first occurrence of an element?
The issue you have is in the last line of your code
let rec remove l x =
match l with
| [] -> []
| h::t when h = x -> t
| h::t -> h::(remove l h)
^^^^^^^^^^^
You want to keep the head h and process the tail t but the code do not do this, referring to h and l, instead of t and x.
The type signature of remove is correctly inferred to 'a list-> 'a -> 'a list but the wrong second argument is used in the last match branch. It is using h rather than x as the element to remove parameter.
The first argument is also incorrect, since referring to l does not change through each recursion. It needs to refer to the latest tail t.
So the last match branch should read:
| h::t -> h::(remove t x)
Here is the full corrected code;
let rec remove l x =
match l with
| [] -> []
| h::t when h = x -> t
| h::t -> h::(remove t x)
I ended up writing the same code you did and it seems to work just fine. I reordered the parameters for better piping. I could also work to make this tail-recursive.
let rec removeFirst elem xs =
match xs with
| [] -> []
| h :: t when elem = h -> t
| h :: t -> h :: (removeFirst elem t)
> removeFirst 2 [1;2;2;1];;
val it: int list = [1; 2; 1]
Tail-call optimized version
let removeFirst elem list =
let rec loop head tail =
match tail with
| [] -> list
| x :: xs when x = elem -> (List.rev head) # xs
| x :: xs -> loop (x::head) xs
loop [] list
removeFirst 1 [1; 2; 3] |> printfn "%A" // [2; 3]
removeFirst 2 [1; 2; 3] |> printfn "%A" // [1; 3]
removeFirst 3 [1; 2; 3] |> printfn "%A" // [1; 2]
removeFirst 4 [1; 2; 3] |> printfn "%A" // [1; 2; 3]
How it works:
We're traversing list keeping visited elements in head and unvisited in tail. Take first element from tail and see if it's equal to elem we're searching for. If element is found, reverse head and attach to tail without removed element. If element is not found, attach current to head and continue. If we've reached end of list and element isn't found, then return list without modifications.
Example:
Given list of [1; 2; 3; 4; 5] and element 3 iterations will look like this:
head
tail
x
xs
[]
[1; 2; 3; 4; 5]
1
[2; 3; 4; 5]
[1]
[2; 3; 4; 5]
2
[3; 4; 5]
[2; 1]
[3; 4; 5]
3
[4; 5]
At last iteration element is found and all that's remains is to build list: reverse of [2; 1] is [1; 2], attach to [4; 5] and get [1; 2; 4; 5].
Note: head is kept in reverse to improve performance of building it from O(n2) to O(n). Combining head with xs in second branch can be improved from O(head.length*2) to O(head.length) by avoiding usage of rev with # and building result list manually

How to convert a 2d array to a list of lists in F#

I have a 2d array of floats:
let scores = Array2D.init<float> width height (fun _ _ -> 0.)
and I would like to convert it to a list of lists where I have a list of rows and each of these row is a list of column values.
for example:
[
1, 2, 3
4, 5, 6
7, 8, 9
]
would become:
[
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
]
I found this question: F# convert Array2 into a list
but it converts the 2d array into a list, I'm trying to find how to convert it to a list of list.
I could iterate through the elements and build the list, but I'm sure there has to be a better way.
This is made quite readable by F#'s slice operators (now in C# 8 too!).
To slice a multi-dimensional array you can use .[range,range].
For example, .[*,n] for the n-th column, and .[n,*] for the n-th row.
The final piece we need is the height of the array, which is Dimension 0, given by
array.GetLength 0
Now it becomes trivial to slice up the 2D array, using a list comprehension.
[
let height = arr.GetLength 0
for row in 0..height-1 do
yield arr.[row,*] |> List.ofArray
]
For non-zero indexed arrays, as suggested by Henrik Hansen, it is preferable to use:
[
for i in arr.GetLowerBound(0)..arr.GetUpperBound(0)
do yield arr.[i,*] |> List.ofArray
]
Test
let counter = ref 0
//generate the test array
let arr = Array2D.init (3) (3) (fun _ _ -> Interlocked.Increment(counter))
arr |> printfn "%A"
let lists =
[
let height = arr.GetLength 0
for row in 0..height - 1 do
yield arr.[row,*] |> List.ofArray
]
lists |> printfn "%A"
Output:
[[1; 2; 3]
[4; 5; 6]
[7; 8; 9]]
[[1; 2; 3]; [4; 5; 6]; [7; 8; 9]]
Another way building on Asti's ideas:
module Array2D =
let toListOfLists (arr2d: 'a [,]) = [ yield! [arr2d.GetLowerBound(0)..arr2d.GetUpperBound(0)] |> List.map (fun i -> arr2d.[i,*] |> List.ofArray) ]
let base002D = Array2D.init 5 5 (fun x y -> (x, y))
let base152D = Array2D.initBased 1 5 5 5 (fun x y -> (x, y))
printfn "%A" (base002D |> Array2D.toListOfLists)
printfn "%A" (base152D |> Array2D.toListOfLists)
It works with different bases.

Implement insert in f# elements into set returning the new set with elements?

I'm trying to write a function in F# that inserts y into S, where y and S are sets of elements, in the returning set S elements should be inserted in order using <, if x exists in S then S is returned unchanged. I hope this is much clear. I have implemented the function as follows
let rec insert x S =
match S with
|[] -> x
|e::rest -> e::(insert x rest)
but it does not give me expected output. For example if
S = [2; 3]
x = [3; 4]
the output should be
[2; 3; 4]
But I'm getting
[2; 3; 3; 4]

How to use whole list function argument in Erlang

I can understand most of the [H|T] examples I read in the docs. I usually means that I want to use either the H or the T part of the list. What if I want to use the whole list instead. Sample code:
-module(module_variable).
-export([main/0, list_suffix/1]).
variable() -> [1, 2, 3, 4, 5].
list_suffix([_H|T]) ->
lists:suffix(variable, T).
main() ->
io:fwrite("~p~n", [list_suffix([4, 5])]).
The error I get is:
6> module_variable:list_suffix([1,[4, 5]]).
** exception error: bad argument
in function length/1
called as length(variable)
in call from lists:suffix/2 (lists.erl, line 205)
Help is appreciated.
You can use multiple values from the front of the list. You cannot skip an arbitrary number of values in the middle. Since in your code you don't know how many elements from the head you want to match ahead of time, pattern matching can't do this for you.
Some examples:
Setup:
1> A = [1, 2, 3, 4, 5].
[1,2,3,4,5]
Matches first 2 elements of list
2> [1, 2 | _ ] = A.
[1,2,3,4,5]
% Can pattern match to extract values
3> [B, C | _ ] = A.
[1,2,3,4,5]
4> B.
1
5> C.
2
Can match some constant values and also assign
6> [1, 2, D | _ ] = A.
[1,2,3,4,5]
Can match whole list
7> [1, 2, 3, 4, 5] = A.
[1,2,3,4,5]
% Can't skip over elements in the middle
8> [1, 2| [4, 5]] = A.
** exception error: no match of right hand side value [1,2,3,4,5]
% This works, though not useful most of the time:
9> [1, 2, 3 | [4, 5]] = A.
[1,2,3,4,5]
% Can assign every element
10> [B, C, D, E, F] = A.
[1,2,3,4,5]
11> E.
4
12> F.
5
% If you don't use a pipe, the length has to match exactly
13> [B, C, D, E] = A.
** exception error: no match of right hand side value [1,2,3,4,5]

Erlang, Function which return the lenghts of the lists?

I'm trying to implement a function
llen(ListOfLists)
which returns a list containing the lengths of the lists in ListOfLists. Function should use lists:map/2.
Example:
1> funs:llen([[1, 2, 3], [], [4, 5]]).
[3, 0, 2]
I know how to calculate length for one list:
list([]) -> 0;
list([_|T]) -> 1+list(T).
but i don't know how to do this for multiple lists using funs and lists.
lists:map/2 is a higher order function that applies a function for each element of a list. erlang:length/1 is a function that returns the length of a list.
Apply erlang:length/1 on each element of your list using lists:map/2:
lists:map(fun erlang:length/1, [[1, 2, 3], [], [4, 5]])
And when you get to list comprehensions:
53> L = [[1, 2, 3], [], [4, 5]].
[[1,2,3],[],[4,5]]
54> [length(X) || X <- L].
[3,0,2]
A list comprehension is like a for-loop in other languages, and this one reads like:
length(X) for X in L
length(X) || X <- L
The outer [ ] serves to gather up all the results into a list.

Resources