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