--Boundary-00 dwvGh1C3FtoFsb
Content-Type: Multipart/Mixed;
boundaryoundary-00 dwvGh1C3FtoFsb"
--Boundary-00 dwvGh1C3FtoFsb
Content-Type: text/plain;
charset tf-8"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
Here's my fairly straightforward, no bells-and-whistles solution.
Each state is represented as an Array of Strings. I originally just used
a String, and split() when needed, but keeping it as an Array makes it a
bit faster and does simplify the code in a few places.
transformer() builds a Proc that takes a neighborhood as its argument (as
an Array of Strings) and returns the transformed cell state (as a String).
A Hash could have been used instead of a Proc.
step() takes a state (as an Array of Strings), tacks [0,0] onto both ends,
and calls each_cons(3) to iterate through the neighborhoods, which are
passed to the transformer Proc.
$ ./cellular_automata.rb -r 110 -s 1 -n 15
X
XX
XXX
XX X
XXXXX
XX X
XXX XX
XX X XXX
XXXXXXX X
XX XXX
XXX XX X
XX X XXXXX
XXXXX XX X
XX X XXX XX
XXX XXXX X XXX
XX X XX XXXXX X
--
Jesse Merriman
jessemerriman / warpmail.net
http://www.jessemerriman.com/
--Boundary-00 dwvGh1C3FtoFsb
Content-Type: application/x-ruby;
name
ellular_automata.rb"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename
ellular_automata.rb"
#!/usr/bin/env ruby
# Ruby Quiz 134: Cellular Automata
require 'enumerator'
require 'getoptlong'
Draw :blank ' ', '0' ' ', '1' 'X' }
Edge 0, 0]
NeighborhoodSize
# Build a Proc that takes a neighborhood as its argument and returns the
# transformed cell state.
def transformer rule_num
rule ule_num.to_s 2
rule '0' * (2**NeighborhoodSize - rule.length) + rule).reverse.split(//)
lambda { |hood| rule[hood.join.to_i(2)] }
end
# Takes the current state and a transformation Proc, and returns the next
# state.
def step state, trans
new_state ]
(Edge + state + Edge).each_cons(NeighborhoodSize) do |hood|
new_state << trans[hood]
end
new_state
end
# Outputs the current state. The current step number and total step number are
# needed to calculate how far to indent.
def puts_state state, step, total_steps
puts Draw[:blank] * (total_steps - step) + state.map { |x| Draw[x] }.join
end
if __FILE__ $0
Opts etoptLong.new(
[ '--rule', '-r', GetoptLong::REQUIRED_ARGUMENT ],
[ '--state', '-s', GetoptLong::REQUIRED_ARGUMENT ],
[ '--steps', '-n', GetoptLong::REQUIRED_ARGUMENT ] )
# defaults
rule 10
state w{ 1 }
steps 0
Opts.each do |opt, arg|
case opt
when '--rule'; rule rg.to_i
when '--state'; state rg.split(//)
when '--steps'; steps rg.to_i
end
end
trans ransformer(rule)
puts_state state, 0, steps
steps.times do |s|
state tep(state, trans)
puts_state state, s+1, steps
end
end
--Boundary-00 dwvGh1C3FtoFsb--
--Boundary-00 dwvGh1C3FtoFsb--