reversing a list in OCaml using fold_left/right - recursion

UPDATE - Solution
Thanks to jacobm for his help, I came up with a solution.
// Folding Recursion
let reverse_list_3 theList =
List.fold_left (fun element recursive_call -> recursive_call::element) [] theList;;
I'm learning about the different ways of recursion in OCaml (for class) and for some exercise, I'm writing a function to reverse a list using different recursion styles.
// Forward Recursion
let rec reverse_list_forward theList =
match theList with [] -> [] | (head::tail) -> (reverse_list_1 tail) # [head];;
// Tail Recursion
let rec reverse_list_tail theList result =
match theList with [] -> result | (head::tail) -> reverse_list_2 tail (head::result);;
Now, I'm trying to write a reverse function using List.fold_left but I'm stuck and can't figure it out. How would I write this reverse function using folding?
Also, if anyone has good references on functional programming, the different types of recursion, higher-order-functions, etc..., links would be greatly appreciated :)

I find it helpful to think of the fold operations as a generalization of what to do with a sequence of operations
a + b + c + d + e
fold_right (+) 0 applies the + operation right-associatively, using 0 as a base case:
(a + (b + (c + (d + (e + 0)))))
fold_left 0 (+) applies it left-associatively:
(((((0 + a) + b) + c) + d) + e)
Now consider what happens if you replace + with :: and 0 with [] in both right- and left-folds.
It may also be useful to think about the way fold_left and fold_right work as "replacing" the :: and [] operators in a list. For instance, the list [1,2,3,4,5] is really just shorthand for 1::(2::(3::(4::(5::[])))). It may be useful to think of fold_right op base as letting you "replace" :: with op and [] with base: for instance
fold_right (+) 0 1::(2::(3::(4::(5::[]))))
becomes
1 + (2 + (3 + (4 + (5 + 0))))
:: became +, [] became 0. From this perspective, it's easy to see that fold_right (::) [] just gives you back your original list. fold_left base op does something a bit weirder: it rewrites all the parentheses around the list to go the other direction, moves [] from the back of the list to the front, and then replaces :: with op and [] with base. So for instance:
fold_left 0 (+) 1::(2::(3::(4::(5::[]))))
becomes
(((((0 + 1) + 2) + 3) + 4) + 5)
With + and 0, fold_left and fold_right produce the same result. But in other cases, that's not so: for instance if instead of + you used - the results would be different: 1 - (2 - (3 - (4 - (5 - 0)))) = 3, but (((((0 - 1) - 2) - 3) - 4) - 5) = -15.

let rev =
List.fold_left ( fun lrev b ->
b::lrev
) [];;
test:
# rev [1;2;3;4];;
- : int list = [4; 3; 2; 1]

Related

Functionally idiomatic FFT

I've written the this radix-2 FFT with the goal of making it functionally idiomatic without sacrificing too much performance:
let reverse x bits =
let rec reverse' x bits y =
match bits with
| 0 -> y
| _ -> ((y <<< 1) ||| (x &&& 1))
|> reverse' (x >>> 1) (bits - 1)
reverse' x bits 0
let radix2 (vector: Complex[]) (direction: int) =
let z = vector.Length
let depth = floor(Math.Log(double z, 2.0)) |> int
if (1 <<< depth) <> z then failwith "Vector length is not a power of 2"
// Complex roots of unity; "twiddle factors"
let unity: Complex[] =
let xpn = float direction * Math.PI / double z
Array.Parallel.init<Complex> (z/2) (fun i ->
Complex.FromPolarCoordinates(1.0, (float i) * xpn))
// Permutes elements of input vector via bit-reversal permutation
let pvec = Array.Parallel.init z (fun i -> vector.[reverse i depth])
let outerLoop (vec: Complex[]) =
let rec recLoop size =
if size <= z then
let mid, step = size / 2, z / size
let rec inrecLoop i =
if i < z then
let rec bottomLoop idx k =
if idx < i + mid then
let temp = vec.[idx + mid] * unity.[k]
vec.[idx + mid] <- (vec.[idx] - temp)
vec.[idx] <- (vec.[idx] + temp)
bottomLoop (idx + 1) (k + step)
bottomLoop i 0
inrecLoop (i + size)
inrecLoop 0
recLoop (size * 2)
recLoop 2
vec
outerLoop pvec
The outerLoop segment is the biggest nested tail-recursive mess I have ever written. I replicated the algorithm in the Wikipedia article for the Cooley-Tukey algorithm, but the only functional constructs I could think to implement using higher-order functions result in massive hits to both performance and memory efficiency. Are there other solutions that would yield the same results without resulting in massive slow-downs, while still being idiomatic?
I'm not an expert on how the algorithm works, so there might be a nice functional implementation, but it is worth noting that using a localised mutation is perfectly idiomatic in F#.
Your radix2 function is functional from the outside - it takes vector array as an input, never mutates it, creates a new array pvec which it then initializes (using some mutation along the way) and then returns it. This is a similar pattern to what built-in functions like Array.map use (which initializes a new array, mutates it and then returns it). This is often a sensible way of doing things, because some algorithms are better written using mutation.
In this case, it's perfectly reasonable to also use local mutable variables and loops. Doing that will make your code more readable compared to the tail-recursive version. I have not tested this, but my naive translation of your outerLoop function would just be to use three nested loops - something like this:
let mutable size = 2
while size <= z do
let mid, step = size / 2, z / size
let mutable i = 0
while i < z do
for j in 0 .. mid - 1 do
let idx, k = i + j, step * j
let temp = pvec.[idx + mid] * unity.[k]
pvec.[idx + mid] <- (pvec.[idx] - temp)
pvec.[idx] <- (pvec.[idx] + temp)
i <- i + size
size <- size * 2
This might not be exactly right (I did this just be refactoring your code), but I think it's actually more idiomatic than using complex nested tail-recursive functions in this case.

Average calculating of consecutive list elements in OCaml

I am trying to write a function in OCaml that will calculate the average of consecutive elements in a list. For example with [1; 2; 3; 4] it should output [1; 2; 3]. It should take (1 + 2) / 2 and give 1 then take (2 + 3) / 2 and give 2 and so on.
The code I wrote, however, only returns [1; 2]:
let rec average2 xs = match xs with
|[] -> []
|x :: [] -> [x]
|x :: x' :: xs -> if xs = [] then [(x + x') / 2] else [(x + x') / 2] # (average2 xs)
Can you please tell me how to fix this. Thank you.
When you're doing x :: y :: l in a match, you're effectively taking out the elements of the list permanently.
So if you want to do an operation on pairs of elements, you need to put one back in.
Example:
You have a list of [1;2;3;4]
You want to operate on 1 and 2, in your match it will interpret as:
1 :: 2 :: [3;4]
If you continue without adding an element in, the next statement would be:
3 :: 4 :: []
which is not what you want.
To correct this, in your recurice call you need to do (average2 (x'::xs) and not just (average2 xs) because xs is the rest of the list after taking the elements out.
OCaml allows to bind a pattern p to a variable v using p as v (alias patterns):
let rec average2 = function
| x :: (y :: _ as tail) -> (x + y) / 2 :: (average2 tail)
| _ -> []
Above, y :: _ as tail destructures a list named tail as a non-empty list headed by y and having an arbitrary tail _, the value of which we don't care about.
Note that I also simplified your function so that you don't check whether _ is empty or not: recursion handles this for you here.
Also, when you have zero or one element in the list, you should return an empty list.
# average2 [ 10; 20; 30; 40];;
- : int list = [15; 25; 35]

Simplify a recursive function from 3 to 2 clauses

I am doing some exercises on F#, i have this function that calculate the alternate sum:
let rec altsum = function
| [] -> 0
| [x] -> x
| x0::x1::xs -> x0 - x1 + altsum xs;;
val altsum : int list -> int
The exercise consist in declare the same function with only two clauses...but how to do this?
The answer of mydogisbox is correct and work!
But after some attempts I found a smallest and readable solution of the problem.
let rec altsum2 = function
| [] -> 0
| x0::xs -> x0 - altsum2 xs
Example
altsum2 [1;2;3] essentially do this:
1 - (2 - (3 - 0)
it's is a bit tricky but work!
OFF TOPIC:
Another elegant way to solve the problem, using F# List library is:
let altsum3 list = List.foldBack (fun x acc -> x - acc) list 0;;
After the comment of phoog I started trying to solve the problem with a tail recursive function:
let tail_altsum4 list =
let pl l = List.length l % 2 = 0
let rec rt = function
| ([],acc) -> if pl list then -acc else acc
| (x0::xs,acc) -> rt (xs, x0 - acc)
rt (list,0)
This is also a bit tricky...substraction is not commutative and it's impossible think to revers with List.rev a long list...but I found a workaround! :)
To reduce the number of cases, you need to move your algorithm back closer to the original problem. The problem says to negate alternating values, so that's what your solution should do.
let altsum lst =
let rec altsumRec lst negateNext =
match lst with
| [] -> 0
| head::tail -> (if negateNext then -head else head) + altsumRec tail (not negateNext)
altsumRec lst false

All substrings that are sequences of characters using functional programming

As a followup to my earlier question on finding runs of the same character in a string, I would also like to find a functional algorithm to find all substrings of length greater than 2 that are ascending or descending sequences of letters or digits (e,g,: "defgh", "34567", "XYZ", "fedcba", "NMLK", 9876", etc.) in a character string ([Char]). The only sequences that I am considering are substrings of A..Z, a..z, 0..9, and their descending counterparts. The return value should be a list of (zero-based offset, length) pairs. I am translating the "zxcvbn" password strength algorithm from JavaScript (containing imperative code) to Scala. I would like to keep my code as purely functional as possible, for all the usual reasons given for writing in the functional programming style.
My code is written in Scala, but I can probably translate an algorithm in any of Clojure, F#, Haskell, or pseudocode.
Example: For the string qweABCD13987 would return [(3,4),(9,3)].
I have written a rather monsterous function that I will post when I again have access to my work computer, but I am certain that a more elegant solution exists.
Once again, thanks.
I guess a nice solution for this problem is really more complicated than it seems at first.
I'm no Scala Pro, so my solution is surely not optimal and nice, but maybe it gives you some ideas.
The basic idea is to compute the difference between two consecutive characters, afterwards it unfortunately gets a bit messy. Ask me if some of the code is unclear!
object Sequences {
val s = "qweABCD13987"
val pairs = (s zip s.tail) toList // if s might be empty, add a check here
// = List((q,w), (w,e), (e,A), (A,B), (B,C), (C,D), (D,1), (1,3), (3,9), (9,8), (8,7))
// assuming all characters are either letters or digits
val diff = pairs map {case (t1, t2) =>
if (t1.isLetter ^ t2.isLetter) 0 else t1 - t2} // xor could also be replaced by !=
// = List(-6, 18, 36, -1, -1, -1, 19, -2, -6, 1, 1)
/**
*
* #param xs A list indicating the differences between consecutive characters
* #param current triple: (start index of the current sequence;
* number of current elements in the sequence;
* number indicating the direction i.e. -1 = downwards, 1 = upwards, 0 = doesn't matter)
* #return A list of triples similar to the argument
*/
def sequences(xs: Seq[Int], current: (Int, Int, Int) = (0, 1, 0)): List[(Int, Int, Int)] = xs match {
case Nil => current :: Nil
case (1 :: ys) =>
if (current._3 != -1)
sequences(ys, (current._1, current._2 + 1, 1))
else
current :: sequences(ys, (current._1 + current._2 - 1, 2, 1)) // "recompute" the current index
case (-1 :: ys) =>
if (current._3 != 1)
sequences(ys, (current._1, current._2 + 1, -1))
else
current :: sequences(ys, (current._1 + current._2 - 1, 2, -1))
case (_ :: ys) =>
current :: sequences(ys, (current._1 + current._2, 1, 0))
}
sequences(diff) filter (_._2 > 1) map (t => (t._1, t._2))
}
It's always best to split a problem into several smaller subproblems. I wrote a solution in Haskell, which is easier for me. It uses lazy lists, but I suppose you can convert it to Scala either using streams or by making the main function tail recursive and passing the intermediate result as an argument.
-- Mark all subsequences whose adjacent elements satisfy
-- the given predicate. Includes subsequences of length 1.
sequences :: (Eq a) => (a -> a -> Bool) -> [a] -> [(Int,Int)]
sequences p [] = []
sequences p (x:xs) = seq x xs 0 0
where
-- arguments: previous char, current tail sequence,
-- last asc. start offset of a valid subsequence, current offset
seq _ [] lastOffs curOffs = [(lastOffs, curOffs - lastOffs)]
seq x (x':xs) lastOffs curOffs
| p x x' -- predicate matches - we're extending current subsequence
= seq x' xs lastOffs curOffs'
| otherwise -- output the currently marked subsequence and start a new one
= (lastOffs, curOffs - lastOffs) : seq x' xs curOffs curOffs'
where
curOffs' = curOffs + 1
-- Marks ascending subsequences.
asc :: (Enum a, Eq a) => [a] -> [(Int,Int)]
asc = sequences (\x y -> succ x == y)
-- Marks descending subsequences.
desc :: (Enum a, Eq a) => [a] -> [(Int,Int)]
desc = sequences (\x y -> pred x == y)
-- Returns True for subsequences of length at least 2.
validRange :: (Int, Int) -> Bool
validRange (offs, len) = len >= 2
-- Find all both ascending and descending subsequences of the
-- proper length.
combined :: (Enum a, Eq a) => [a] -> [(Int,Int)]
combined xs = filter validRange (asc xs) ++ filter validRange (desc xs)
-- test:
main = print $ combined "qweABCD13987"
Here is my approximation in Clojure:
We can transform the input string so we can apply your previous algorithm to find a solution. The alorithm wont be the most performant but I think you will have a more abstracted and readable code.
The example string can be transformed in the following way:
user => (find-serials "qweABCD13987")
(0 1 2 # # # # 7 8 # # #)
Reusing the previous function "find-runs":
user => (find-runs (find-serials "qweABCD13987"))
([3 4] [9 3])
The final code will look like this:
(defn find-runs [s]
(let [ls (map count (partition-by identity s))]
(filter #(>= (% 1) 3)
(map vector (reductions + 0 ls) ls))))
(def pad "#")
(defn inc-or-dec? [a b]
(= (Math/abs (- (int a) (int b))) 1 ))
(defn serial? [a b c]
(or (inc-or-dec? a b) (inc-or-dec? b c)))
(defn find-serials [s]
(map-indexed (fn [x [a b c]] (if (serial? a b c) pad x))
(partition 3 1 (concat pad s pad))))
find-serials creates a 3 cell sliding window and applies serial? to detect the cells that are the beginning/middle/end of a sequence. The string is conveniently padded so the window is always centered over the original characters.

polynomial equation standard ml

I'm trying to make a function that will solve a univariante polynomial equation in Standard ML, but it keeps giving me error.
The code is below
(* Eval Function *)
- fun eval (x::xs, a:real):real =
let
val v = x (* The first element, since its not multiplied by anything *)
val count = 1 (* We start counting from the second element *)
in
v + elms(xs, a, count)
end;
(* Helper Function*)
- fun pow (base:real, 0) = 1.0
| pow (base:real, exp:int):real = base * pow(base, exp - 1);
(* A function that solves the equation except the last element in the equation, the constant *)
- fun elms (l:real list, a:real, count:int):real =
if (length l) = count then 0.0
else ((hd l) * pow(a, count)) + elms((tl l), a, count + 1);
now the input should be the coefficient if the polynomial elements and a number to substitute the variable, ie if we have the function 3x^2 + 5x + 1, and we want to substitute x by 2, then we would call the eval as follows:
eval ([1.0, 5.0, 3.0], 2.0);
and the result should be 23.0, but sometimes on different input, its giving me different answers, but on this imput its giving me the following error
uncaught exception Empty raised at:
smlnj/init/pervasive.sml:209.19-209.24
what could be my problem here?
Empty is raised when you run hd or tl on an empty list. hd and tl are almost never used in ML; lists are almost always deconstructed using pattern matching instead; it's much prettier and safer. You don't seem to have a case for empty lists, and I didn't go through your code to figure out what you did, but you should be able to work it out yourself.
After some recursive calls, elms function gets empty list as its argument. Since count is always greater than 0, (length l) = count is always false and the calls hd and tl on empty list are failed right after that.
A good way to fix it is using pattern matching to handle empty lists on both eval and elms:
fun elms ([], _, _) = 0.0
| elms (x::xs, a, count) = (x * pow(a, count)) + elms(xs, a, count + 1)
fun eval ([], _) = 0.0
| eval (x::xs, a) = x + elms(xs, a, 1)

Resources