Omu
Omu

Reputation: 71206

sum 2 lists and get 3rd in f#, please correct my syntax

I'm trying to achieve this:

7 2 3 5
10 12 20

res = 10 + max(7,2) ; 12 + max(2,3); 20 + max(3,5)

this is my code so far:

//prevline.count is always currLine.count+1

let getResLine currLine prevLine =
   let rec loop resLine prevLine' = function
       |[] -> resLine
       |hd::tl -> loop (hd + (max (List.nth prevLine' 0) (List.nth prevLine' 1)))::resLine (List.tail prevLine') tl
   loop [] prevLine currLine

but it doesn't compile, it tells me some type mismatch errors, probably somebody more experienced could see some obvious errors that I made, please help

Edit: updated my code accoding to the suggestions, but it's still not working

Upvotes: 0

Views: 279

Answers (4)

J D
J D

Reputation: 48687

I have no idea what your question is asking but yamen's answer can be simplified to:

let res =
  Seq.pairwise nums1
  |> Seq.map2 (fun a (b1, b2) -> a + max b1 b2) nums2

Upvotes: 4

yamen
yamen

Reputation: 15618

By the way, you might be interested in another way of looking at the problem. Start with the list of numbers:

let nums1 = [7; 2; 3; 5]
let nums2 = [10; 12; 20]

Then

let res = nums1 
          |> Seq.pairwise 
          |> Seq.map2 (fun a (b1, b2) -> a + max b1 b2) nums2

This has the benefit of being more semantically matched to what you want to do.

Edit: Simplified using map2 instead of zip and map thanks to @Daniel and @JonHarrop.

Upvotes: 9

svick
svick

Reputation: 244827

First, if you want to split a list into a head and a tail, use just hd::tl (without brackets).

Second, you don't seem to be actually creating the result list. And I think you don't need an accumulator here.

Third, I think it's confusing to use the same variable names in both functions (because you can use the variables from the outer function in the inner function).

Because of all that, I would rewrite your function like this:

let getResLine prevLine resLine =
    let rec loop prevLine' = function
        |[] -> []
        |hd::tl -> (hd + (max (List.nth prevLine' 0) (List.nth prevLine' 1)))::loop (List.tail prevLine') tl
    loop prevLine resLine

Although I think it would be more readable using higher-order functions, not explicit recursion:

let getResLine prevLine resLine =
    let maxes line = Seq.map2 (max) prevLine (List.tail prevLine)
    Seq.map2 (+) (maxes prevLine) resLine | Seq.toList

I used Seq.map2, insted of List.map2, because the latter doesn't handle lists of unequal length.

Upvotes: 2

John Palmer
John Palmer

Reputation: 25516

I think this is what you want

let getResLine currLine prevLine =
    let rec loop resLine prevLine = function
        |[] -> resLine
        |hd::tl -> loop (hd + max (List.nth prevLine 0) (List.nth prevLine 1)) (List.tail prevLine) tl
    loop 0 prevLine currLine

Upvotes: 2

Related Questions