Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning a list of every possible coordinate in a grid of that width and height

So I am writing a function allCoords that returns a list of every possible coordinate in a grid of width w and height h Both width and height must be non-negative integers in order to return a sensible result.

Example: allCoords 3 2 should return [(0,0),(0,1),(0,2),(1,0),(1,1),(1,2)]

This is all I've got so far but I don't know how to even start writing the function

type GridCoord = (Int, Int)

allCoords :: Int -> Int -> [GridCoord]
like image 344
Asher Kore Avatar asked Sep 18 '20 12:09

Asher Kore


3 Answers

You could do that using a list comprehension.

[ (x,y) | x <- [0..1], y <- [0..2] ]

Will give the list in your example.

Your function would then need to be defined as:

type GridCoord = (Int, Int)

allCoords :: Int -> Int -> [GridCoord]
allCoords height width = [ (x,y) | x <- [0..width-1], y <- [0..height-1] ]
like image 118
heijp06 Avatar answered Oct 16 '22 19:10

heijp06


The range function does that.

import Data.Ix
allCoords h w = range ((0,0), (w,h))
like image 45
Daniel Wagner Avatar answered Oct 16 '22 20:10

Daniel Wagner


We can make use of the Functor and Applicative instance of a list to generate this with:

allCoords :: (Num a, Enum a, Num b, Enum b) => a -> b -> [(a, b)]
allCoords h w = (,) <$> [0 .. h-1] <*> [0 .. w-1]

Here (,) <$> [0 .. h-1] will produce a list of functions b -> (a, b) where the first item of the tuple is already filled in. With the TupleSections enabled, this list is equivalent to [(0,), (1,), …, (w-1,)].

Then the (<*>) function will take a function from this list, and for each such function call it on each value in the list [0 .. w-1], thus constructing 2-tuples.

For example:

Prelude> allCoords 3 4
[(0,0),(0,1),(0,2),(0,3),(1,0),(1,1),(1,2),(1,3),(2,0),(2,1),(2,2),(2,3)]
like image 2
Willem Van Onsem Avatar answered Oct 16 '22 19:10

Willem Van Onsem