First commit
This commit is contained in:
		
							
								
								
									
										87
									
								
								HELP.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								HELP.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | ||||
| # Help | ||||
|  | ||||
| ## Running the tests | ||||
|  | ||||
| To run the test suite, execute the following command: | ||||
|  | ||||
| ```bash | ||||
| stack test | ||||
| ``` | ||||
|  | ||||
| #### If you get an error message like this... | ||||
|  | ||||
| ``` | ||||
| No .cabal file found in directory | ||||
| ``` | ||||
|  | ||||
| or | ||||
|  | ||||
| ``` | ||||
| RedownloadInvalidResponse Request { | ||||
| ... | ||||
| } | ||||
|  "/home/username/.stack/build-plan/lts-xx.yy.yaml" (Response {responseStatus = Status {statusCode = 404, statusMessage = "Not Found"}, | ||||
| ``` | ||||
|  | ||||
| You are probably running an old stack version and need | ||||
| to upgrade it. Try running: | ||||
|  | ||||
| ```bash | ||||
| stack upgrade | ||||
| ``` | ||||
|  | ||||
| Or see other options for upgrading at [Stack documentation](https://docs.haskellstack.org/en/stable/install_and_upgrade/#upgrade). | ||||
|  | ||||
| #### Otherwise, if you get an error message like this... | ||||
|  | ||||
| ``` | ||||
| No compiler found, expected minor version match with... | ||||
| Try running "stack setup" to install the correct GHC... | ||||
| ``` | ||||
|  | ||||
| Just do as it says and it will download and install | ||||
| the correct compiler version: | ||||
|  | ||||
| ```bash | ||||
| stack setup | ||||
| ``` | ||||
|  | ||||
| If you want to play with your solution in GHCi, just run the command: | ||||
|  | ||||
| ```bash | ||||
| stack ghci | ||||
| ``` | ||||
|  | ||||
| ## Submitting your solution | ||||
|  | ||||
| You can submit your solution using the `exercism submit src/GameOfLife.hs package.yaml` command. | ||||
| This command will upload your solution to the Exercism website and print the solution page's URL. | ||||
|  | ||||
| It's possible to submit an incomplete solution which allows you to: | ||||
|  | ||||
| - See how others have completed the exercise | ||||
| - Request help from a mentor | ||||
|  | ||||
| ## Need to get help? | ||||
|  | ||||
| If you'd like help solving the exercise, check the following pages: | ||||
|  | ||||
| - The [Haskell track's documentation](https://exercism.org/docs/tracks/haskell) | ||||
| - The [Haskell track's programming category on the forum](https://forum.exercism.org/c/programming/haskell) | ||||
| - [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5) | ||||
| - The [Frequently Asked Questions](https://exercism.org/docs/using/faqs) | ||||
|  | ||||
| Should those resources not suffice, you could submit your (incomplete) solution to request mentoring. | ||||
|  | ||||
| ## Getting Started | ||||
|  | ||||
| Please refer to the [installation](https://exercism.io/tracks/haskell/installation) | ||||
| and [learning](https://exercism.io/tracks/haskell/learning) help pages. | ||||
|  | ||||
| ## Feedback, Issues, Pull Requests | ||||
|  | ||||
| The [exercism/haskell](https://github.com/exercism/haskell) repository on | ||||
| GitHub is the home for all of the Haskell exercises. | ||||
|  | ||||
| If you have feedback about an exercise, or want to help implementing a new | ||||
| one, head over there and create an issue.  We'll do our best to help you! | ||||
							
								
								
									
										36
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| # Game of Life | ||||
|  | ||||
| Welcome to Game of Life on Exercism's Haskell Track. | ||||
| If you need help running the tests or submitting your code, check out `HELP.md`. | ||||
|  | ||||
| ## Introduction | ||||
|  | ||||
| [Conway's Game of Life][game-of-life] is a fascinating cellular automaton created by the British mathematician John Horton Conway in 1970. | ||||
|  | ||||
| The game consists of a two-dimensional grid of cells that can either be "alive" or "dead." | ||||
|  | ||||
| After each generation, the cells interact with their eight neighbors via a set of rules, which define the new generation. | ||||
|  | ||||
| [game-of-life]: https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life | ||||
|  | ||||
| ## Instructions | ||||
|  | ||||
| After each generation, the cells interact with their eight neighbors, which are cells adjacent horizontally, vertically, or diagonally. | ||||
|  | ||||
| The following rules are applied to each cell: | ||||
|  | ||||
| - Any live cell with two or three live neighbors lives on. | ||||
| - Any dead cell with exactly three live neighbors becomes a live cell. | ||||
| - All other cells die or stay dead. | ||||
|  | ||||
| Given a matrix of 1s and 0s (corresponding to live and dead cells), apply the rules to each cell, and return the next generation. | ||||
|  | ||||
| ## Source | ||||
|  | ||||
| ### Created by | ||||
|  | ||||
| - @tofische | ||||
|  | ||||
| ### Based on | ||||
|  | ||||
| Wikipedia - https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life | ||||
							
								
								
									
										34
									
								
								game-of-life.cabal
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								game-of-life.cabal
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| cabal-version: 1.12 | ||||
|  | ||||
| -- This file has been generated from package.yaml by hpack version 0.37.0. | ||||
| -- | ||||
| -- see: https://github.com/sol/hpack | ||||
|  | ||||
| name:           game-of-life | ||||
| version:        1.0.0.0 | ||||
| build-type:     Simple | ||||
|  | ||||
| library | ||||
|   exposed-modules: | ||||
|       GameOfLife | ||||
|   other-modules: | ||||
|       Paths_game_of_life | ||||
|   hs-source-dirs: | ||||
|       src | ||||
|   ghc-options: -Wall | ||||
|   build-depends: | ||||
|       base | ||||
|   default-language: Haskell2010 | ||||
|  | ||||
| test-suite test | ||||
|   type: exitcode-stdio-1.0 | ||||
|   main-is: Tests.hs | ||||
|   other-modules: | ||||
|       Paths_game_of_life | ||||
|   hs-source-dirs: | ||||
|       test | ||||
|   build-depends: | ||||
|       base | ||||
|     , game-of-life | ||||
|     , hspec | ||||
|   default-language: Haskell2010 | ||||
							
								
								
									
										21
									
								
								package.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								package.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| name: game-of-life | ||||
| version: 1.0.0.0 | ||||
|  | ||||
| dependencies: | ||||
|   - base | ||||
|  | ||||
| library: | ||||
|   exposed-modules: GameOfLife | ||||
|   source-dirs: src | ||||
|   ghc-options: -Wall | ||||
|   # dependencies: | ||||
|   # - foo       # List here the packages you | ||||
|   # - bar       # want to use in your solution. | ||||
|  | ||||
| tests: | ||||
|   test: | ||||
|     main: Tests.hs | ||||
|     source-dirs: test | ||||
|     dependencies: | ||||
|       - game-of-life | ||||
|       - hspec | ||||
							
								
								
									
										59
									
								
								src/GameOfLife.hs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/GameOfLife.hs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| module GameOfLife (tick) where | ||||
|  | ||||
| type Grid = [[Int]] | ||||
|  | ||||
| -- Maps a function over every element in a grid | ||||
| gridMap :: (a -> b) -> [[a]] -> [[b]] | ||||
| gridMap f = map (map f) | ||||
|  | ||||
| -- Param 1: The current value of the cell | ||||
| -- Param 2: The number of living neighbors | ||||
| -- Return value: The next value of the cell | ||||
| nextIterHelper :: Int -> Int -> Int | ||||
| nextIterHelper 1 2 = 1 | ||||
| nextIterHelper 1 3 = 1 | ||||
| nextIterHelper 0 3 = 1 | ||||
| nextIterHelper _ _ = 0 | ||||
|  | ||||
| -- Returns the value of a specific cell in a grid - out-of-bounds is always zero | ||||
| cellVal :: Grid -> (Int, Int) -> Int | ||||
| cellVal grid (x,y) | ||||
| 	| x < 0 || y < 0 = 0 | ||||
| 	| y >= length (grid) || x >= length (grid!!0) = 0 | ||||
| 	| otherwise = (grid!!y)!!x | ||||
|  | ||||
| -- Given a tuple (representing the location of a cell), | ||||
| -- it returns a list of tuples that are the locations of the neighbors | ||||
| neighbors :: (Int, Int) -> [(Int, Int)] | ||||
| neighbors (x, y) = [(a,b) | a <- dx, b <- dy, a /= x || b /= y] | ||||
| 	where 	dx = [x-1..x+1] | ||||
| 		dy = [y-1..y+1] | ||||
|  | ||||
| -- Predicate - returns whether the cell is alive or not | ||||
| isAlive :: Grid -> (Int,Int) -> Bool | ||||
| isAlive grid tup = if (cellVal grid tup) == 1 then True else False | ||||
|  | ||||
| -- Filter function that takes a list of indexes in a grid, and only returns the ones | ||||
| -- where the cell value is 1 | ||||
| keepAliveCells :: Grid -> [(Int,Int)] -> [(Int,Int)] | ||||
| keepAliveCells grid tups = filter (isAlive grid) tups | ||||
|  | ||||
| -- Returns the number of alive neighbors of the given cell | ||||
| numAliveNeighbors :: Grid -> (Int,Int) -> Int | ||||
| numAliveNeighbors grid tup = (length . keepAliveCells grid . neighbors) tup | ||||
|  | ||||
| -- Given the grid and the location of a cell, returns the next value of the cell | ||||
| nextIter :: Grid -> (Int, Int) -> Int | ||||
| nextIter grid tup = nextIterHelper (cellVal grid tup) (numAliveNeighbors grid tup) | ||||
|  | ||||
| -- Returns a grid of all cell indices in the grid | ||||
| cellIndices :: Grid -> [[(Int,Int)]] | ||||
| cellIndices [[]] = [[]] | ||||
| cellIndices grid = [[(x,y) | x <- [0..xdim-1]] | y <- [0..ydim-1]]	 | ||||
| 	where 	xdim = length (grid!!0) | ||||
| 		ydim = length grid | ||||
|  | ||||
| tick :: Grid -> Grid | ||||
| tick [] = [] | ||||
| tick [[]] = [[]] | ||||
| tick grid = gridMap (nextIter grid) (cellIndices grid) | ||||
							
								
								
									
										1
									
								
								stack.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								stack.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| resolver: lts-20.18 | ||||
							
								
								
									
										12
									
								
								stack.yaml.lock
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								stack.yaml.lock
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| # This file was autogenerated by Stack. | ||||
| # You should not edit this file by hand. | ||||
| # For more information, please see the documentation at: | ||||
| #   https://docs.haskellstack.org/en/stable/lock_files | ||||
|  | ||||
| packages: [] | ||||
| snapshots: | ||||
| - completed: | ||||
|     sha256: 9fa4bece7acfac1fc7930c5d6e24606004b09e80aa0e52e9f68b148201008db9 | ||||
|     size: 649606 | ||||
|     url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/20/18.yaml | ||||
|   original: lts-20.18 | ||||
							
								
								
									
										125
									
								
								test/Tests.hs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								test/Tests.hs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,125 @@ | ||||
| {-# OPTIONS_GHC -fno-warn-type-defaults #-} | ||||
| {-# LANGUAGE RecordWildCards #-} | ||||
|  | ||||
| import Data.Foldable     (for_) | ||||
| import Test.Hspec        (Spec, describe, it, shouldBe) | ||||
| import Test.Hspec.Runner (configFailFast, defaultConfig, hspecWith) | ||||
|  | ||||
| import GameOfLife (tick) | ||||
|  | ||||
| main :: IO () | ||||
| main = hspecWith defaultConfig {configFailFast = True} specs | ||||
|  | ||||
| specs :: Spec | ||||
| specs = describe "tick" $ for_ cases test | ||||
|   where | ||||
|  | ||||
|     test Case{..} = it description assertion | ||||
|       where | ||||
|         assertion = tick matrix `shouldBe` expected | ||||
|  | ||||
| data Case = Case { description :: String | ||||
|                  , matrix      :: [[Int]] | ||||
|                  , expected    :: [[Int]] | ||||
|                  } | ||||
|  | ||||
| cases :: [Case] | ||||
| cases = [ Case { description = "Empty matrix" | ||||
|                , matrix      = [] | ||||
|                , expected    = [] | ||||
|                } | ||||
|         , Case { description = "Live cells with zero live neighbors die" | ||||
|                , matrix      = [ | ||||
|                                 [0, 0, 0], | ||||
|                                 [0, 1, 0], | ||||
|                                 [0, 0, 0] | ||||
|                                ] | ||||
|                , expected    = [ | ||||
|                                 [0, 0, 0], | ||||
|                                 [0, 0, 0], | ||||
|                                 [0, 0, 0] | ||||
|                                ] | ||||
|                } | ||||
|         , Case { description = "Live cells with only one live neighbor die" | ||||
|                , matrix      = [ | ||||
|                                 [0, 0, 0], | ||||
|                                 [0, 1, 0], | ||||
|                                 [0, 1, 0] | ||||
|                                ] | ||||
|                , expected    = [ | ||||
|                                 [0, 0, 0], | ||||
|                                 [0, 0, 0], | ||||
|                                 [0, 0, 0] | ||||
|                                ] | ||||
|                } | ||||
|         , Case { description = "Live cells with two live neighbors stay alive" | ||||
|                , matrix      = [ | ||||
|                                 [1, 0, 1], | ||||
|                                 [1, 0, 1], | ||||
|                                 [1, 0, 1] | ||||
|                                ] | ||||
|                , expected    = [ | ||||
|                                 [0, 0, 0], | ||||
|                                 [1, 0, 1], | ||||
|                                 [0, 0, 0] | ||||
|                                ] | ||||
|                } | ||||
|         , Case { description = "Live cells with three live neighbors stay alive" | ||||
|                , matrix      = [ | ||||
|                                 [0, 1, 0], | ||||
|                                 [1, 0, 0], | ||||
|                                 [1, 1, 0] | ||||
|                                ] | ||||
|                , expected    = [ | ||||
|                                 [0, 0, 0], | ||||
|                                 [1, 0, 0], | ||||
|                                 [1, 1, 0] | ||||
|                                ] | ||||
|                } | ||||
|         , Case { description = "Dead cells with three live neighbors become alive" | ||||
|                , matrix      = [ | ||||
|                                 [1, 1, 0], | ||||
|                                 [0, 0, 0], | ||||
|                                 [1, 0, 0] | ||||
|                                ] | ||||
|                , expected    = [ | ||||
|                                 [0, 0, 0], | ||||
|                                 [1, 1, 0], | ||||
|                                 [0, 0, 0] | ||||
|                                ] | ||||
|                } | ||||
|         , Case { description = "Live cells with four or more neighbors die" | ||||
|                , matrix      = [ | ||||
|                                 [1, 1, 1], | ||||
|                                 [1, 1, 1], | ||||
|                                 [1, 1, 1] | ||||
|                                ] | ||||
|                , expected    = [ | ||||
|                                 [1, 0, 1], | ||||
|                                 [0, 0, 0], | ||||
|                                 [1, 0, 1] | ||||
|                                ] | ||||
|                } | ||||
|         , Case { description = "Bigger matrix" | ||||
|                , matrix      = [ | ||||
|                                 [1, 1, 0, 1, 1, 0, 0, 0], | ||||
|                                 [1, 0, 1, 1, 0, 0, 0, 0], | ||||
|                                 [1, 1, 1, 0, 0, 1, 1, 1], | ||||
|                                 [0, 0, 0, 0, 0, 1, 1, 0], | ||||
|                                 [1, 0, 0, 0, 1, 1, 0, 0], | ||||
|                                 [1, 1, 0, 0, 0, 1, 1, 1], | ||||
|                                 [0, 0, 1, 0, 1, 0, 0, 1], | ||||
|                                 [1, 0, 0, 0, 0, 0, 1, 1] | ||||
|                                ] | ||||
|                , expected    = [ | ||||
|                                 [1, 1, 0, 1, 1, 0, 0, 0], | ||||
|                                 [0, 0, 0, 0, 0, 1, 1, 0], | ||||
|                                 [1, 0, 1, 1, 1, 1, 0, 1], | ||||
|                                 [1, 0, 0, 0, 0, 0, 0, 1], | ||||
|                                 [1, 1, 0, 0, 1, 0, 0, 1], | ||||
|                                 [1, 1, 0, 1, 0, 0, 0, 1], | ||||
|                                 [1, 0, 0, 0, 0, 0, 0, 0], | ||||
|                                 [0, 0, 0, 0, 0, 0, 1, 1] | ||||
|                                ] | ||||
|                } | ||||
|         ] | ||||
		Reference in New Issue
	
	Block a user