"Problem9": Packing a list - list

I'm learning f# with no prior functional programming background - starting to make progress but been stuck on this one. Could anybody please help me understand the solution to Problem 9 of the 99 f# problems - they can be found here:[http://fssnip.net/an][1]
Basically I don't understand how the pattern matching works in the provided solution. For a start what is xss? cheers for any help!
Problem 9 : Pack consecutive duplicates of list elements into sublists.
If a list contains repeated elements they should be placed in separate sublists.
Example:
pack ['a'; 'a'; 'a'; 'a'; 'b'; 'c'; 'c'; 'a'; 'a'; 'd'; 'e'; 'e'; 'e'; 'e']
val it : char list list =
[['a'; 'a'; 'a'; 'a']; ['b']; ['c'; 'c']; ['a'; 'a']; ['d']; ['e'; 'e'; 'e'; 'e']]
Sample Solution;
let pack xs =
let collect x = function
| (y::xs)::xss when x = y -> (x::y::xs)::xss
| xss -> [x]::xss
List.foldBack collect xs []

To understand this, it is first important to understand how lists are represented in F#. An F# list is either:
an empty list written as [] or
a value (head) followed by another list (tail) written as head::tail
So if you write, for example, [ 1; 2; 3 ] you are actually constructing a list containing 1, followed by a list containing 2, (etc.) followed by an empty list. The expression is compiled to:
1::(2::(3::[]))
And you can omit the brackets and write just 1::2::3::[].
Pattern matching uses exactly the same syntax, but in the opposite direction. Instead of constructing lists, you are decomposing them. So when you have a pattern x::xs it means that you want to take the first element and assign it to a variable x and the remaining list should be assinged to a variable xs.
The pattern (x::xs)::xss is a bit more tricky, because it works on lists of lists. This means that the head of the list you match on is also a list. You could rewrite the code to the following simpler version:
let pack xs =
let collect x = function
| head::xss -> // Decompose into first element (head) and the rest (tail)
match head with
| y::xs when x = y -> (x::y::xs)::xss
| _ -> [x]::xss
| xss -> [x]::xss
List.foldBack collect xs []
Now you have some duplication in the code, but you can see that collect takes x and another parameter, matches that another parameter against head::xss (to get the head/tail) and then also decomposes the head.

(y::xs)::xss matches a (non-empty) list of lists, y and xs being the head and tail of the first sublist and xss being the tail of the outer list. xss, in the second case, matches the entire list (empty or not).
foldBack (('T -> 'State -> 'State) -> 'T list -> 'State -> 'State) threads an accumulator argument through the list, going from back to front.
collect is the "accumulating" function, which basically reads: if the state (initially an empty list) contains at least one sublist, which is also non-empty, and the current element (x) matches the head of the sublist (y), prepend x to the sublist, otherwise prepend a new sublist to the state (xss) consisting solely of x. Each sublist is a group of equal, adjacent elements.

Related

Insert number into sorted list using List.fold_right

I am trying to insert a number x into a sorted list l using Ocaml's List.fold_right and return the list with the inserted element. I have figured out a way to insert it if the element is to go at the front of the list or in the middle of the list, however I cannot figure out how to code the case where the element is larger than every element in the list and thus must go at the end.
Here is what I have so far:
let insert_number (x: int) (l: int list): int list =
List.fold_right l ~f:(
fun cur -> fun acc ->
if x < cur then cur::x::accum
else cur::accum
) ~init: []
Using this with a test case like:
insert_number (3) ([1; 2; 4]);;
- : int list = [1; 2; 3; 4]
gives the correct answer. However, with a test case like this:
insert_number (3) ([1; 2]);;
- : int list = [1; 2]
the number is not inserted because it should be added to the end of the list.
Could someone help me understand how I am supposed to integrate this case into the function used with List.fold_right.
A fold works by passing along a set of state as it iterates over each element in a list (or other foldable data structure). The function passed in takes both the current element and that state.
I think you're really really close, but you need as Jeffrey suggests a boolean flag to indicate whether or not the value has been inserted. This will prevent multiple insertions and if the flag is still false when the fold is done, we can detect that and add the value to insert.
This match also serves the purpose of giving us an opportunity to discard the no longer needed boolean flag.
let insert v lst =
match List.fold_right
(fun x (inserted, acc) ->
if v > x && not inserted then (true, x::v::acc)
else (inserted, x::acc))
lst
(false, []) with
| (true, lst) -> lst
| (_, lst) -> v::lst
One way to look at List.fold_right is that it looks at each element of the list in turn, but in reverse order. For each element it transforms the current accumulated result to a new one.
Thinking backward from the end of the list, what you want to do, in essence, is look for the first element of the list that's less than x, then insert x at that point.
So the core of the code might look something like this:
if element < x then element :: x :: accum else element :: accum
However, all the earlier elements of the list will also be less than x. So (it seems to me) you need to keep track of whether you've inserted x into the list or not. This makes the accumulated state a little more complicated.
I coded this up and it works for me after fixing up the case where x goes at the front of the list.
Perhaps there is a simpler way to get it to work, but I couldn't come up with one.
As I alluded to in a comment, it's possible to avoid the extra state and post-processing by always inserting the element and effectively doing a "local sort" of the last two elements:
let insert_number x l =
List.fold_right (
fun cur -> function
| [] when x > cur -> [cur; x]
| [] -> [x; cur]
| x::rest when x > cur -> cur::x::rest
| x::rest -> x::cur::rest
) l []
Also, since folding doesn't seem to actually be a requirement, here's a version using simple recursion instead, which I think is far more comprehensible:
let rec insert_number x = function
| [] -> [x]
| cur::rest when cur > x -> x::cur::rest
| cur::rest -> cur::insert_number x rest

How to count the number of recurring character repetitions in a char list?

My goal is to take a char list like:
['a'; 'a'; 'a'; 'a'; 'a'; 'b'; 'b'; 'b'; 'a'; 'd'; 'd'; 'd'; 'd']
Count the number of repeated characters and transform it into a (int * char) list like this:
[(5, 'a'); (3, 'b'); (1, 'a'); (4, 'd')]
I am completely lost and also am very very new to OCaml. Here is the code I have rn:
let to_run_length (lst : char list) : (int * char) list =
match lst with
| [] -> []
| h :: t ->
let count = int 0 in
while t <> [] do
if h = t then
count := count + 1;
done;
I am struggling on how to check the list like you would an array in C or Python. I am not allowed to use fold functions or map or anything like that.
Edit: Updated code, yielding an exception on List.nth:
let rec to_run_length (lst : char list) : (int * char) list =
let n = ref 0 in
match lst with
| [] -> []
| h :: t ->
if h = List.nth t 0 then n := !n + 1 ;
(!n, h) :: to_run_length t ;;
Edit: Added nested match resulting in a function that doesn't work... but no errors!
let rec to_run_length (lst : char list) : (int * char) list =
match lst with
| [] -> []
| h :: t ->
match to_run_length t with
| [] -> []
| (n, c) :: tail ->
if h <> c then to_run_length t
else (n + 1, c) :: tail ;;
Final Edit: Finally got the code running perfect!
let rec to_run_length (lst : char list) : (int * char) list =
match lst with
| [] -> []
| h :: t ->
match to_run_length t with
| (n, c) :: tail when h = c -> (n + 1, h) :: tail
| tail -> (1, h) :: tail ;;
One way to answer your question is to point out that a list in OCaml isn't like an array in C or Python. There is no (constant-time) way to index an OCaml list like you can an array.
If you want to code in an imperative style, you can treat an OCaml list like a list in C, i.e., a linked structure that can be traversed in one direction from beginning to end.
To make this work you would indeed have a while statement that continues only as long as the list is non-empty. At each step you examine the head of the list and update your output accordingly. Then replace the list with the tail of the list.
For this you would want to use references for holding the input and output. (As a side comment, where you have int 0 you almost certainly wanted ref 0. I.e., you want to use a reference. There is no predefined OCaml function or operator named int.)
However, the usual reason to study OCaml is to learn functional style. In that case you should be thinking of a recursive function that will compute the value you want.
For that you need a base case and a way to reduce a non-base case to a smaller case that can be solved recursively. A pretty good base case is an empty list. The desired output for this input is (presumably) also an empty list.
Now assume (by recursion hypothesis) you have a function that works, and you are given a non-empty list. You can call your function on the tail of the list, and it (by hypothesis) gives you a run-length encoded version of the tail. What do you need to do to this result to add one more character to the front? That's what you would have to figure out.
Update
Your code is getting closer, as you say.
You need to ask yourself how to add a new character to the beginning of the encoded value. In your code you have this, for example:
. . .
match to_run_length t with
| [] -> []
. . .
This says to return an empty encoding if the tail is empty. But that doesn't make sense. You know for a fact that there's a character in the input (namely, h). You should be returning some kind of result that includes h.
In general if the returned list starts with h, you want to add 1 to the count of the first group. Otherwise you want to add a new group to the front of the returned list.

how to add a number in a 2D list with specific index in haskell

I'm beginner in haskell and I tried to add a number in a 2D list with specific index in haskell but I don't know how to do
example i have this:
[[],[],[]]
and I would like to put a number (3) in the index 1 like this
[[],[3],[]]
I tried this
[array !! 1] ++ [[3]]
but it doesn't work
As you may have noticed in your foray so far, Haskell isn't like many other languages in that it is generally immutable, so trying to change a value, especially in a deeply nested structure like that, isn't the easiest thing. [array !! 1] would give you a nested list [[]] but this is not mutable, so any manipulations you do this structure won't be reflected in the original array, it'll be a separate copy.
(There are specialized environments where you can do local mutability, as with e.g. Vectors in the ST monad, but these are an exception.)
For what you're trying to do, you'll have to deconstruct the list to get it to a point where you can easily make the modification, then reconstruct the final structure from the (modified) parts.
The splitAt function looks like it will help you with this: it takes a list and separates it into two parts at the index you give it.
let array = [[],[],[]]
splitAt 1 array
will give you
([[]], [[],[]])
This helps you by getting you closer to the list you want, the middle nested list.
Let's do a destructuring bind to be able to reconstruct your final list later:
let array = [[],[],[]]
(beginning, end) = splitAt 1 array
Next, you'll need to get at the sub-list you want, which is the first item in the end list:
desired = head end
Now you can make your modification -- note, this will produce a new list, it won't modify the one that's there:
desired' = 3:desired
Now we need to put this back into the end list. Unfortunately, the end list is still the original value of [[],[]], so we'll have to replace the head of this with our desired' to make it right:
end' = desired' : (tail end)
This drops the empty sub-list at the beginning and affixes the modified list in its place.
Now all that's left is to recombine the modified end' with the original beginning:
in beginning ++ end'
making the whole snippet:
let array = [[],[],[]]
(beginning, end) = splitAt 1 array
desired = head end
desired' = 3:desired
end' = desired' : (tail end)
in beginning ++ end'
or, if you're entering all these as commands in the REPL:
let array = [[],[],[]]
let (beginning, end) = splitAt 1 array
let desired = head end
let desired' = 3:desired
let end' = desired' : (tail end)
beginning ++ end'
As paul mentions, things in Haskell are immutable. What you want to do must be done not be modifying the list in place, but by destructuring the list, transforming one of its parts, and restructuring the list with this changed part. One way of destructuring (via splitAt) is put forth there; I'd like to offer another.
Lists in Haskell are defined as follows:
data [] a = [] | a : [a]
This reads "A list of a is either empty or an a followed by a list of a". (:) is pronounced "cons" for "constructor", and with it, you can create nonempty lists.
1 : [] -> [1]
1 : [2,3] -> [1,2,3]
1 : 2 : 3 : [] -> [1,2,3]
This goes both ways, thanks to pattern matching. If you have a list [1,2,3], matching it to x : xs will bind its head 1 to the name x and its tail [2,3] to xs. As you can see, we've destructured the list into the two pieces that were initially used to create it. We can then operate on those pieces before putting the list back together:
λ> let x : xs = [1,2,3]
λ> let y = x - 5
λ> y : xs
[-4,2,3]
So in your case, we can match the initial list to x : y : z : [], compute w = y ++ [3], and construct our new list:
λ> let x : y : z : [] = [[],[],[]]
λ> let w = y ++ [3]
λ> [x,w,z]
[[],[3],[]]
But that's not very extensible, and it doesn't solve the problem you pose ("with specific index"). What if later on we want to change the thousandth item of a list? I'm not too keen on matching that many pieces. Fortunately, we know a little something about lists—index n in list xs is index n+1 in list x:xs. So we can recurse, moving one step along the list and decrementing our index each step of the way:
foo :: Int -> [[Int]] -> [[Int]]
foo 0 (x:xs) = TODO -- Index 0 is x. We have arrived; here, we concatenate with [3] before restructuring the list.
foo n (x:xs) = x : foo (n-1) xs
foo n [] = TODO -- Up to you how you would like to handle invalid indices. Consider the function error.
Implement the first of those three yourself, assuming you're operating on index zero. Make sure you understand the recursive call in the second. Then read on.
Now, this works. It's not all that useful, though—it performs a predetermined computation on a specified item in a list of one particular type. It's time to generalize. What we want is a function of the following type signature:
bar :: (a -> a) -> Int -> [a] -> [a]
where bar f n xs applies the transformation f to the value at index n in the list xs. With this, we can implement the function from before:
foo n xs = bar (++[3]) n xs
foo = bar (++[3]) -- Alternatively, with partial application
And believe it or not, changing the foo you already wrote into the much more useful bar is a very simple task. Give it a try!

how to compress a List in f#?

Hi I'm new to f# and I got this exercise I can't figure out:
"Implement a Function :"
let compress (l : List<'a>) : List<'a> = ...
That removes consecutive occurences of the same element in l. for example compressing [a;a;a;a;b;b;c] to [a;b;c]
I'm not allowed to use the built-in functions of f# and need to do this with pattern matching.
My current code (it's not much) :
let rec compress (l: List<'a>) : List<'a> =
match l with
| [] -> l
thanks for the help!
For any recursive function you need to consider: 1. the terminal case and 2. the general case. In your scenario:
the empty list []
non-empty list x::xs (where x represents the head of the list and xs the rest aka tail)
The other important aspect to consider when you build such a functions is to assume it works for a previous value. For example in the case of factorial, we assume the function already works for a previous scenario e.g. factorial of n-1.
let fact n =
match n with
| 0 | 1 -> 1
| _ -> n * fact (n-1)

Haskell and manipulating a list of tuples

Ok so have been faced with a problem where basically I have a been told to make a multiset, or a list of tuples. (Char,Int) and then I have to write a function that takes a item and inserts it into this list, but if there is already a matching tuple in the list it increases the Int.
i.e. i had a list [(p,2),(w,3)] and i get another w it should give [(p,2),(w,4)]
How would you go about it, i've tried
listAdd :: Char->Int->ListOfT -> ListOfT
listAdd c i l
|length l == 0 =(c,i):l
|fst l == c = (c,i+1):l
but this gives loads of errors, i need to remove the list element at that point and replace it with with (c,i+1), so how do i remove from the list and how to i get i+1? also how do you make a loop which will go through all the elements in a list?
And i can't use any of the import Data stuff
I know this is asking a ton but any help would be great thanks.
Neo
Okay can this code be fiddled with so it can be used tto make tuples of any items not just chars. so i could load it up and make a list of tuples with stirngs instead, close it then load it up again and make a list of tuples of ints?
ok I think your idea is not bad you just have to get the details straight.
The loop you asked about is usually either done with recursion (as a list is a recursive structure that's a great idea) or with some higher order functions like map, filter, foldr, ... that will hide the recursion from you (you could say they abstract away the repeating stuff) - anway in this case I think the easiest way is just to go with what you started and use the direct recursion.
Here is a simple version (you maybe want to extent) that does the basic stuff:
listAdd :: Char -> [(Char,Int)] -> [(Char,Int)]
listAdd c [] = [(c,1)]
listAdd c ((c',i):xs)
| c' == c = (c,i+1):xs
| otherwise = (c',i) : listAdd c xs
as you can see the first case is very similar to what you had: if the dictionary (the second argument) is the empty list than you just add a new tuple with the char to insert and the number 1
if not then you check if the first element in the dictionary has the same character (c' here), if yes then you increase the count and if not you let this element stand as it is and recursively search through the rest of the dictionary.
Also note that you can use pattern matching here to not only deconstruct the dictionary into head::tail form but also deconstruct the head into (..,..) tuple parts as well.
If you want you can use a # in there to and get the second case a bit more concise:
listAdd :: Char -> [(Char,Int)] -> [(Char,Int)]
listAdd c [] = [(c,1)]
listAdd c (x#(c',i):xs)
| c' == c = (c,i+1):xs
| otherwise = x : listAdd c xs
PS: in case you wondered why I did not use your Int argument? Because I don't know what you want to do with it if there is already a value - here is a version where I just add it to it (seems resonable):
listAdd :: Char -> Int -> [(Char,Int)] -> [(Char,Int)]
listAdd c i [] = [(c,i)]
listAdd c i (x#(c',i'):xs)
| c' == c = (c,i+i'):xs
| otherwise = x : listAdd c i xs
List manipulations with just recursive functions can be indeed hard for beginners to grok, but in this case they should fit the problem nicely.
Let's start with a bit better signature and a helper.
type MyList = [(Char, Int)]
listAdd :: Char -> MyList -> MyList
listAdd p l = listAdd' p [] l
Notice that I've changed the signature to accept just Char; we don't need to supply the initial count, since if there are no such elements currently on the list, we'll just set it to 1 when adding a new element.
Okay, that's the basic skeleton. The helper is there just to make it easier to store the "already processed" part of the list. Let's look at it:
listAdd' :: Char -> MyList -> MyList -> MyList
First, we add the recursion end condition:
listAdd' p left [] = left ++ [(p, 1)]
This means that if we haven't found the element to replace earlier, we can just add it at the end.
listAdd' p left (x:right) = if p == fst x
then left ++ [(fst x, snd x + 1)] ++ right
else listAdd' p (left ++ [x]) right
Okay, so now we split up the "right" part to the first element of it and the rest. Let's look at the if:
if we managed to find the element, we can end the computation by appending the rest of the list to the modified element and what we had previously
if it's still not it, we proceed with recursion.
As an additional remark at the end, you could easily change Char to Eq a => a to allow your function to work on any type that can be directly compared, Char included.