List multiplication with nested lists - list

Consider the list of lists
thisList = [[1], [1, 1], [1, 1, 1]]
how could I multiple thisList so that it would produce another list
anotherList = [[1], [2, 2], [3, 3, 3]]
I have made the function
reps = [1] : map (\ns -> head ns:ns) reps
which produces thisList
Thanks for any help

You could do:
zipWith (\x -> map (const x)) [1..] thisList
Example usage:
Prelude> let thisList = [[1], [1,1], [1,1,1]]
Prelude> zipWith (\x -> map (const x)) [1..] thisList
[[1],[2,2],[3,3,3]]
Or simpler:
zipWith (map . const) [1..] thisList
It's quite easy. zipWith f as bs is equivalent to map (uncurry f) $ zip as bs. So we have:
zip [1..] thisList == [(1, [1]), (2, [1,1,]), (3, [1,1,1])]
Then we apply f to each pair and so:
map (const 1) [1] == [const 1 1] == [1]
map (const 2) [1,1] == [const 2 1, const 2 1] == [2,2]
map (const 3) [1,1,1] == [const 3 1, const 3 1, const 3 1] == [3,3,3]
If you meant that a sublist of length n should be replaced by [n, n, ..., n] of length n, as in:
thisList = [[1, 1], [1], [1], [1, 1, 1]]
result = [[2,2], [1], [1], [3,3,3]]
then you have to change approach:
map (\xs -> let len = length xs in replicate len len) thisList
Example:
Prelude> let thisList = [[1, 1], [1], [1], [1, 1, 1]]
Prelude> map (\xs -> let len = length xs in replicate len len) thisList
[[2,2],[1],[1],[3,3,3]]

Related

Reversing a list in SML

fun reverse ( [] ) = ( [] )
| reverse (x::xs) = reverse (xs) :: [x]
why my this function of reversing a list is not working
Your function has type 'a list -> 'a list. :: has type 'a -> 'a list -> 'a list. Thus you can't pass the result of calling reverse as the first argument to ::.
You could use # as suggested by JRose because that has type 'a list -> 'a list -> 'a list and will concatenate the two lists but that is inefficient compared to ::. # is O(n). Using it makes reverse have O(n^2) runtime efficiency.
Instead, let's use a tail-recursive helper function to build up an accumulator list in reverse order using ::, then return that. Because :: is O(1), this has O(n) runtime efficiency which is much better.
fun reverse lst =
let
fun aux [] acc = acc
| aux (x::xs) acc = aux xs (x :: acc)
in
aux lst []
end
Consider reversing [1, 2, 3]:
reverse [1, 2, 3]
aux [1, 2, 3] []
aux [2, 3] [1]
aux [3] [2, 1]
aux [] [3, 2, 1]
[3, 2, 1]
Further reading on the efficiency of # and ::. The link talks about OCaml, but the core principles are the same in SML.

Turn adjacency list into tuple array Haskell

Let's say I have the following input:
[(0, [1, 2]) , (2, [3, 4]) , (4, [])
This is an adjacency list and I want to convert it as such:
[(0,1), (0,2), (2,3), (2, 4)] -- notice how there is no 4 mapping to anything
Here is what I have so far:
conv :: [(Int, [Int])] -> [(Int, Int)]
conv adj = map fn adj -- mapping (0, [1, 2]) should give me [(0, 1), (0, 2)]
fn:: (Int, [Int]) -> [(Int, Int)]
fn (rt, list) = -- somehow perform [(rt, l[0]), (rt, l[1]) ...]
List comprehension can do the trick:
conv :: [(a, [b])] -> [(a, b)]
conv xys = [(x, y) | (x, ys) <- xys, y <- ys ]
Or we can use concatMap here:
conv :: Foldable f => f (a, [b]) -> [(a, b)]
conv = concatMap (uncurry (map . (,)))
Here the inner function uncurry (map . (,)) takes a tuple (x, ys) and thus performs a map (x,): the uncurry basically unpacks the tuple (x, ys), and calls (map . (,)) x ys, so that means that we obtain (map (x,)) ys. The above syntax uses the TupleSections extension, but we do not need to activate that extension in the real program, since we never write such syntax. Your fn function you defined is thus equivalent to uncurry (map . (,)).
We thus use this function in a concatMap that will pass the 2-tuples, and concatenate the lists these individual tuples create.
or we can use the "bind" >>= :: Monad m => m a -> (a -> m b) -> m b function:
conv :: Monad m => m (a, m b) -> m (a, b)
conv = (=<<) (\(x, ys) -> ys >>= return . (x,))
or shorter:
conv :: Monad m => m (a, m b) -> m (a, b)
conv = (=<<) (uncurry (fmap . (,)))
the nice thing about the latter is that it also works with Maybes, etc. For example:
Prelude> conv [(0, [1, 2]) , (2, [3, 4]) , (4, [])]
[(0,1),(0,2),(2,3),(2,4)]
Prelude> conv Nothing
Nothing
Prelude> conv (Just (3, Nothing))
Nothing
Prelude> conv (Just (3, Just 2))
Just (3,2)
Taking advantage of instance Traversable ((,) a), we have this remarkably short (and remarkably inscrutable) solution:
conv :: [(Int, [Int])] -> [(Int, Int)]
conv = (sequence =<<)
The most general type of (sequence =<<) is (Monad m, Traversable t) => m (t (m a)) -> m (t a).

Haskell - separate a list of pairs in two lists using fold

So, I am given a list containing tuples and I need to break it down into two lists, the first list containing the elements with odd index and the second list containing the elements with even index, must be done using fold, here is my attempt:
breakList :: [(Integer, Integer)] -> [[(Integer, Integer)]]
breakList [] = [[], []]
breakList xxs#(x:xs) = foldl (\ acc y -> if length (acc !! 0) < length (acc !! 1) then y : (acc !! 0) else y : (acc !! 1) ) [[], []] xxs
Error I am getting:
Couldn't match type '(Integer, Integer)'
with '[(Integer, Integer)]'
Expected type: [[(Integer, Integer)]]
when hovering over y : (acc !! 1) and y : (acc !! 0)
Example:
Input:
ex1 = [ (2, 2), (1, 3), (2, 3), (2, 4), (3, 5), (0, 2), (2, 1), (1, 4)
, (2, 0), (1, 2), (3, 1), (1, 0)]
Output
breakList ex1
== ( [(2,2),(2,3),(3,5),(2,1),(2,0),(3,1)] , [(1,3),(2,4),(0,2),(1,4),(1,2),(1,0)])
The standard trick here, as hinted at by Willem in the comments, which I first saw few years back on SO in an (F# or Ocaml) answer by [user:Ed'ka], is
evenodds :: [a] -> ([a], [a])
evenodds xs = foldr g ([],[]) xs
where
g x ~(as,bs) = (bs,x:as)
or
oddevens :: [a] -> ([a], [a])
oddevens xs = foldr g ([],[]) xs
where
g x ~(bs,as) = (x:as,bs)
What are odd positions from here, are even positions from the position one notch further on the list.
The tilde ~ introduces a lazy pattern so that the function is properly lazy in its operations.
Note that you want to split a list into two lists of a pair, so the return type should be
([(Integer, Integer)], [(Integer, Integer)])
not
[[(Integer, Integer)]]
and access the element of pair, you can use fst and snd instead of through index, and finally, use foldl will return the resulted list in reversed order, it can be fixed use foldr instead. The correction look like:
breakList :: [(Integer, Integer)]->([(Integer, Integer)], [(Integer, Integer)])
breakList xxs = foldr (\y acc-> if length (fst acc) < length (snd acc)
then (y:(fst acc), snd acc)
else (fst acc, y:(snd acc)) ) ([], []) xxs

Consecutive pairs from list in haskell

How can I get a list of consecutive pairs (tuples) from a list without recursion ?
For example : [1, 2, 3, 4] would be [(1, 2), (2, 3), (3, 4)]
\xs -> zip xs $ tail xs or zip <*> tail.

sml foldl explanation/trace

I'm trying to figure this out for some time but I'm not successful.
How is following function (powerset) proceeding in detail, taking the example input argument of [1,2,3]?
Thank you much for help.
fun ps L = foldl (fn (x,tl) => tl # map (fn xs => x::xs) tl) [[]] L;
To use the function correctly, you have to assume there is no duplication in input lists.
The function can be understood as follows:
We start with an accumulator which is a set of sets only consisting of an empty set ([[]]).
In each step, we take every set in the accumulator, add the current element x to them and add these results to the accumulator.
The final result is a set of all possible sets of n elements i.e. powerset.
To be easily express traces, let's create an auxiliary function f
fun f (x, tl) = tl # map (fn xs => x::xs) tl
Now we have a trace for [1, 2, 3]:
ps [1, 2, 3]
~> foldl f [[]] [1, 2, 3] (* Step 1 *)
~> foldl f (f (1, [[]])) [2, 3]
~> foldl f ([[]] # map (fn xs => 1::xs) [[]]) [2, 3]
~> foldl f [[], [1]] [2, 3] (* Step 2 *)
~> foldl f (f (2, [[], [1]])) [3]
~> foldl f ([[], [1]] # map (fn xs => 2::xs) [[], [1]]) [3]
~> foldl f [[], [1], [2], [2, 1]] [3] (* Step 3 *)
~> foldl f (f (3, [[], [1], [2], [2, 1]])) []
~> foldl f ([[], [1], [2], [2, 1]] # map (fn xs => 3::xs) [[], [1], [2], [2, 1]]) []
~> foldl f [[], [1], [2], [2, 1], [3], [3, 1], [3, 2], [3, 2, 1]] [] (* Step 4 *)
~> [[], [1], [2], [2, 1], [3], [3, 1], [3, 2], [3, 2, 1]] (* Final result *)