Improve 1DLIFE.BAS: Less memory, more speed, constant printing#12
Open
HedAurabesh wants to merge 2 commits into
Open
Improve 1DLIFE.BAS: Less memory, more speed, constant printing#12HedAurabesh wants to merge 2 commits into
HedAurabesh wants to merge 2 commits into
Conversation
This improves the 1-D Life code in several ways, as outlined in my YouTube comment on running this code on the Centurion. The new code improves the following: - Instead of two arrays, only uses one array - Instead of a binary state (life/death) stores a 2-bit state (past & future life/death) - Instead of writing twice to the array, only writes once - Instead of looping to find the neighbors, uses a mathematical expression. Due to this, the code runs ~2x faster, has less lines of code and does not create a pause before printing a line, since printing and updates are now the same. The state is encoded with 2 bits: * 0 = Stay Dead (was dead) * 1 = Be Born (was dead) * 2 = Die (was alive) * 3 = Stay Alive (was alive) So the past & future state can be extracted via dividing by two (past) or by taking the modulo (future). The general flow is: * Initialize the array X with random values from [0, 3] * For each cell in X: * > IF cell was alive PRINT "X" ELSE " "; * > IF cell was alive AND has (2 || 4) neighbors THEN set X[C] = 3 (Lives) ELSE 2 (Dies) * > IF cell was dead AND has (2 || 3) neighbors THEN set X[C] = 0 (Stays dead) ELSE 1 (Gets born) The neighbour count is the value S computed as: S = (X[C-2] / 2) + (X[C-1] / 2) + (X[C+1] % 2) + (X[C+2] % 2) Do note how the already modified left-neighbors use the past state (division), while the unmodified cells use the present/future state (modulo)
Author
|
Also note: If MOD is not available, it can be replaced by bitwise AND -- or unrolled into a loop: 120 LET ALIVE = X(I) AND 1If divisions by two is slow -- and SHR is not available -- one can unroll the computation of S with an IF statement: 200 LET S = 0
201 IF X(I-2) > 1 THEN LET S = S+1
202 IF X(I-1) > 1 THEN LET S = S+1
203 LET S = S + (X(I+1) AND 1)
204 LET S = S + (X(I+2) AND 1)Of course, for maximum compatibility, the above has to be unrolled into "IF-THEN-GOTO-LINE" statements. |
Changed the code to be more portable * Made it so the array starts with 1 instead of 0 * Consistent use of LET in all assignments * Replaced the MOD with an arithmetic version, as neither MOD nor bitwise AND are universally present (looking at you Spectrum Basic)
Author
|
I updated the code in this pull request to be more portable. Most notably, arrays now start with index 1 and the MOD function (which isn't universal) was replaced with its slower, but portable arithmetic variant. Things I learned: In Spectrum Basic "AND" is not a bitwise AND -- but a weird hack for a specific use case of "AND". |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This improves the 1-D Life code in several ways, as outlined in my YouTube comment on running this code on the Centurion.
The new code improves the following:
Due to this, the code runs ~2x faster, has less lines of code and does not create a pause before printing a line, since printing and updates are now the same.
The state is encoded with 2 bits:
So the past & future life/death state can be extracted via dividing by two (past) or by taking the modulo (future).
The general flow is:
The neighbour count is the value S computed as:
S = (X[C-2] / 2) + (X[C-1] / 2) + (X[C+1] % 2) + (X[C+2] % 2)Do note how the already modified left-neighbors use the past state (division), while the unmodified cells use the present/future state (modulo)