Turning a list of Integers into a List of Colors - rgb

I have an image stored as a very large List Int and I would like to turn them into a List Color However remember that rgb requires 3 arguments and rgba requires 4. So let's try:
toColor : List Int -> List Color
toColor x =
if List.isEmpty x then
[]
else
List.append ( rgba <| List.take 4 x ) ( toColor <| List.drop 4 x )
This definition is recursive. We chomp 4 numbers, create an rgb color and append the results. However if x is List Int we cannot write this:
rgba <| List.take 4 x
Here is the kind of error we get. rgb is expecting three numbers and instead it gets a list
71| rgb <| List.take 4 x
^^^^^^^^^^^^^
(<|) is expecting the right argument to be a:
Int
But the right argument is:
List a
I wonder that taking out the first element of a List Int returns a Maybe Int
head : List a -> Maybe a
> head [1,2,3,4]
Just 1 : Maybe.Maybe number
Here is a modification of rgb which turns 3 Maybe Int into a Color. Now, reading the image data, I think rgba is necessary but I just add one more.
rgb' : Maybe Int -> Maybe Int -> Maybe Int -> Color
rgb' a b c =
case a of
Nothing -> rgb 0 0 0
Just a' -> case b of
Nothing -> rgb 0 0 0
Just b' -> case c of
Nothing -> rgb 0 0 0
Just c' -> rgb a' b' c'
this started when I was translating this d3js example to Elm and I noticed it used some features which aren't currently supported in Elm. In particular ctx.getImageData() since you can't import and image to Canvas. So this is part of my make-shift solution.

It seems to me that you're looking for a really clean way to
Collapse a List Int into a List (List Int), where each child list has at most 3 or 4 members if you want to do rgb or rgba.
Pass each List Int into a function that will convert it using rgb, handling the case where there aren't enough Ints in the final entry.
For the first step, you can write a function called groupList:
groupsOf : Int -> List a -> List (List a)
groupsOf size list =
let
group =
List.take size list
rest =
List.drop size list
in
if List.length group > 0 then
group :: groupsOf size rest
else
[]
You can also get this functionality by using the greedyGroupsOf function from the elm-community/list-extra package.
For the second step, it'll be much cleaner to pattern match on the structure of the list value itself rather than using List.head and matching on Maybe.
rgbFromList : List Int -> Color
rgbFromList values =
case values of
r::g::b::[] ->
rgb r g b
_ ->
rgb 0 0 0
The first case will be matched when there are exactly 3 entries in the list, and everything else will fall through to handing 0s to rgb.
You can put all of these things together by doing the following:
toColor : List Int -> List Color
toColor x =
x
|> groupsOf 3
|> List.map rgbFromList
Alternatively, if instead of ending up with rgb 0 0 0 for invalid colors you want to exclude them entirely, you can use the List.filterMap function to prune out things you don't want. We can change rgbFromList to look like
rgbFromList : List Int -> Maybe Color
rgbFromList values =
case values of
r::g::b::[] ->
Just <| rgb r g b
_ ->
Nothing
and then call it like
toColor : List Int -> List Color
toColor x =
x
|> groupsOf 3
|> List.filterMap rgbFromList
Please be advised that since the groupsOf function here as well as greedyGroupsOf in elm-community/list-extra is recursive, it will fail for very large lists.
Edit: for very large lists
For very large lists it's easy to get into trouble with recursion. Your best bet is to fold over the list and manage some intermediate state while you're folding:
groupsOf : Int -> List a -> List (List a)
groupsOf size list =
let
update next state =
if (List.length state.current) == size then
{ current = [next], output = state.current :: state.output }
else
{ state | current = state.current ++ [next] }
result =
List.foldl update { current = [], output = [] } list
in
List.reverse (result.current :: result.output)
This works by folding over the list, which is an iterative process rather than recursive, and building up groups one at a time. The last step reverses the list because it will be constructed in reverse order in order to cons instead of doing costly appends once the output list begins to grow large. I don't expect this to overflow the stack, but it is likely that it will be very slow. In my opinion, your best option to get the outcome you are looking for in a reasonable amount of time is to write the groupsOf function in JavaScript using a for loop and then pass the result in through a port.

This recursive implementation should work without building the stack, because Elm has tail call optimisation. Each step takes three ints from the original list, and appends them to the list of colors. Recursion stops and returns the list of colors, when there are less than three elements in the original list.
It uses rgb, but can be easily modified to take 4 elements from the list.
It also reverses the order, so you might need to combine it with List.reverse.
import Color exposing (rgb, Color)
listColors : List Int -> List Color
listColors =
listColors' []
listColors' : List Color -> List Int -> List Color
listColors' colors ints =
case ints of
r :: g :: b :: rest ->
listColors' (rgb r g b :: colors) rest
_ ->
colors

Related

Array manipulations in Ocaml

I am trying to do all combinations of an Array in Ocaml.
I am trying to do a recursive function that recives an array and its initial state need to be let a = [|0;0;0|] and i need to change it recursivly like in the first iteration needs to be a = [|1;0;0|] and the next one a = [|0;1;0|] and so on until it reaches a = [|1;1;1|] making all the possible combinations, so in this case needs to do 2^3 changes.
I know that im not been very explicit but its a bit hard to me to explain, but if someone could help me i would be grateful.
An array is a mutable data structure, so if you're going to mutate it in every recursive call, then the mutation will be taken in place. Basically, it means, that after 2^3 calls, the state of array will be the last combination. So, there is no point in doing this at all. A valid solution would be to create a function, that will take an initial array, and will return a list of all combinations. An even more efficient solution is to write a function, that will take another function, and applies it to all combinations (or fold over all combinations). This will allow you to save memory, as you don't need to store all the combinations.
The outline would be to implement the following interface:
type state
val zero : state
val next : state -> state option
val value : state -> int array
Where state will be a cursor, that will move through the space of combinations. It can be an integer or an integer array, or anything else. Once these functions are implemented you can easily implement your function as follows:
let fold_combinations f init =
let rec fold state x =
let x = f (value state) x in
match next state with
| None -> x
| Some state -> fold state x in
fold zero init
Finally, your example shows not all possible combinations or permutations, but all possible binary values of bit width equal to the length of the input array. If this is really a task that you're trying to solve, then you can just translate an integer into a binary representation. In that case, the good choice for the state would be int, and then next function is an increment, that will stop at 2^k-1, where k is the length of the initial state. And the value function will just translate an integer into the array of bits, where the n-th bit (element) can be determined as state land (1 lsl n). You can use Array.init to create a fresh new array every time, alternatively, you can just iterate over the existing array. This will be more efficient, but error-prone.
let combinaison f n =
let rec aux acc n =
if n=0 then List.iter f acc
else (
aux (List.map (fun l -> 0::l ) acc) (n-1);
aux (List.map (fun l -> 1::l ) acc) (n-1);
)
in
aux [[]] n
;;
Test
combinaison ( fun lx ->
let a=Array.of_list lx in
Array.iter ( fun x ->
Printf.printf "%d " x
) a ;
Printf.printf "\n"
) 3;;
0 0 0
1 0 0
0 1 0
1 1 0
0 0 1
1 0 1
0 1 1
1 1 1

Haskell iteration (not literally) over a list

I know I should be forgetting about iterating in functional languages, but I dont know how else to put forth my question.
If I have a list of integers arranged in ascending or descending order, and I have an arbitrary number that may or may not be present in the list, how can I loop over the list to find a number that is small than the given number and return that integer.
I just need to know how to go about it.
You could use find to find the first element matching a predicate you specify. Example:
find even [3,5,7,6,2,3,4]
Or, you could drop all the unwanted elements from the left:
dropWhile (not . even) [3,5,7,6,2,3,4]
(and possibly take the first element remaining, which has to be even).
Or, you could filter out unwanted elements
filter even [3,5,7,6,2,3,4]
Or, you could use recursion and code everything yourself.
You can recursively deconstruct the list with pattern matching:
searchList :: Int -> [Int] -> ???
searchList n [] = ???
searchList n (x:xs) = ???
You check whether x is the number you want, and if not you can call searchList n xs to search the rest of the list.
The normal way to do something like that would be with the library function foldr, but it would be better to understand how to do this with recursion first.
You can have "state" in a list iteration by using a fold - the state is passed from one iteration to the next in a function argument.
An example:
sup :: [Int] -> Int -> Int
sup xs y = go (head xs) xs
where
go s [] = s
go s (x:xs) = if x >= y then s else go x xs
Here s is the "state" -- it is the latest value in the list that is less than y.
Because you said the input list would never be empty, head xs is okay here.
This is almost what you want. Perhaps you can modify it to handle all of your conditions.

Creating sets of similar elements in a 2D array

I am trying to solve a problem that is based on a 2D array. This array contains different kinds of elements (from a total of 3 possible kinds). Lets assume the kind as X, Y, Z.
The array appears to be something like this. Note that it would always be completely filled. The diagram is for illustration.
7 | | | | | | |
6 | | | | | | |
5 | | | | | | |
4 | |X|Z|Y|X| |
3 | |Y|X|Y|Y|X|
2 |Y|Y|X|Z|Z|X|
1 |X|X|Y| |X|X|
0 | | | |Z| | |
0 1 2 3 4 5
I am trying to create sets of elements that are placed adjacent to each other. For example, set1 may comprise of elements of type X located at: (0,1), (1,1), (2,2), (2,3), (1,4). Similarly, set2 may comprise of elements of type Y located at: (3,4), (3,3), 4,3).
Problem: Given any point in the array, it must be capable of adding all elements to the appropriate set and ensuring that there are no two sets that contain the same element. Note that a set is only created if more than 2 adjacent elements of the same kind are encountered.
Moreover, if a certain subset of elements is removed, more elements are added to replace the removed ones. The array must then be re-iterated over to make new sets or modify the existing ones.
Solution: I implemented a recursive solution such that it would iterate over all the adjacent elements of, for example, element X (0,1). Then, while iterating over the 8 possible adjacent elements, it would call itself recursively whenever a type X occurred.
This kind of solution is too much brute-force and inefficient, especially in the case where some elements are replaced with new ones of possibly different types. In such a case, almost the whole array has to be re-iterated to make/modify sets and ensuring that no same element exists in more than one set.
Is there any algorithm to deal efficiently with this kind of problem? I need help with some ideas/suggestions or pseudo codes.
[EDIT 5/8/2013: Fixed time complexity. (O(a(n)) is essentially constant time!)]
In the following, by "connected component" I mean the set of all positions that are reachable from each other by a path that allows only horizontal, vertical or diagonal moves between neighbouring positions having the same kind of element. E.g. your example {(0,1), (1,1), (2,2), (2,3), (1,4)} is a connected component in your example input. Each position belongs to exactly one connected component.
We will build a union/find data structure that will be used to give every position (x, y) a numeric "label" having the property that if and only if any two positions (x, y) and (x', y') belong to the same component then they have the same label. In particular this data structure supports three operations:
set(x, y, i) will set the label for position (x, y) to i.
find(x, y) will return the label assigned to the position (x, y).
union(Z), for some set of labels Z, will combine all labels in Z into a single label k, in the sense that future calls to find(x, y) on any position (x, y) that previously had a label in Z will now return k. (In general k will be one of the labels already in Z, though this is not actually important.) union(Z) also returns the new "master" label, k.
If there are n = width * height positions in total, this can be done in O(n*a(n)) time, where a() is the extremely slow-growing inverse Ackermann function. For all practical input sizes, this is the same as O(n).
Notice that whenever two vertices are adjacent to each other, there are four possible cases:
One is above the other (connected by a vertical edge)
One is to the left of the other (connected by a horizontal edge)
One is above and to the left of the other (connected by a \ diagonal edge)
One is above and to the right of the other (connected by a / diagonal edge)
We can use the following pass to determine labels for each position (x, y):
Set nextLabel to 0.
For each row y in increasing order:
For each column x in increasing order:
Examine the W, NW, N and NE neighbours of (x, y). Let Z be the subset of these 4 neighbours that are of the same kind as (x, y).
If Z is the empty set, then we tentatively suppose that (x, y) starts a brand new component, so call set(x, y, nextLabel) and increment nextLabel.
Otherwise, call find(Z[i]) on each element of Z to find their labels, and call union() on this set of labels to combine them together. Assign the new label (the result of this union() call) to k, and then also call set(x, y, k) to add (x, y) to this component.
After this, calling find(x, y) on any position (x, y) effectively tells you which component it belongs to. If you want to be able to quickly answer queries of the form "Which positions belong to the connected component containing position (x, y)?" then create a hashtable of lists posInComp and make a second pass over the input array, appending each (x, y) to the list posInComp[find(x, y)]. This can all be done in linear time and space. Now to answer a query for some given position (x, y), simply call lab = find(x, y) to find that position's label, and then list the positions in posInComp[lab].
To deal with "too-small" components, just look at the size of posInComp[lab]. If it's 1 or 2, then (x, y) does not belong to any "large-enough" component.
Finally, all this work effectively takes linear time, so it will be lightning fast unless your input array is huge. So it's perfectly reasonable to recompute it from scratch after modifying the input array.
In your situation, I would rely, at least, on two different arrays:
Array1 (sets) -> all the sets and the associated list of points. Main indices: set names.
Array2 (setsDef) -> type of each set ("X", "Y" or "Z"). Main indices: type names.
It might be possible to create more supporting arrays like, for example, one including the minimum/maximum X/Y values for each set to speed up the analysis (although it would be pretty quick anyway, as shown below).
You are not mentioning any programming language, but I include a sample (C#) code because it is the best way to explain the point. Please, don't understand it as a suggestion of the best way to proceed (personally, I don't like Dictionaries/Lists too much; although think that do provide a good graphical way to show an algorithm, even for unexperienced C# users). This code only intends to show a data storage/retrieval approach; the best way to achieve the optimal performance would depend upon the target language and further issues (e.g., dataset size) and is something you have to take care of.
Dictionary<string, List<Point>> sets = new Dictionary<string, List<Point>>(); //All sets and the associated list of points
Dictionary<string, List<string>> setsDef = new Dictionary<string, List<string>>(); //Array indicating the type of information stored in each set (X or Y)
List<Point> temp0 = new List<Point>();
temp0.Add(new Point(0, 0));
temp0.Add(new Point(0, 1));
sets.Add("Set1", temp0);
List<String> tempX = new List<string>();
tempX.Add("Set1");
temp0 = new List<Point>();
temp0.Add(new Point(0, 2));
temp0.Add(new Point(1, 2));
sets.Add("Set2", temp0);
List<String> tempY = new List<string>();
tempY.Add("Set2");
setsDef.Add("X", tempX);
setsDef.Add("Y", tempY);
//-------- TEST
//I have a new Y value which is 2,2
Point targetPoint = new Point(2, 2);
string targetSet = "Y";
//I go through all the Y sets
List<string> targetSets = setsDef[targetSet];
bool alreadyThere = false;
Point candidatePoint;
string foundSet = "";
foreach (string set in targetSets) //Going through all the set names stored in setsDef for targetSet
{
List<Point> curPoints = sets[set];
foreach (Point point in curPoints) //Going through all the points in the given set
{
if (point == targetPoint)
{
//Already-stored point and thus the analysis will be stopped
alreadyThere = true;
break;
}
else if (isSurroundingPoint(point, targetPoint))
{
//A close point was found and thus the set where the targetPoint has to be stored
candidatePoint = point;
foundSet = set;
break;
}
}
if (alreadyThere || foundSet != "")
{
break;
}
}
if (!alreadyThere)
{
if (foundSet != "")
{
//Point added to an existing set
List<Point> curPoints = sets[foundSet];
curPoints.Add(targetPoint);
sets[foundSet] = curPoints;
}
else
{
//A new set has to be created
string newName = "New Set";
temp0 = new List<Point>();
temp0.Add(targetPoint);
sets.Add(newName, temp0);
targetSets.Add(newName);
setsDef[targetSet] = targetSets;
}
}
Where isSurroundingPoint is a function checking whether both points are close one to the other:
private bool isSurroundingPoint(Point point1, Point point2)
{
bool isSurrounding = false;
if (point1.X == point2.X || point1.X == point2.X + 1 || point1.X == point2.X - 1)
{
if (point1.Y == point2.Y || point1.Y == point2.Y + 1 || point1.Y == point2.Y - 1)
{
isSurrounding = true;
}
}
return isSurrounding;
}
You may want to check out region growing algorithms, which are used for image segmentation. These algorithms start from a seed pixel and grow a contiguous region where all the pixels in the region have some property.
In your case adjacent 'pixels' are in the same image segment if they have the same label (ie, kind of element X, Y or Z)
I wrote something to find objects of just one type for another SO question. The example below adds two more types. Any re-iteration would examine the whole list again. The idea is to process the list of points for each type separately. The function solve groups any connected points and removes them from the list before enumerating the next group. areConnected checks the relationship between the points' coordinates since we are only testing points of one type. In this generalized version, the types (a b c) could be anything (strings, numbers, tuples, etc.), as long as they match.
btw - here's a link to a JavaScript example of j_random_hacker's terrific algorithm: http://jsfiddle.net/groovy/fP5kP/
Haskell code:
import Data.List (elemIndices, delete)
example = ["xxyyyz"
,"xyyzzz"
,"yxxzzy"
,"yyxzxy"
,"xyzxyy"
,"xzxxzz"
,"xyzyyz"
,"xyzxyy"]
objects a b c ws = [("X",solve xs []),("Y",solve ys []),("Z",solve zs [])] where
mapIndexes s =
concatMap (\(y,xs)-> map (\x->(y,x)) xs) $ zip [0..] (map (elemIndices s) ws)
[xs,ys,zs] = map mapIndexes [a,b,c]
areConnected (y,x) (y',x') = abs (x-x') < 2 && abs (y-y') < 2
solve [] r = r
solve (x:xs) r =
let r' = solve' xs [x]
in solve (foldr delete xs r') (if null (drop 2 r') then r else r':r)
solve' vs r =
let ys = filter (\y -> any (areConnected y) r) vs
in if null ys then r else solve' (foldr delete vs ys) (ys ++ r)
Sample output:
*Main> objects 'x' 'y' 'z' example
[("X",[[(7,0),(6,0),(5,0),(4,0)]
,[(3,4),(5,2),(5,3),(4,3),(2,2),(3,2),(2,1),(0,1),(1,0),(0,0)]])
,("Y",[[(7,5),(6,4),(7,4),(6,3)],[(4,4),(4,5),(3,5),(2,5)]
,[(4,1),(3,0),(3,1),(0,4),(2,0),(0,3),(1,1),(1,2),(0,2)]])
,("Z",[[(5,5),(6,5),(5,4)]
,[(7,2),(6,2),(5,1),(4,2),(3,3),(1,3),(2,3),(2,4),(1,4),(1,5),(0,5)]])]
(0.02 secs, 1560072 bytes)

Data structure for keeping track of a game board in OCaml

I am fairly new to OCaml and I want to implement a game which is similar to four-in-a-line.
What I need is some data structure to keep the game state. The game board is a 4x4 square with a total of 16 tiles.
I am looking for a representation for this in OCaml that will make it easy and fast to retrieve (or do some operation on) all the elements in entire column, row or diagonal.
I will be doing minimax search on this game, which is why speed is important.
So far I have considered a one-dimensional list. The problem with a list is that its hard to figure out what elements belong to each row/column/diagonal, and then retrieve them with a List.map for example.
I thought about using Array.make 4 (Array.make 4 Empty);;. This is absolutely perfect when it comes to rows. Its easy to get them and do a pattern match on it. But it is a chore to do pattern matching on individual columns and diagonals.
What I would like to be able to do is have a function that takes a game board and returns a list of lists containing all the rows/columns/diagonals. I would then like to do, for example, match (rows,columns,diagonals) with (Empty, Empty, Empty, Empty) -> something.
Since length is fixed, prefer arrays over lists: they use less memory and are faster to read and write.
I'm afraid you will need to write a function to get diagonals, there is no simple pattern matching.
When you write "do some operation on [a diagonal]", I assume you're thinking about a function f that takes an array of length 4 storing the elements, for instance [|Empty;Empty;Empty;Empty|].
Maybe f could instead take as arguments the position p, and an array of indices inside the position:
f p [|x1,y1; x2,y2; x3,y3; x4,y4|] would extract the squares p.(x1).(y1) ... p.(x4).(y4). Then just pass different x's and y's to make f operate on row/columns/diagonals.
Once the code is working and you're turning to optimization, you might want to have a look at bitvectors:
if there are a lot of positions stored in the tree of you minmax search, reducing the memory footprint means more cache hits and faster execution. You might event want to encode a position in a single int yourself, but this is some tricky work, you don't want to do it too early.
Sometimes matching doesn't work. Here, I think you should try to use functions as much as possible, and then getting your cells row first or column first won't be that complex, and you could even move from one representation to the other by reversing the indices order.
If I use the following type:
type color = Red | Yellow;;
type cell = Empty | Color of color;;
type board = Array.make 4 (Array.make 4 Empty);;
and decide for column first, then the following functions will get me rows or columns:
let column (b: board) i j = b.(i).(j)
let row (b: board) i j = b.(j).(i)
For the diagonals, there are 2 sets of them, one going top-left toward down-right, and the other one in the other direction (top-right to bottom-left):
let ldiag (b: board) i j = b.((i + j) mod 4).(j)
let rdiag (b: board) i j = b.((i - j + 4) mod 4).(j)
Then I guess that checking a row, column, or diagonal is just a matter of checking the 4 cells of that line.
let check predicate linef k = predicate (linef b k 0) &&
predicate (linef b k 1) &&
predicate (linef b k 2) &&
predicate (linef b k 3)
then for instance, checking if there's a diagonal of red:
let has_line linef b color =
let cmp x = x = color in
let check k = check cmp linef b k in
check 0 || check 1 || check 2 || check 3
let has_ldiag b color = has_line ldiag b color
let has_rdiag b color = has_line rdiag b color
let has_red_diagonal b = has_ldiag b Red | has_rdiag b Red
Etc.
How about indexing your tiles with the corresponding coordinate? So, the elements on your one-d list would be of the form:
(int * int * ref tile)
Then you can filter rows / columns / diagonals like this:
Row n: (precondition: 0 <= n, u, v <= 3)
List.filter tiles (fun x -> match x with (u, v, _) -> u = n);;
Column n: (precondition: 0 <= n, u, v <= 3)
List.filter tiles (fun x -> match x with (u, v, _) -> v = n);;
Diagonal 1: (precondition: 0 <= u, v <= 3)
List.filter tiles (fun x -> match x with (u, v, _) -> u = v);;
Diagonal 2: (precondition: 0 <= u, v <= 3)
List.filter tiles (fun x -> match x with (u, v, _) -> u + v = 3);;
It should also be possible to index the tiles with just one integer (the index of the tile within the one-d list), but that would need some calculations in the filter function (given index, figure out the coordinate and then decide if it belongs to the desired row / column / diagonal).

Haskell - Array

I'm a newbie to Haskell, got stuck on a simple question:
aaa :: [[(Char, Float)]] -> Float -> [[(Char, Float)]]
aaa [[]] a = error "no indata"
aaa [[(a,b)]] c = [[(a, b/c)]]
aaa inD c = ??
How to make it work with more than 1 element in Array?
Ex: aaa [[('a',3)],[('b',4)],[('c',5)]] 4
the result: [[('a',0.75)],[('b',1)],[('c',1.25)]]
Any hint pls, thx!
You can define operations on lists as follows (I give you a simpler example that adds 1 to each list item)
f [] = []
f (head:tail) = (head + 1):(f tail)
I.e. head:tail represents a list; to be more specific, it represents the first list item (head) and the remaining list if we take the first item away (tail). Then, you usually apply your stuff to head and make a recursive call using tail.
Completing your example (without testing) this would yield:
aaa ([(a,b)]:tail) c = [(a, b/c)] : (aaa tail c)
One thing: You are dealing with a list and want to modify each element of the list in a specific way (but each element is transformed the same way). For such occasions, Haskell provides its intrinsic map function, which takes:
the function to transform a list items
the list of items
as parameters and returns the transformed list.
First of all, that [...] stuff denotes lists, not arrays; there is a fundamental difference between those two.
Try to think in terms of fmap :: Functor a => (a -> b) -> f a -> f b. This function takes another function and applies it over a data-structure. You could use it to implement your function. Here is a simple implementation. Try to understand it:
aaa l c = fmap (fmap (fmap (/c))) l

Resources