Creating Arrays of permutations - algorithm

I have an array that looks like this
mainArray =>
[a] =>
[A]
[B]
[C]
[b] =>
[D]
[E]
[F]
[c] =>
[G]
[H]
[I]
I want to put these into an array like this:
secondArray =>
[0] => { [A], [D], [G] }
[1] => { [A], [E], [G] }
.
.
.
[n] => { [C], [F], [I] }
I am having trouble figuring out how to get the right number of elements in $secondArray that start with a certain element in { [A],[B], .. }. For example, how many start with [A].
This is what I think I have to do:
secondArray =>
[0] =>
[A]
secondArray =>
[0] =>
[A]
[D]
secondArray =>
[0] =>
[A]
[D]
[G]
secondArray =>
[0] =>
[A]
[D]
[G]
[1] =>
[A]
[D]
[H]
secondArray =>
[0] =>
[A]
[D]
[G]
[1] =>
[A]
[D]
[H]
[2] =>
[A]
[D]
[I]
secondArray =>
[0] =>
[A]
[D]
[G]
[1] =>
[A]
[D]
[H]
[2] =>
[A]
[D]
[I]
[3] =>
[A]
[E]
[G]
[4] =>
[A]
[E]
[H]
[5] =>
[A]
[E]
[I]
secondArray =>
[0] =>
[A]
[D]
[G]
[1] =>
[A]
[D]
[H]
[2] =>
[A]
[D]
[I]
[3] =>
[A]
[E]
[G]
[4] =>
[A]
[E]
[H]
[5] =>
[A]
[E]
[I]
[6] =>
[A]
[F]
[G]
[7] =>
[A]
[F]
[H]
[8] =>
[A]
[F]
[I]
and so on, but I can't really think of how to implement it...
Any help would be appreciated

You can generate the elements sequentially.
To implement the iterator:
-remember the array of input arrays, if there exists a next element.
and an array of indexes of the same length.
-if any input array is empty, the result set is empty and there is no next (first) element.
-initialise the array of indexes to all zeroes.
To get the next element:
-If you remember there is no next element, fail.
-compute the result:
--start with an empty result
--For each input array and its corresponding index
---Append input[index] to the result
-compute the next set of indexes:
--Iterate the indexes in reverse order. For each index
---Increment the index
---If the index now points past its corresponding input array
----Reset the index to zero
---Else
----Return the result, exiting the function.
-Remember there is no next element
-Return the result (last element).
If you do want all combinations at once, the code simplifies slightly:
-if any input array is empty, the result set is empty.
-initialise the array of indexes to all zeroes.
-compute the result and store in the result set.
-while not done generating results:
--Iterate the indexes in reverse order. For each index
---Increment the index
---If the index now points past its corresponding input array
----Reset the index to zero
---Else
----Compute the result from the current indexes
----Add the result to the result set
----Continue generating the results
--(all indexes were reset to zero) finish generating the results.
-return the result set.

In Ruby:
['A', 'B', 'C'].product(['D', 'E', 'F'])
# => [['A', 'D'], ['A', 'E']...
Array#product can accept multiple arrays.

Related

splitList Function in Haskell

In my homework, there is a question, I copied below.
Write a function splitList that gives all the ways to split a list of at least two elements in two non-empty parts. The type declaration is:
splitList :: [a] -> [([a],[a])]
The call splitList [1..4] should give:
Prelude> splitList [1..4]
[([1],[2,3,4]),([1,2],[3,4]),([1,2,3],[4])]
And here is the code I wrote:
splitList :: Eq a=> [a]->[([a],[a])]
splitList []=[([],[])]
splitList (x:xs) = [([x],xs)]++[(splitList xs)]
But it gives an error: Couldn't match expected type `([a], [a])' with actual type `[([a], [a])]'
splitList (x:xs) = [([x],xs)]++[(splitList xs)]
I made bold where the error highlighted.
The problem is that you wrap the splitList xs in another list, and thus you construct a value of type [[([a], [a])]]. You thus should replace this with:
splitList :: Eq a => [a] -> [([a], [a])]
splitList [] = [([],[])]
splitList (x:xs) = [([x],xs)] ++ splitList xs
or more elegant:
splitList :: Eq a => [a] -> [([a], [a])]
splitList [] = [([],[])]
splitList (x:xs) = ([x],xs) : splitList xs
This is however not sufficient, you will need to prepend the first item of the 2-tuples of splitList with x in. You can use map :: (a -> b) -> [a] -> [b] for this. This will thus look like:
splitList :: Eq a => [a] -> [([a], [a])]
splitList [] = [([],[])]
splitList (x:xs) = ([x],xs) : map … (splitList xs)
where … is still something you need to fill in yourself.
Note that your function here will also return a 2-tuple where the second list is empty. Based on the expected output, that is not the what you intend to do. You can define an extra clause like:
splitList :: Eq a => [a] -> [([a], [a])]
splitList [] = []
splitList x#[_] = [([], x)]
splitList (x:xs) = ([x],xs) : map … (splitList xs)
where … is still something you need to fill in yourself.

I would like to check if the comparison operator is true or false

So I know how to write a code to see if my list is sorted from smallest to biggest
isSorted :: (Ord a) => [a] -> Bool
isSorted [] = True
isSorted [x] = True
isSorted (x:y:xs) = x <= y && isSorted (y:xs)
But I would like to write a code that tells me if my list is sorted by the given comparison operator
for example
I wanna put in
sorted (<=) [1,2,2,4,5] == True
sorted (<) [1,2,2,4,5] == False
sorted (==) [1,2,2,2,3] == False
What would I have to do?
I would like to write a code that tells me if my list is sorted by the given comparison operator for example I wanna put in
isSorted function can be enhanced to receive a function, which compares two elements and that function can be called instead of <= in your example:
isSorted :: (a -> a -> Bool) -> [a] -> Bool
isSorted _ [] = True
isSorted _ [x] = True
isSorted comparator (x:y:xs) = comparator x y && isSorted comparator (y:xs)
So the function is going to be called as:
isSorted (<) [1, 2, 3]
isSorted (>=) [3, 2, 1]
Calling it with (==) will just compare if the elements are the same in the list.
The idea can be to parameterize the comparison. Now you use <=, but we can replace it with an f, we pass as a parameter:
isSorted :: (a -> a -> Bool) -> [a] -> Bool
isSorted _ [] = True
isSorted _ [x] = True
isSorted f (x:y:xs) = f x y && isSorted f (y:xs)
We can however improve the following code by using zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] and and :: [Bool] -> Bool:
isSorted :: (a -> a -> Bool) -> [a] -> Bool
isSorted _ [] = True
isSorted f xs#(_:xs2) = and(zipWith f xs xs2)
The isSorted thus takes a predicate that works with two as, and we check if the predicate holds for every item, and its next item. You can thus write more advanced predicates that do not necessary encapsulate an order relation.

How do I count one list against another, in O(n*log(n))?

I am looking for a function that can efficiently count, for each element in one list, its occurrences in another list. It should return a sorted list of element/count tuples. Here's the specification:
countList :: Ord a => [a] -> [a] -> [(a, Integer)]
countList ['a', 'b', 'c', 'b', 'b'] ['a', 'b', 'x']
== [('a', 1), ('b', 3), ('x', 0)]
length (countList xs ys) == length ys
A naive implementation would be:
countList xs = sort . map (id &&& length . (\ y -> filter (== y) xs))
This is O(n^2). However, since we have Ord a, this could be made a bit faster using a better strategy. We might sort both lists first, and then compare them in a "ladder-climbing" fasion.
For example, here are the two lists sorted. If I were doing it imperatively, I would use two pointers pointing towards the first element in each list:
i
|
xs = ['a', 'b', 'b', 'b', 'c']
ys = ['a', 'b', 'x']
|
j
Then increase i when xs !! i == ys !! j, meanwhile adding one to the counter at position j. When i encounters a new element, find it in ys by increasing j, and then repeat the previous step. This algorithm is O(n*log(n)).
But I can't find a way to achieve the same complexity in a purely functional way, nor did I find any existing function that can achieve what I want. How should I do this in Haskell?
If the 2nd list does not have duplicates, and the 1st list is longer, you may avoid sorting the first list by using Data.Map. This will achieve an n1 log n2 complexity:
import Data.Map (fromList, toList, adjust)
countList :: Ord a => [a] -> [a] -> [(a, Int)]
countList l r = toList $ foldr (adjust (+1)) (fromList . zip r $ repeat 0) l
I think this accomplishes what you're looking for:
import Data.List (sort)
countList :: Ord a => [a] -> [a] -> [(a, Int)]
countList l1 l2 = countList' (sort l1) (sort l2)
where countList' _ [] = []
countList' xs (y:ys) = let xs' = dropWhile (< y) xs
(a,b) = span (== y) xs'
in (y, length a) : countList' b ys
main = print $ countList ['a', 'b', 'c', 'b', 'b'] ['a', 'b', 'x']

Sorting algorithm in Haskell

I am trying to implement a very trivial sorting algorithm in Haskell. It compiles but keeps giving me incorrect outputs.
Here is the code
import Data.List
minimum' :: (Ord a) => [a] -> a
minimum' (x:xs) = foldr (\ x y -> if x <= y then x else y) x xs
qsrt :: (Ord a) => [a] -> [a]
qsrt [] = []
qsrt l#(x:xs) = minimum' l : qsrt xs
Any thoughts?
The logic error is that qsrt takes the minimum element of l and then skips x, but x would only be the minimum element of l by accident so you're usually skipping the wrong element.
Just as an addendum to Rein Henrichs's answer, I managed to craft a correct version of the above using a filter.
import Data.List
minimum' :: (Ord a) => [a] -> a
minimum' (x:xs) = foldl' (\ x y -> if x <= y then x else y) x xs
srt :: (Ord a) => [a] -> [a]
srt [] = []
srt l = ml : srt (delete ml l)
where ml = minimum' l

Sort one list by the order of another list

I need to sort one list by the order of another, but I don't know how it can be done.
For example: I could have a list a similar to:
[C, B, G, E]
And a list b (that sets the order):
[A, B, C, D, E, F, G, ...]
(Just as example, these aren't the actual values though)
Then, list a should be sorted the same way as List b and thus become sorted to:
[B, C, E, G]
How to do this sorting by the order of another list?
If I understand, one of the lists give the relative order of all the elements of the other list. Ie:
> sortWithOrder [5,1,2,3,4] [1,2,3,4,5,5,4,3,2,1]
[5,5,1,1,2,2,3,3,4,4]
This piece of code should work :
module SortWithOrder where
import qualified Data.Map.Strict as M
import Data.List
import Data.Ord
sortWithOrder :: Ord a
=> [a] -- order list
-> [a] -- source list
-> [a]
sortWithOrder order = sortBy (comparing getOrder)
where
getOrder k = M.findWithDefault (-1) k ordermap
ordermap = M.fromList (zip order [0..])
Edit: a more efficient solution is to use sortOn, like this:
sortWithOrder order = sortOn getOrder
You could also map the order to the list and sort it:
Prelude> let order = zip ["A", "B", "C", "D", "E", "F", "G"] [0..]
Prelude> let myList = ["C", "B", "G", "E"]
Prelude> import Data.List (sort)
Prelude> map snd . sort . map (\x -> (lookup x order, x)) $ myList
["B","C","E","G"]
Thus we can define this function as
sortAlong :: Eq b => [b] -> [b] -> [b]
sortAlong order = map snd . sortBy (comparing fst) . map (\x -> (lookup x z, x))
where
z = zip order [0..]
An Ord constraint allows the more efficient route through Map but this version needs just Eq:
> sortAlong "ABCDEFG" "CBGE"
"BCEG"

Resources