0

I am trying to write a function in SML where there are two lists being passed into a function, and if both lists contain the same number (or multiple of the same number) those numbers are added to a new function.

fun shared([], []) = []
    let 
        val list = []
    in
        shared(x::xs, y) = if x = y then x::list else shared(xs,y)
    end

my thought process is that if x and y are equal then x will be added to the list which will contain all of the numbers that are shared in both of the original lists.

Edit: New code

fun append([], L) = L
    | append(x::rest, L) = x::append(rest, L);

fun shared([], y) = 
    let 
        val list = []
    in
        | shared(y, x::xs) = if y = x then append(list, x)
                                    else shared(y,xs)
    end;

I do not think using the | here is legal in the in statement, but I don't know how to run through the list recursively without it.

  • Are you aware that `val list = []` permanently binds `list` to the empty list, and does not provide any way to subsequently make `list` contain elements? – ruakh Jan 31 '18 at 03:06
  • Oh I thought it by using the :: I could keep consing values into the empty list @ruakh – TrashMachine139 Jan 31 '18 at 03:13
  • You absolutely can, but that doesn't mutate the existing list. "Consing" doesn't mean what you think; `x::list` just means "a list whose first element is `x` and whose remaining elements are `list`". (I see that you have some C++ background. Consider something like `const int i = 0; 3 + i;`. This certainly adds a value to `i`, but it doesn't change the value of `i`.) – ruakh Jan 31 '18 at 04:01
  • yes my main language is c++ :) Is there any way to write a function in a way where i add common integers to a new list? I've updated my code a little bit. I'm just trying to mess with different methods until I can find a solution! It's way more difficult to think recursively instead of iteratively! @ruakh – TrashMachine139 Jan 31 '18 at 04:17
  • I also realize that the append is doing the same thing as you described above, is there a way to keep a new list updated? Or should I try an approach of deleting items in one of this lists unless they are a match? @ruakh – TrashMachine139 Jan 31 '18 at 04:19
  • @TrashMachine139: What do you mean by "those numbers are *added* to a *new* function"? Do you mean *apply* those numbers to *another* function? – sshine Feb 01 '18 at 09:14

1 Answers1

0

if both lists contain the same number (or multiple of the same number) [...]

You assume that the input lists may contain duplicates, but you don't say if the result list should contain duplicates, and if so, what their multiplicity should be. Your code suggests a left-bias: That duplicates in xs should be repeated as many times as they occur in xs, regardless of how many times duplicates occur in ys; this seems unintended and undesired.

If you want duplicates to occur more than once, you should probably stick to the multiset intersection definition of multiplicity.

In the answer below I'll assume that you only want numbers to appear in the result once, even if they occur multiple times in either input list. Ideally in this case, though, you use a data type for sets that don't allow duplicates.

I'll start by finding the set intersection between two lists:

(* Remove duplicates in ''a list. O(n^2) *)
fun nub [] = []
  | nub (x::xs) = x :: nub (List.filter (fn y => x <> y) xs)

(* Determine membership of x in ys. O(n) *)
fun isElem (x, ys) = List.exists (fn y => x = y) ys

(* Find intersection of xs, ys, remove duplicates. O(n^2) *)
fun intersect (xs, ys) = nub (List.filter (fn x => isElem (x, ys)) xs)

Here's an example of using this:

- intersect ([0,0,1,1,2,2,3,4], [1,1,2,3,3,5,6,6]);
> val it = [1, 2, 3] : int list

[...] those numbers are added to a new function

I'm not sure exactly what is meant here. You don't add numbers and functions together, and functions don't have mutable state to which things can be added. Perhaps you mean that if the intersection is non-empty, a function is applied to this non-empty result?

That could look like:

fun sum xs = foldl op+ 0 xs

fun printIntersectSum (xs, ys) =
    case intersect (xs, ys) of
         []  => print "Nothing to see; move along!\n"
       | res => print ("Sum of intersection: " ^ Int.toString (sum res) ^ "\n")

And here's an example of using this:

- printIntersectSum ([0,0,1,1,2,2,3,4], [1,1,2,3,3,5,6,6]);
The sum of the intersection is: 6
> val it = () : unit
sshine
  • 15,635
  • 1
  • 41
  • 66