All Projects → zverok → ruby_as_apl

zverok / ruby_as_apl

Licence: other
Conway's game of life in one statement of idiomatic Ruby... ported from APL

Programming Languages

ruby
36898 projects - #4 most used programming language

This repository contains implementation of Conway's Game of Life in one Ruby statement.

It was inspired by (in)famous APL's one-line implementation and is a more-or-less straightforward port of it into idiomatic Ruby.

To port the algorithm, a small prototype library with APL-style Array were created—so, technically, it is not a one-statement implementation, but I still prefer to think about it as "one-statement" one, as the class implemented is of generic use (somewhat like Numo::NArray), and operations used are familiar to any Rubyist.

You can read an explanatory article in my blog, but here we'll just show an implementation:

require 'apl'

AA = APL::Ary

def life(current_gen)
  current_gen.wrap
    .product(AA[-1, 0, 1], &:hrotate)
    .product(AA[-1, 0, 1], &:vrotate)
    .flatten(1).reduce(&:+)
    .eq(AA[3, 4])
    .zip(AA[1, current_gen], &:&)
    .reduce(&:|)
    .unwrap
end

...and its usage:

def show(grid)
  # APL-style AA#values_at(aa) produces array of items from the first array, taken and shaped
  # using numbers from second array as indexes.
  puts AA[' ', '█'].values_at(grid)
end

glider = AA[1, 1, 1, 1, 0, 0, 0, 1, 0].reshape(3, 3)
grid = glider.take(-10, -10)

show grid.wrap
# ┌──────────┐
# │          │
# │          │
# │          │
# │          │
# │          │
# │          │
# │          │
# │       ███│
# │       █  │
# │        █ │
# └──────────┘


generations = [grid]
9.times { generations << life(generations.last) }

show AA[*generations]

# or, simpler, with 2.7's Enumerator#produce:

generations = Enumerator.produce(grid) { |cur| life(cur) }.take(10).map(&:wrap)
show AA[*generations]
# ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
# │          │ │          │ │          │ │          │ │          │ │          │ │          │ │          │ │          │ │          │
# │          │ │          │ │          │ │          │ │          │ │          │ │          │ │          │ │          │ │          │
# │          │ │          │ │          │ │          │ │          │ │          │ │          │ │          │ │          │ │          │
# │          │ │          │ │          │ │          │ │          │ │          │ │          │ │          │ │          │ │          │
# │          │ │          │ │          │ │          │ │          │ │          │ │          │ │          │ │          │ │      █   │
# │          │ │          │ │          │ │          │ │          │ │       █  │ │      ██  │ │      ██  │ │     ███  │ │     ██   │
# │          │ │        █ │ │       ██ │ │       ██ │ │      ███ │ │      ██  │ │      █ █ │ │     ██   │ │     █    │ │     █ █  │
# │       ███│ │       ██ │ │       █ █│ │      ██  │ │      █   │ │      █ █ │ │      █   │ │       █  │ │      █   │ │          │
# │       █  │ │       █ █│ │       █  │ │        █ │ │       █  │ │          │ │          │ │          │ │          │ │          │
# │        █ │ │          │ │          │ │          │ │          │ │          │ │          │ │          │ │          │ │          │
# └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].