Duplicate Elements in Array (SML) - list

I have the following list
L = [2, 4, 6, 8, 10]
and I am trying to write a function that duplicates each element in the list, so the end result would be
L = [2, 2, 4, 4, 6, 6, 10, 10]
where my function is
fun duplicateList(nil) = nil
| duplicateList([a]) = [a]
| duplicateList(L) =
let val copy = L
in hd(L)::hd(copy)::duplicateList(tl(L))
end;
But I keep getting an error that reads Error: syntax error: replacing END with EQUALOP
What does that mean and how can I avoid it?

You can write your function as follows
fun duplicateList nil = nil
| duplicateList (x::xs) = x :: x :: duplicateList xs;
This way you aren't making the copy and you only have to worry about two cases.

maybe you can do something like below:
val L = [2, 4, 6, 8, 10]
val D = foldr (fn (a, b) => a::a::b) [] L

Related

Haskell - Find first 0 in a 2 level nested list

Imagine you have a 2 dimensional list of lists like this:
[[1, 3, 2, 4, 5, 6, 9, 3], [3, 2, 4, 1, 6, 8, 7, 0, 9], ....]
I want to get the coordinate of the first 0 value of the array -> (1, 7).
I have tried using map and elemIndex.
Both elemIndex and map are quite unnecessary to solve this problem. You simply need to keep track of a set of beginning coordinates and modify it as you recursively transverse the list of lists.
Clearly, the value we're looking for can never be in an empty list, so that case will return Nothing.
If the first list in the list is empty, it also can't be there, so we go to the next list, incrementing the first coordinate and resetting the second to 0.
If that first list is not empty, we check to see if its first element is the one we're looking for. If it is, we can return the coordinates wrapped up with Just, and the recursion ends.
Otherwise, continue by incrementing the second coordinate and considering the remainder of the list of lists.
findCoords :: Eq a => (Int, Int) -> a -> [[a]] -> Maybe (Int, Int)
findCoords _ _ [] = Nothing
findCoords (i, _) v ([]:xs) = findCoords (i+1, 0) v xs
findCoords (i, j) v ((x:y):xs)
| v == x = Just (i, j)
| otherwise = findCoords (i, j+1) v (y:xs)
This requires manually passing (0, 0) when called. This can be cleaned up by using a local aux function.
findCoords :: Eq a => a -> [[a]] -> Maybe (Int, Int)
findCoords = aux (0, 0)
where
aux _ _ [] = Nothing
aux (i, _) v ([]:xs) = aux (i+1, 0) v xs
aux (i, j) v ((x:y):xs)
| v == x = Just (i, j)
| otherwise = aux (i, j+1) v (y:xs)
When you're trying to do something to a number of items, the place to start is to work out how to do that something to just one item. Then map your function across all of the items.
Let's pick this list: [3, 2, 4, 1, 6, 8, 7, 0, 9]
The type of elemIndex can be seen in GHCi by using :t.
:m Data.List -- load module
:t elemIndex -- show type
This returns elemIndex :: Eq a => a -> [a] -> Maybe Int
So, we give it a value and a list and it returns the index as a Maybe.
elemIndex 0 [3, 2, 4, 1, 6, 8, 7, 0, 9] -- returns Just 7
Perhaps we call this function f
f = elemIndex 0
Then we map this function across the list of lists.
result = map f lst
The biggest question is what you mean by the first value. If you have a list like [[1,2,3,0],[0,1,2,3]], which is the first value? That will inform how you process the results of the map.
The way that you handle a Maybe Int, is at the simplest level to match against the two value Just x and Nothing.
f :: Maybe Int -> String
f (Just x) = show x
f Nothing = "Nothing"
main = do
putStrLn $ f (Just 3)
putStrLn $ f (Nothing)
Using these ideas I wrote this code, which appears to do what is required. Having mapped elemIndex over the lists, I find the first matching list using findIndex. The function findIndex takes a predicate for Just x, returning True if so, and False for Nothing. Then it's just a case of matching with Just and Nothing to extract the result.
import Data.List
lst=[[1, 3, 2, 4, 5, 6, 9, 3], [3, 2, 4, 1, 6, 8, 7, 0, 9]]
f = elemIndex 0
pJust :: Maybe a -> Bool
pJust (Just x) = True
pJust Nothing = False
main = do
let results = map f lst
let location = findIndex pJust results
case location of
Just index -> do
let location2 = results !! index
case location2 of
Just index2 -> putStrLn $ "(" ++
show index ++ "," ++
show index2 ++ ")"
Nothing -> putStrLn "Search failed"
Nothing -> putStrLn "Search failed"

SML - Error: types of if branches do not agree

I am trying to code an SML function that returns an array of results in listViolations(L1, L2). I specifically want to cross reference each element with eachother O(n^2), and check to see if the selection conflicts with one another. To visualize: [[1, 2], [2, 3]] is option 1 and [[3, 2], [2, 1]] is option two. I would call listViolations like this: listViolations([[[1, 2], [2, 3]], [[3, 2], [2, 1]]]).
The plan of action would be to :
fun listViolations(L1, L2) =
if L1 = [] orelse L2 = []
then 0
else totalViolations(transitive_closure(hd(L1)),path(hd(L2)))::[] # listViolations(L1, tl(L2))::[] # listViolations(tl(L1), L2)::[];
Here I am checking the head of both lists, and passing on the tails of both recursively, in hopes of creating something like this: [3, 0 , 0].
Although I am getting this error when I declare the function:
stdIn:726.5-728.136 Error: types of if branches do not agree [overload conflict]
then branch: [int ty]
else branch: int list
in expression:
if (L1 = nil) orelse (L2 = nil)
then 0
else totalViolations (transitive_closure <exp>,path <exp>) ::
nil # listViolations <exp> :: <exp> # <exp>
I provided all my other functions below to show that there's nothing wrong with them, I just want to know if there's something im doing wrong. I know for a fact that
totalViolations(transitive_closure(hd(L1)),path(hd(L2)))
listViolations(L1, tl(L2))::[]
listViolations(tl(L1), L2)::[];
return integers. How do I make a list out of it and return it within this function? Thank you in advance.
//[1, 2] , [1, 2, 3] = 0
//[3, 2] , [1, 2, 3] = 1
fun violation(T, P) =
if indexOf(hd(T), P) < indexOf(hd(tl(T)), P) then 0
else 1;
//[[1, 2], [2, 3]] , [1, 2, 3] = 0
//[[3, 2], [2, 1]] , [1, 2, 3] = 2
fun totalViolations(TS, P) =
if TS = [] then 0
else violation(hd(TS), P) + totalViolations(tl(TS), P);
//[[1, 2],[2, 3]] -> [1, 2, 3]
fun path(L) =
if L = [] orelse L =[[]]
then []
else union(hd(L),path(tl(L)));
// [[1, 2],[2, 3]] -> [[1, 2],[2, 3], [1, 3]]
fun transitive_closure(L) = union(L, remove([], closure(L, L)));
Additional Code:
fun len(L) = if (L=nil) then 0 else 1+length(tl(L));
fun remove(x, L) =
if L = [] then []
else if x = hd(L) then remove(x, tl(L))
else hd(L)::remove(x, tl(L));
fun transitive(L1, L2) =
if len(L1) = 2 andalso len(L2) = 2 andalso tl(L1) = hd(L2)::[]
then hd(L1)::tl(L2)
else [];
fun closure(L1, L2) =
if (L1 = [[]] orelse L2 = [[]] orelse L1 = [] orelse L2 = [])
then [[]]
else if len(L1) = 1 andalso len(L2) = 1
then transitive(hd(L1), hd(L2))::[]
else
union( union(closure(tl(L1), L2), closure(L1, tl(L2))), transitive(hd(L1), hd(L2))::[]);
The then branch of your if is an int while the else branch is a list of ints. To form a list in the former, write [0] (which is just short for 0::[]). Also, the result of the recursive calls in the other branch is already expected to return a list, so the consing with [] is wrong, because it forms a list of lists.
More tips: never compare to the empty list, that will force the element type to be an equality type. Use the null predicate instead. Even better (and much more readable), avoid null, hd, and tail altogether and use pattern matching.

Haskell: How to show all elements in impair and pair indexes from a list?

It will need to get the next imput and output:
pospair [1, 3, 9, 2, 5, 7, 1, 11]
[1, 9, 5, 1]
posimpair [1, 3, 9, 2, 5, 7, 1, 11]
[3, 2, 7, 11]
This is the way to obtain the element on the specified index:
show_in_index::Ord a=>[a]->Int->a
show_in_index l n = l!!n
It shows a result like this:
*Main> show_in_index [1,4,2,7,9] 3
7
The most simple way to do this is using recursion:
pospair :: [a] -> [a]
pospair xs = aux xs [] True
where
aux [] acc _ = acc
aux (y:ys) acc True = aux ys (acc ++ [y]) False
aux (y:ys) acc False = aux ys acc True
Note how I use True or False value to keep track of what value to eliminate. If it's False, I don't include the value in acc (accumulator). If it's True, I include the value. Using the same idea, you can implement posimpair.
You could map the function for indexing
For pospair the following works:
map ([1, 3, 9, 2, 5, 7, 1, 11] !! ) [0,2..length [1, 3, 9, 2, 5, 7, 1, 11]-1]
For posimpair we only have to change the second list that is the one that holds the indexing numbers, previously we had the series of pairs and now we want the series of impairs, so instead of having 0,2,.. until the length of the list -1 we have to do it with 1,3,..until the length of the list-1.
map ([1, 3, 9, 2, 5, 7, 1, 11] !! ) [1,3..length [1, 3, 9, 2, 5, 7, 1, 11]-1]
The general implementation is
pospairs = map (list !!) [0,2..length list - 1]
posimpairs = map (list !!) [1,3..length list - 1]
I tested your example and works.

List of List in scala

I would like to know how can I create a List of List in the result of a reduce operation.
I've for example this lines
1,2,3,4
0,7,8,9
1,5,6,7
0,6,5,7
And I would like to get something like this
1, [[2,3,4],[5,6,7]]
0, [[7,8,9],[6,5,7]]
Thsi is my code
val parsedData = data.map { line =>
val parts = line.split(",")
val label = Integer.parseInt(parts(0))
(label, List(Integer.parseInt(parts(1)), Integer.parseInt(parts(2)), Integer.parseInt(parts(3)))
}
With this I get
1, [2,3,4]
0, [7,8,9]
1, [5,6,7]
0, [6,5,7]
But if I use a reduceByKey operation with a List.concat(_,_) I get one single List with all items concated.
parsedData.reduceByKey(List.concat(_,_))
I want a List of List, reduced by the Key.
Is there some other operation that i don't know?
Thanks a lot for your help!
Here is a working example:
val data = "1,2,3,4\n0,7,8,9\n1,5,6,7\n0,6,5,7".split("\n")
val parsedData = data.map{ line =>
val parts = line.split(",")
val label = Integer.parseInt(parts(0))
(label, List(Integer.parseInt(parts(1)), Integer.parseInt(parts(2)), Integer.parseInt(parts(3))))
}.toList
//parsedData: List[(Int, List[Int])] = List((1,List(2, 3, 4)), (0,List(7, 8, 9)), (1,List(5, 6, 7)), (0,List(6, 5, 7)))
parsedData.groupBy(_._1).mapValues(_.map(_._2))
// Map(1 -> List(List(2, 3, 4), List(5, 6, 7)), 0 -> List(List(7, 8, 9), List(6, 5, 7)))
I am not sure this is concat you are looking for.
Can you try with that:
parsedData.reduceByKey(_ :: _ :: Nil)
Which should literally create a new list with your elements inside

SML val 'a grupper = fn : int -> 'a list -> 'a list list

I wanna create a function that have the type int -> 'a list -> 'a list list
Function call:
grupper 2 [3, 1, 4, 1, 5, 9] shall return [[3, 1], [4, 1], [5, 9]]
grupper 4 [3, 1, 4, 1, 5, 9] shall return [[3, 1, 4, 1], [5, 9]]
grupper 42 [3, 1, 4, 1, 5, 9] shall return [[3, 1, 4, 1, 5, 9]].
I got this so far
fun grupper _ [] = []
| grupper n (x::xs) = if n > length(x::xs) then [x::xs]
else [List.take(x::xs, n)] # grupper (n) xs
some help please.
You should use both List.take and List.drop:
fun grupper _ [] = []
| grupper n xs = if n >= length xs then [xs]
else List.take(xs, n)::(grupper n (List.drop(xs, n)))