Created
January 7, 2020 19:15
-
-
Save loicginoux/edeb6eec7e9f51b42be23251b423280d to your computer and use it in GitHub Desktop.
# Daily Coding Problem: Problem #39 [Medium]
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Daily Coding Problem: Problem #39 [Medium] | |
# Conway's Game of Life takes place on an infinite two-dimensional board of square cells. Each cell is either dead or alive, and at each tick, the following rules apply: | |
# Any live cell with less than two live neighbours dies. | |
# Any live cell with two or three live neighbours remains living. | |
# Any live cell with more than three live neighbours dies. | |
# Any dead cell with exactly three live neighbours becomes a live cell. | |
# A cell neighbours another cell if it is horizontally, vertically, or diagonally adjacent. | |
# Implement Conway's Game of Life. It should be able to be initialized with a starting list of live cell coordinates and the number of steps it should run for. Once initialized, it should print out the board state at each step. Since it's an infinite board, print out only the relevant coordinates, i.e. from the top-leftmost live cell to bottom-rightmost live cell. | |
# You can represent a live cell with an asterisk (*) and a dead cell with a dot (.). | |
def find_limits | |
allX = @cells.keys | |
minX = allX.min | |
maxX = allX.max | |
allY = @cells.values.map(&:keys).inject [] {|arr, acu| acu.concat arr} | |
minY = allY.min | |
maxY = allY.max | |
[minX, maxX, minY, maxY] | |
end | |
def displayCells | |
minX, maxX, minY, maxY = find_limits() | |
lines = [] | |
line = " - " | |
(minX..maxX).each do |x| | |
line += " #{x} " | |
end | |
lines << line | |
(minY..maxY).each do |y| | |
line = "#{y} - " | |
(minX..maxX).each do |x| | |
if living?(x,y) | |
line += " 0 " | |
else | |
line += " . " | |
end | |
end | |
lines << line | |
end | |
lines.each do |l| | |
p l | |
end | |
end | |
def live_neighbours_count(x,y) | |
live = 0 | |
relative_neighbours = [ | |
[-1, -1], | |
[-1, 0], | |
[-1, 1], | |
[0, -1], | |
[0, 1], | |
[1, -1], | |
[1, 0], | |
[1, 1], | |
] | |
relative_neighbours.each do |r| | |
if living?(x+r[0], y+r[1]) | |
live += 1 | |
end | |
end | |
live | |
end | |
def living?(x, y) | |
@cells[x] && @cells[x][y] | |
end | |
def dies(x,y) | |
if living?(x, y) | |
# p "dies" | |
@new_cells[x].delete(y) | |
end | |
end | |
def born(x,y) | |
if !living?(x, y) | |
@new_cells[x] = {} if !@cells[x] | |
# p "born" | |
@new_cells[x][y] = true | |
end | |
end | |
def process | |
minX, maxX, minY, maxY = find_limits | |
# extends, new cells can appears at the frontier | |
minX -= 1 | |
minY -= 1 | |
maxX += 1 | |
maxY += 1 | |
@new_cells = @cells.dup | |
(minX..maxX).each do |x| | |
(minY..maxY).each do |y| | |
count = live_neighbours_count(x,y) | |
# p "check (#{x}, #{y}) - live count: #{count}" | |
if count < 2 || count > 3 || (count == 2 && living?(x,y)) | |
dies(x,y) | |
else count == 3 && !living?(x,y) | |
born(x, y) | |
end | |
end | |
end | |
@cells = @new_cells | |
end | |
def run(run_nb) | |
p "start" | |
displayCells() | |
(1..run_nb).each do |run| | |
p "run: #{run}" | |
p "display:" | |
process() | |
displayCells() | |
end | |
end | |
@cells = { | |
1 => { | |
1 => true, | |
2 => true, | |
3 => true | |
}, | |
2 => { | |
4 => true, | |
2 => true, | |
3 => true | |
}, | |
3 => { | |
4 => true, | |
2 => true, | |
3 => true | |
} | |
} | |
run(1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment