+1 (315) 557-6473 

Create Game of Life In Haskell Assignment Solution.


Instructions

Objective
Write a haskell assignment to create the game of life.

Requirements and Specifications

We are going to change the Game of Life to include colours. The colour of a new cell (a "child") will be a blend of the colours of its alive neighbours (its "parents").
Consider the following configuration where the dead cell in the lower left is to come alive, since it is surrounded by three neighbours:
![avg-1](assets/gol-average-example-1.png)
We will compute the color of the new child by averaging the red, green and blue values of its parents. In this example, this average makes the child grey:
![img2](assets/gol-average-example-2.png)
To implement this idea, we begin by defining a type of colors. A colour is a RGB (Red, Green, Blue) triple with values 0 - 255.
We will need to take the average of a list of numbers, and we can do this using a function.
Next, we can define our `blend` function by computing the averages of the RGB components of a list of colours .
We will need to redefine cells to carry not only their coordinate, but also a colour.
Using the standard functions `fromJust` and `lookup` (which will be explained in later lectures) we can easily get the colour of a cell (specified by a coordinate)in a grid.
We will also need to display our colors on the screen. Recall that in the original Game of Life we saw that we can use escape codes to clear the terminal or move the cursor.
Screenshots of output
create a program game of life in haskell
Source Code
-- setting the "warn-incomplete-patterns" flag asks GHC to warn you
-- about possible missing cases in pattern-matching definitions
{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
-- see https://wiki.haskell.org/Safe_Haskell
{-# LANGUAGE Safe #-}
module Assessed1 (checksum , step , bin2Bool , bool2Bin , notBin , andBin , orBin , deMorg1 , deMorg2 , deMorg3 , deMorg4 , equals , roots) where
import Types
---------------------------------------------------------------------------------
---------------- DO **NOT** MAKE ANY CHANGES ABOVE THIS LINE --------------------
---------------------------------------------------------------------------------
{- Question 1 -}
checksum :: Integral a => [a] -> Bool
-- returns true only if length = 8 and the element sum divides 11 exactly
checksum xs = length xs == 8 && sum xs `mod` 11 == 0
{- Question 2 -}
step :: Grid -> Grid
step [] = [] -- empty grid stays empty
step [x] = [] -- one element dies at next gen
step [x,y] = [] -- two elements die at next gen
step xs = getNewCells ++ (filter aliveDead xs)
    where
        -- apply rules to every list of neighbors
        aliveDead (pos, _) = let ns = liveNeighbours xs pos in
            -- < 2 or > 3 neighbors -> dies in next gen, otherwise dies
            length ns == 2 || length ns == 3
        -- min and max coordinates of grid
        minx = (minimum (fst <$> fst <$> xs)) - 1
        maxx = (maximum (fst <$> fst <$> xs)) + 1
        miny = (minimum (snd <$> fst <$> xs)) - 1
        maxy = (maximum (snd <$> fst <$> xs)) + 1
        -- get the colors of all the live neighbours of position pos
        getNeighbourColours pos = map (colourOf xs) (liveNeighbours xs pos)
        -- select dead cells that have 3 live neighbors and create new cell
        -- blending the colors of the live neighbors
        getNewCells =
            [((x,y), blend (getNeighbourColours (x,y))) | x <- [minx..maxx], y <- [miny..maxy], isDead (x,y) xs && length (liveNeighbours xs (x,y)) == 3]
-- The other Game of Life functions are in Types.hs to keep this file clean.
-- But life depends on step, so it needs to be here.
life :: Grid -> IO ()
life seed = f 0 seed
 where
  f n g = do
           terminalRender g
           putStrLn (show n)
           delayTenthSec 1
           f (n+1) (step g)
{- Question 3 -}
bin2Bool :: Binary -> Bool
bin2Bool Zero = False -- if Zero, convert to True
bin2Bool One = True -- if One, convert to False
bool2Bin :: Bool -> Binary
bool2Bin False = Zero -- if False, convert to Zero
bool2Bin True = One -- if True, convert to One
notBin :: Binary -> Binary
notBin Zero = One -- invert Zero to One
notBin One = Zero -- invert One to Zero
andBin :: Binary -> Binary -> Binary
andBin One One = One -- and returns One only if the two inputs are One
andBin _ _ = Zero -- in any other case returns Zero
orBin :: Binary -> Binary -> Binary
orBin Zero Zero = Zero -- or returns Zero only if the two inputs are Zero
orBin _ _ = One -- in any other case returns True
deMorg1 :: Binary -> Binary -> Binary
-- returns not (A || B)
deMorg1 a b = notBin (orBin a b)
deMorg2 :: Binary -> Binary -> Binary
-- (not A) && (not B)
deMorg2 a b = andBin (notBin a) (notBin b)
deMorg3 :: Binary -> Binary -> Binary
-- returns not (A && B)
deMorg3 a b = notBin (andBin a b)
deMorg4 :: Binary -> Binary -> Binary
-- returns (not A) || (not B)
deMorg4 a b = orBin (notBin a) (notBin b)
{- Question 4 -}
equals :: (Finite a, Eq b) => (a -> b) -> (a -> b) -> Bool
equals f g = (evalAllX f) == (evalAllX g)
    where
        -- get the minimum and maximum value for the bound type and enumerate
        -- all elements, then evaluate the function in all elements
        evalAllX fun = map fun (enumFromTo minBound maxBound)
{- Question 5 -}
roots :: (Finite a , Num b, Eq b) => (a -> b) -> [a]
-- evaluate all values and filter the ones that make f equal to zero
roots f = filter (\a -> f a == 0) (enumFromTo minBound maxBound)