How to check if x value exists in SML List - list

I need to write an SML function that takes in as input a list of tuples (x and y coordinates) and an integer value. The function needs to return true if the integer is an x value in the list and false otherwise. For example if the list was:
val list = [(1,1),(2,4),(3,9),(4,16)];
The function would behave as follows:
memberOf(2, list) = true
memberOf(4, list) = true
memberOf(9, list) = false
Can somebody help me write a function that accomplishes this? I only need to test if the x value is in the list, the y value of the tuple is unimportant.
Thank you!

fun member_of (item, list) = List.exists (fn (x,y) => x = item) list

You can access the first argument of your tuple using #1 tuple and the second one with #2 tuple. So you check if the item exists either as the first argument or the second of the tuple list until you reach the end of your list.
(* fn : int * (int * int) list -> bool *)
fun exists_in (item: int, mylist: (int*int) list) =
if null mylist
then false
else if #1 (hd mylist) = item orelse #2 (hd mylist) = item
then true
else exists_in (item, tl mylist)

Related

How to write a function in SML/NJ that in a given list, counts successive equal elements and returns a list of pairs (value, count)?

I have to write a function in SML/NJ that in a given list, counts successive equal elements and returns a list of pairs (value, count). Function should look like this:
fun group (xs: ''a list): (''a * int) list
I can only use anonymous functions and the structures List, ListPair and Math.
I have no idea how to do it. Can somebody please help me?
A simple but inefficient way is to write this version of group:
val group : ''a list -> ''a list list
and transform the output further into:
val group_count : ''a list -> (''a * int) list
in the following way:
fun group_count xss = map (fn xs => (hd xs, length xs)) xss
But a more efficient way would be to write a function span_count:
fun span_count p x [] count = (count, [])
| span_count p x (y::xs) count =
if p (x, y)
then span_count p x xs (count+1)
else (count, y::xs)
and use it recursively:
fun group_count [] = []
| group_count (x::xs) =
case span_count op= x xs 1 of
(count, ys) => (x, count) :: group_count ys

SML/NJ searching in list of tuples of list

I am very new to SML/NJ and I am kind of lost. I have been trying to implement a function that is going to search through the list of tuples that have some lists in it, for example:
val x = [(5, 2, [9 , 8, 7]), (3, 4, [6, 5, 0]), (11, 12, [8, 3, 1])]
I would like my function to add the first element of the tuple to the new list once there is a match between my target number and a number in element 3 of the tuple. I have tried several implementations, but none of them work properly so far.
type id = int* int* int list;
val b:id list = [(5,2,[9,8,7]), (3,4,[6,5,0]), (11, 12, [8,3,1])]
val number: int = 8;
val a: int list = nil;
fun findNum(nil) = a | findNum (x: id list) =
let val tem = hd(x)
val theList = #3tem
val i = #1tem
fun findMatch(nil) = a | findMatch(tem) =
if (number = hd(theList)) then i::a
else findMatch (tl(theList))
in findNum(tl(x))
end;
findNum(b);
I know it is badly written, and that is why it keeps returning an empty list. I feel like I need to do "if else" instead of let/in/end so it will recursively call the rest of the tuples in the list. My problem is that I am not sure how to do it because if I use if/else then I cannot declare some value inside the function. I appreciate any suggestions or hints.
Thank you.
You might start with a function member (x, xs) that is true if x is an element in the list xs:
fun member (x, xs) = List.exists (fn y => x = y) xs
A base case is when the list of three-tuples is empty. Then x does not occur in the third element of any of the (non-existing) three-tuples, and the list of results is empty. A recursive case is achieved by pattern matching against the first element of the list being a three-tuple, (i,j,xs), and the tail of the list, ts, and ask if x is a member of that third element xs; if it is, return the first part of the tuple, i:
fun find (x, []) = []
| find (x, (i,j,xs)::ts) =
if member (x, xs)
then i :: find (x, ts)
else find (x, ts)
A shorter version using the higher-order list combinators map and filter:
fun find (x, ts) = map #1 (filter (fn (i,j,xs) => member (x, xs)) ts)
Here is my implementation with some slight changes:
type id = int* int* int list;
val b:id list = [(5,2,[9,8,7]), (3,4,[6,5,0]), (11, 12, [8,3,1])]
val number: int = 8;
fun findNum [] = []
| findNum (x::xs) =
let
val theList :int list = #3 (x :id)
val i : int = #1 x
fun findMatch [] = false
| findMatch (y::ys) = if (number = y) then true
else findMatch ys
in
if (findMatch theList = true) then i ::(findNum xs)
else (findNum xs)
end;
Example:
- findNum b;
val it = [5,11] : int list

Checking elements of a list in SML

Hi I am relatively new to ML/SML and I am trying to write function that takes as input 2 lists. The one list contains 4 random strings ["duck","goose","swan","gull"] and the second takes another 4 strings ["duck","swan","goose","pigeon"].
What I would like to do i check each element in the first list against each element the other. If the strings are in the same position and are equal output a 'yes'. If the elements are not in the same position but are in the list then output 'maybe', and if the element isn't in the second list output 'no'.
So given the 2 examples above it would output ["yes","maybe","maybe","no"].
This is what I have done so far, but I can't figure out how to keep recursively calling the main function, checkEqual, to iterate over the entire first list.
fun buildStringList nil nil = nil
|buildStringList lst appList =
lst # appList
in
fun checkEqual nil nil = nil
| checkEqual code guess =
if hd code = hd guess then
buildStringList ([])(["yes"])
else if hd code = hd(tl guess) then
buildStringList ([])(["maybe"])
else if hd code = hd(tl(tl guess)) then
buildStringList ([])(["maybe"])
else if hd code = hd(tl(tl(tl guess))) then
buildStringList ([])(["maybe"])
else
buildStringList ([])(["no"])
end;
Any help would be greatly appreciated.
There are two code paths, comparing items by index [the "yes" condition] and then comparing them without regard to index [the "maybe" path]. Using recursion and a helper function [or two] allows both code paths to be followed:
val ls1 = ["duck", "goose", "swan", "gull"]
val ls2 = ["duck", "swan", "goose", "pigeon"]
fun checker (list1,list2) =
(* Zipping the two lists together creates
a list of pairs that can be searched
for "yes" values as the first part of the aux function.
It might be worth checking to see if
ListPair.zipEq is more suited to the
needs of a particular appliation. *)
let val zipped = ListPair.zip(list1, list2)
(* find_in_list is called if there is
no "yes" match. It recurses down
list2 with the string from list1
which did not return "yes". *)
fun find_in_list (x, xs) =
case xs
of [] => "no"
| x'::xs' =>
if x' = x
then "maybe"
else find_in_list (x, xs')
(* This function could be the main body
of checker, but instead it trampolines.
First it checks for "yes". Either appends
"yes" onto a recursive call to itself or
otherwise appends a call to find_in_list
onto a recursive call to itself.
The type checker wants an explicit type
for lop because the record is being accessed
with #1 and #2 *)
fun aux (lop : (string * string) list) =
case lop
of [] => []
| x'::xs' =>
if #1 (hd lop) = #2 (hd lop)
then "yes"::aux (tl lop)
else (find_in_list (#1 (hd lop), list2))::(aux (tl lop))
in aux(zipped) end
checker (ls1,ls2) (* returns ["yes", "maybe", "maybe", "no"] *)

SML "('a list * int) -> ('a list, boolean)"

So this is my question: i wanna make a function that takes a list and and int, it then recursively moves through the list, and if it finds an element in the list equal to the int, then it should return the entire list with the element removed, and a boolean indicating wether something was removed. this is what i got so far:
fun foo ([], n) = ([],false)
| foo ((x::xs), n) = if x = n
then (xs,true)
else ([x] # foo(xs,n),false);
my idea was to make the function cons the needed elements inside the tuple like this:
([x0] # [x1] # [x2] # [xs], true)
so is there any way to make this function? keep in mind that it has to stop once it hits the element equal to n, but still retain the rest of the list, and be able to return a boolean. run time is key.
Your current code is close to correct logically, but as you know it doesn't type-check because of [x] # foo (xs, n). foo returns a tuple, which can't be directly appended. Here's how to fix it:
fun foo ([], n) = ([], false)
| foo (x::xs, n) = if x = n
then (xs, true)
else let val (xs', tf) = foo (xs, n) in (x::xs', tf) end
The let is needed to extract the list from the tuple and find out if n was found in the tail of the list. Then we simply put the tuple back together with x consed back on to the front.

Less than function in SML

I've come across 2 confusing problems in SML and was hoping someone could help me out:
The first is a function which takes an element and a list and decides whether that element exists in the list or not, here is the code I've attempted to write:
fun member (e,L) = foldl (fn(a,b) => if (e = b) then true else false) false L;
But I get bool * 'a list --> bool but what I need is ''a * ''a list --> bool
As for the second, it also requires an element and a list but returns a list of elements less than the passed one. I'm not sure whether this should be done via map or foldr/foldl.
Any suggestions?
Thanks in advance :)
Regarding the first question, in fn (a, b) => ... a is the next element and b is the accumulator. Since you compare e with b, e is infered to have type bool. You should compare e with a, and never override b when it becomes true:
fun exists (e, L) =
foldl (fn (a, b) => e = a orelse b) false L
For the second question, you can use foldr/foldl to do so. It's similar to the first example; you start with empty list as the accumulator and prepend an element to it whenever that element is smaller than a threshold.
As a tradeoff, foldr gives you the right order but it isn't tail-recursive. On the other hand, foldl is tail-recursive but gives resulting lists in a reverse order.
to see if an element is in list or not try this:
fun elementExist(e, nil) = false
| elementExist(e, x::xs) = if e = x orelse elementExist(e, xs) then true else false;
for the second one to remove the existing element from the list:
fun elFromList(e, nil) = []
| elFromList(e, x::xs) = if e = x then elFromList(e, xs) else x::elFromList(e, xs);
Good Luck!!