Created
December 11, 2013 23:35
-
-
Save johntyree/7920541 to your computer and use it in GitHub Desktop.
This file contains 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
// GistID: 7920541 | |
// | |
// | |
// In this exercise you should get familiar with closures and | |
// implement an elementary cellular automaton (CA) | |
// [http://en.wikipedia.org/wiki/Elementary_cellular_automaton]. Read | |
// the article before proceeding. Then study closures from | |
// https://developer.mozilla.org/en/JavaScript/Guide/Closures and make | |
// sure you understand "Emulating private methods with closures" part | |
// - the following code will apply this pattern. | |
// | |
// Now when you understand what cellular automata and closures are, | |
// you can take a look at the code below. There are three public methods and a | |
// method you should implement. Init function of the closure takes | |
// two arguments: state is an array of integers presenting the initial state of | |
// the machine, rule is rulenumber used to define the behavior of the | |
// automaton (see | |
// http://en.wikipedia.org/wiki/Elementary_cellular_automaton#The_numbering_system). | |
// In this exercise, the state array of CA is not infinite | |
// long. Instead, it is a 'cycle' of length state.length. This means | |
// that state[0] and state[state.length -1] are neigbours of each | |
// others. | |
// | |
// nextState function, given in the template, calculates the next | |
// generation of the automaton. nextState calls newBit function that | |
// you should implement. | |
// | |
// newBit is the function you should implement. It gets an index as an | |
// argument and returns if the bit in that index should be turned on | |
// or off in the next offspring of the CA. This can be calculated | |
// based on the rule-number and the current state. See next to | |
// understand how nextBit is used. | |
// | |
// Think how you can test your program. NG will test with some unit | |
// tests and therefore assumes that you don't change the function | |
// signatures. You can integrate your CA to a custom Html to learn how | |
// to do this and to test your program locally. Think what kind of | |
// page you would like to have - how to visualize the behavior of the | |
// CA and how to select the initial state. You can also use FireBug | |
// for testing. You are asked to submit a html document that we hope | |
// you have used to test your program. Testruns can also be found from | |
// here: http://www.wolframalpha.com/input/?i=rule+30 You can change | |
// the rule number in the url to get the behavior of different rules. | |
function p(s) { | |
console.log(s); | |
} | |
function dbg(s) { | |
// p(s); | |
} | |
function makeCA() { | |
var state = [], rule = 0; | |
function index_to_neighborhood(index) { | |
var neighborhood = ""; | |
dbg("For index: " + index); | |
for (var i = -1; i < 2; i++) { | |
// Compute index, wrapping left and right | |
idx = (index + i + state.length) % state.length; | |
dbg("idx is " + String(idx)); | |
// neighborhood 0, 1, 2 = left, center, right | |
neighborhood += state[idx]; | |
} | |
dbg("neighborhood is: " + neighborhood); | |
return neighborhood; | |
} | |
function newBit(index) { | |
// Use the fact that the rule is literally named after the correspondence | |
// between states and bits in the next gen. The rule number _is_ a lookup | |
// table. | |
// Interpret the neighborhood as a binary int and use it to select the | |
// bit in the index corresponding to that neighborhood. | |
// Ex. Val: 8 7 6 5 ... | |
// Ex. Hoods: 111 110 101 100 ... | |
// Ex. New State: 0 1 0 0 ... | |
neighborhood = index_to_neighborhood(index); | |
neighborhood = parseInt(neighborhood, 2); | |
bit = (rule >> neighborhood) & 1; | |
return bit; | |
} | |
return { | |
init: function (state_, rule_) { | |
state = state_; | |
rule = rule_; | |
}, | |
nextState: function () { | |
var newState = []; | |
for (var i = 0; i < state.length; i++) { | |
newState[i] = newBit(i); | |
} | |
state = newState; | |
}, | |
getState: function () { | |
return state; | |
} | |
}; | |
} | |
function printstate(state) { | |
p(state.join()); | |
} | |
function test() { | |
function f(neighborhood) { | |
return (110 >> neighborhood) & 1; | |
} | |
for (var i = 7; i >= 0; i--) { | |
p(f(i)); | |
} | |
} | |
function run () { | |
rule = 110; | |
cells = 100; | |
rows = 100; | |
state = []; | |
for (var i = 0; i < cells; i++) { | |
state[i] = 0; | |
} | |
state[Math.floor(cells / 2)] = 1; | |
ca = makeCA(); | |
ca.init(state, rule); | |
printstate(ca.getState()); | |
for (var i = 0; i < rows; i++) { | |
ca.nextState(); | |
printstate(ca.getState()); | |
} | |
} | |
run(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment