Add files via upload
This commit is contained in:
parent
3634892b01
commit
e5eaa45a96
@ -14,7 +14,9 @@
|
|||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 1,
|
"execution_count": 1,
|
||||||
"metadata": {},
|
"metadata": {
|
||||||
|
"collapsed": true
|
||||||
|
},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"program = '''\n",
|
"program = '''\n",
|
||||||
@ -59,17 +61,19 @@
|
|||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 2,
|
"execution_count": 2,
|
||||||
"metadata": {},
|
"metadata": {
|
||||||
|
"collapsed": true
|
||||||
|
},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"import re \n",
|
"import re \n",
|
||||||
"\n",
|
"\n",
|
||||||
"tokenize = re.compile(\n",
|
"tokenize = re.compile(r'''\n",
|
||||||
" r'''\\d* \\.? \\d+ (?: E -? \\d+)? | # number \n",
|
" \\d* \\.? \\d+ (?: E -? \\d+)? | # number \n",
|
||||||
" SIN|COS|TAN|ATN|EXP|ABS|LOG|SQR|RND|INT|FN[A-Z]| # functions (including user-defined FNA-FNZ)\n",
|
" SIN|COS|TAN|ATN|EXP|ABS|LOG|SQR|RND|INT|FN[A-Z]| # functions\n",
|
||||||
" LET|READ|DATA|PRINT|GOTO|IF|FOR|NEXT|END|STOP | # keywords\n",
|
" LET|READ|DATA|PRINT|GOTO|IF|FOR|NEXT|END | # keywords\n",
|
||||||
" DEF|GOSUB|RETURN|DIM|REM|TO|THEN|STEP | # more keywords\n",
|
" DEF|GOSUB|RETURN|DIM|REM|TO|THEN|STEP|STOP | # keywords\n",
|
||||||
" [A-Z]\\d? | # variable names (letter optionally followed by a digit)\n",
|
" [A-Z]\\d? | # variable names (letter + optional digit)\n",
|
||||||
" \".*?\" | # labels (strings in double quotes)\n",
|
" \".*?\" | # labels (strings in double quotes)\n",
|
||||||
" <>|>=|<= | # multi-character relational operators\n",
|
" <>|>=|<= | # multi-character relational operators\n",
|
||||||
" \\S # any non-space single character ''', \n",
|
" \\S # any non-space single character ''', \n",
|
||||||
@ -175,14 +179,17 @@
|
|||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 6,
|
"execution_count": 6,
|
||||||
"metadata": {},
|
"metadata": {
|
||||||
|
"collapsed": true
|
||||||
|
},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"tokens = [] # Global variable to hold a list of tokens\n",
|
"tokens = [] # Global variable to hold a list of tokens\n",
|
||||||
"\n",
|
"\n",
|
||||||
"def tokenizer(line):\n",
|
"def tokenizer(line):\n",
|
||||||
" \"Return a list of the tokens on this line, handling spaces properly, and upper-casing.\"\n",
|
" \"Return a list of the tokens on this line, handling spaces properly, and upper-casing.\"\n",
|
||||||
" return tokenize(remove_spaces(line).upper())\n",
|
" line = ''.join(tokenize(line)) # Remove whitespace\n",
|
||||||
|
" return tokenize(line.upper())\n",
|
||||||
"\n",
|
"\n",
|
||||||
"def peek(): \n",
|
"def peek(): \n",
|
||||||
" \"Return the first token in the global `tokens`, or None if we are at the end of the line.\"\n",
|
" \"Return the first token in the global `tokens`, or None if we are at the end of the line.\"\n",
|
||||||
@ -197,7 +204,7 @@
|
|||||||
" \n",
|
" \n",
|
||||||
"def remove_spaces(line): \n",
|
"def remove_spaces(line): \n",
|
||||||
" \"Remove white space from line, except space inside double quotes.\"\n",
|
" \"Remove white space from line, except space inside double quotes.\"\n",
|
||||||
" return ''.join(tokenize(line))\n",
|
" return \n",
|
||||||
"\n",
|
"\n",
|
||||||
"def lines(text): \n",
|
"def lines(text): \n",
|
||||||
" \"A list of the non-empty lines in a text.\"\n",
|
" \"A list of the non-empty lines in a text.\"\n",
|
||||||
@ -240,9 +247,6 @@
|
|||||||
" assert (tokenizer('100IFX1+123.4+E1-12.3E4 <> 1.2E-34*-12E34+1+\"HI\" THEN99') ==\n",
|
" assert (tokenizer('100IFX1+123.4+E1-12.3E4 <> 1.2E-34*-12E34+1+\"HI\" THEN99') ==\n",
|
||||||
" ['100', 'IF', 'X1', '+', '123.4', '+', 'E1', '-', '12.3E4', '<>', \n",
|
" ['100', 'IF', 'X1', '+', '123.4', '+', 'E1', '-', '12.3E4', '<>', \n",
|
||||||
" '1.2E-34', '*', '-', '12E34', '+', '1', '+', '\"HI\"', 'THEN', '99'])\n",
|
" '1.2E-34', '*', '-', '12E34', '+', '1', '+', '\"HI\"', 'THEN', '99'])\n",
|
||||||
" assert remove_spaces('10 GO TO 99') == '10GOTO99'\n",
|
|
||||||
" assert (remove_spaces('100 PRINT \"HELLO WORLD\", SIN(X) ^ 2')\n",
|
|
||||||
" == '100PRINT\"HELLO WORLD\",SIN(X)^2')\n",
|
|
||||||
" assert lines('one line') == ['one line']\n",
|
" assert lines('one line') == ['one line']\n",
|
||||||
" assert lines(program) == [\n",
|
" assert lines(program) == [\n",
|
||||||
" '10 REM POWER TABLE',\n",
|
" '10 REM POWER TABLE',\n",
|
||||||
@ -364,7 +368,7 @@
|
|||||||
"- **`DIM`** `<list of variable>`\n",
|
"- **`DIM`** `<list of variable>`\n",
|
||||||
"- **`REM`** `<any string of characters whatsoever>`\n",
|
"- **`REM`** `<any string of characters whatsoever>`\n",
|
||||||
" \n",
|
" \n",
|
||||||
"The notation `<variable>` means any variable and `<list of variable>` means zero or more variables, separated by commas. `[STEP <expression>]` means that the literal string `\"STEP\"`, followed by an expression, is optional. \n",
|
"The notation `<variable>` means any variable and `<list of variable>` means zero or more variables, separated by commas. `[`**`STEP`** `<expression>]` means that the literal string `\"STEP\"` followed by an expression is optional. \n",
|
||||||
"\n",
|
"\n",
|
||||||
"Rather than use one of the many [language parsing frameworks](https://wiki.python.org/moin/LanguageParsing), I will show how to build a parser from scratch. First I'll translate the grammar above into Python. Not character-for-character (because it would take a lot of work to get Python to understand how to handle those characters), but almost word-for-word (because I can envision a straightforward way to get Python to handle the following format):"
|
"Rather than use one of the many [language parsing frameworks](https://wiki.python.org/moin/LanguageParsing), I will show how to build a parser from scratch. First I'll translate the grammar above into Python. Not character-for-character (because it would take a lot of work to get Python to understand how to handle those characters), but almost word-for-word (because I can envision a straightforward way to get Python to handle the following format):"
|
||||||
]
|
]
|
||||||
@ -391,7 +395,8 @@
|
|||||||
" 'GOSUB': [linenumber],\n",
|
" 'GOSUB': [linenumber],\n",
|
||||||
" 'RETURN': [],\n",
|
" 'RETURN': [],\n",
|
||||||
" 'DIM': [list_of(variable)], \n",
|
" 'DIM': [list_of(variable)], \n",
|
||||||
" 'REM': [anycharacters]\n",
|
" 'REM': [anycharacters],\n",
|
||||||
|
" 'A': []\n",
|
||||||
" }"
|
" }"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -462,9 +467,9 @@
|
|||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"def linenumber(): return (int(pop()) if peek().isnumeric() else fail('missing line number'))\n",
|
|
||||||
"def number(): return (-1 if pop('-') else +1) * float(pop()) # Optional minus sign\n",
|
"def number(): return (-1 if pop('-') else +1) * float(pop()) # Optional minus sign\n",
|
||||||
"def step(): return (expression() if pop('STEP') else 1) # 1 is the default step\n",
|
"def step(): return (expression() if pop('STEP') else 1) # 1 is the default step\n",
|
||||||
|
"def linenumber(): return (int(pop()) if peek().isnumeric() else fail('missing line number'))\n",
|
||||||
"def relational(): return pop(is_relational) or fail('expected a relational operator')\n",
|
"def relational(): return pop(is_relational) or fail('expected a relational operator')\n",
|
||||||
"def varname(): return pop(is_varname) or fail('expected a variable name')\n",
|
"def varname(): return pop(is_varname) or fail('expected a variable name')\n",
|
||||||
"def funcname(): return pop(is_funcname) or fail('expected a function name')\n",
|
"def funcname(): return pop(is_funcname) or fail('expected a function name')\n",
|
||||||
@ -506,7 +511,9 @@
|
|||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 13,
|
"execution_count": 13,
|
||||||
"metadata": {},
|
"metadata": {
|
||||||
|
"collapsed": true
|
||||||
|
},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"def variable(): \n",
|
"def variable(): \n",
|
||||||
@ -562,7 +569,7 @@
|
|||||||
},
|
},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"def parse(program): return sorted(map(parse_line, lines(program)))\n",
|
"def parse(program): return sorted(parse_line(line) for line in lines(program))\n",
|
||||||
"\n",
|
"\n",
|
||||||
"def parse_line(line): global tokens; tokens = tokenizer(line); return statement()"
|
"def parse_line(line): global tokens; tokens = tokenizer(line); return statement()"
|
||||||
]
|
]
|
||||||
@ -577,7 +584,9 @@
|
|||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 16,
|
"execution_count": 16,
|
||||||
"metadata": {},
|
"metadata": {
|
||||||
|
"collapsed": true
|
||||||
|
},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"def parse_line(line):\n",
|
"def parse_line(line):\n",
|
||||||
@ -648,7 +657,7 @@
|
|||||||
"* Optionally, `\";\"` can be used instead of `\",\"`.\n",
|
"* Optionally, `\";\"` can be used instead of `\",\"`.\n",
|
||||||
"* Optionally, the `\",\"` or `\";\"` can be omitted—we can have a label immediately followed by an expression.\n",
|
"* Optionally, the `\",\"` or `\";\"` can be omitted—we can have a label immediately followed by an expression.\n",
|
||||||
"\n",
|
"\n",
|
||||||
"The effect of a comma is to advance the output to the next column that is a multiple of 15 (and to a new line if this goes past column 75). The effect of a semicolon is similar, but works in multiples of 3, not 15. (Note that column numbering starts at 0, not 1.) Normally, at the end of a `PRINT` statement we advance to a new line, but this is not done if the statement ends in `\",\"` or `\";\"`. Here are some examples:\n",
|
"The effect of a comma is to advance the output to the next column that is a multiple of 15 (and to a new line if this goes past column 100). The effect of a semicolon is similar, but works in multiples of 3, not 15. (Note that column numbering starts at 0, not 1.) Normally, at the end of a `PRINT` statement we advance to a new line, but this is not done if the statement ends in `\",\"` or `\";\"`. Here are some examples:\n",
|
||||||
"\n",
|
"\n",
|
||||||
"* `10 PRINT X, Y`\n",
|
"* `10 PRINT X, Y`\n",
|
||||||
"<br>Prints the value of `X` in column 0 and `Y` in column 15. Advances to new line.\n",
|
"<br>Prints the value of `X` in column 0 and `Y` in column 15. Advances to new line.\n",
|
||||||
@ -711,7 +720,9 @@
|
|||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 19,
|
"execution_count": 19,
|
||||||
"metadata": {},
|
"metadata": {
|
||||||
|
"collapsed": true
|
||||||
|
},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"def expression(prec=1): \n",
|
"def expression(prec=1): \n",
|
||||||
@ -733,7 +744,7 @@
|
|||||||
" return Funcall(pop(), primary())\n",
|
" return Funcall(pop(), primary())\n",
|
||||||
" elif pop('-'): # '-X' => Funcall('NEG', 'X')\n",
|
" elif pop('-'): # '-X' => Funcall('NEG', 'X')\n",
|
||||||
" return Funcall('NEG', primary())\n",
|
" return Funcall('NEG', primary())\n",
|
||||||
" elif pop('('): # '(X + 1)' => Opcall('X', '+', 1)\n",
|
" elif pop('('): # '(X)' => 'X'\n",
|
||||||
" exp = expression()\n",
|
" exp = expression()\n",
|
||||||
" pop(')') or fail('expected \")\" to end expression')\n",
|
" pop(')') or fail('expected \")\" to end expression')\n",
|
||||||
" return exp\n",
|
" return exp\n",
|
||||||
@ -741,7 +752,7 @@
|
|||||||
" return fail('unknown expression')\n",
|
" return fail('unknown expression')\n",
|
||||||
"\n",
|
"\n",
|
||||||
"def precedence(op): \n",
|
"def precedence(op): \n",
|
||||||
" return (3 if op == '^' else 2 if op in ('*', '/') else 1 if op in ('+', '-') else 0)\n",
|
" return (3 if op == '^' else 2 if op in ('*', '/', '%') else 1 if op in ('+', '-') else 0)\n",
|
||||||
"\n",
|
"\n",
|
||||||
"def associativity(op): \n",
|
"def associativity(op): \n",
|
||||||
" return (0 if op == '^' else 1)"
|
" return (0 if op == '^' else 1)"
|
||||||
@ -897,7 +908,9 @@
|
|||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 23,
|
"execution_count": 23,
|
||||||
"metadata": {},
|
"metadata": {
|
||||||
|
"collapsed": true
|
||||||
|
},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"def execute(stmts): \n",
|
"def execute(stmts): \n",
|
||||||
@ -958,7 +971,9 @@
|
|||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 24,
|
"execution_count": 24,
|
||||||
"metadata": {},
|
"metadata": {
|
||||||
|
"collapsed": true
|
||||||
|
},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"import math\n",
|
"import math\n",
|
||||||
@ -973,7 +988,7 @@
|
|||||||
" 'SIN': math.sin, 'COS': math.cos, 'TAN': math.tan, 'ATN': math.atan, \n",
|
" 'SIN': math.sin, 'COS': math.cos, 'TAN': math.tan, 'ATN': math.atan, \n",
|
||||||
" 'ABS': abs, 'EXP': math.exp, 'LOG': math.log, 'SQR': math.sqrt, 'INT': int,\n",
|
" 'ABS': abs, 'EXP': math.exp, 'LOG': math.log, 'SQR': math.sqrt, 'INT': int,\n",
|
||||||
" '>': op.gt, '<': op.lt, '=': op.eq, '>=': op.ge, '<=': op.le, '<>': op.ne, \n",
|
" '>': op.gt, '<': op.lt, '=': op.eq, '>=': op.ge, '<=': op.le, '<>': op.ne, \n",
|
||||||
" '^': pow, '+': op.add, '-': op.sub, '*': op.mul, '/': op.truediv, \n",
|
" '^': pow, '+': op.add, '-': op.sub, '*': op.mul, '/': op.truediv, '%': op.mod,\n",
|
||||||
" 'RND': lambda _: random.random(), 'NEG': op.neg}\n",
|
" 'RND': lambda _: random.random(), 'NEG': op.neg}\n",
|
||||||
" data = deque() # A queue of numbers that READ can read from\n",
|
" data = deque() # A queue of numbers that READ can read from\n",
|
||||||
" for (_, typ, args) in stmts:\n",
|
" for (_, typ, args) in stmts:\n",
|
||||||
@ -1052,7 +1067,9 @@
|
|||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 25,
|
"execution_count": 25,
|
||||||
"metadata": {},
|
"metadata": {
|
||||||
|
"collapsed": true
|
||||||
|
},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"def basic_print(items): \n",
|
"def basic_print(items): \n",
|
||||||
@ -1066,11 +1083,11 @@
|
|||||||
" newline()\n",
|
" newline()\n",
|
||||||
" \n",
|
" \n",
|
||||||
"def print_string(s): \n",
|
"def print_string(s): \n",
|
||||||
" \"Print a string, keeping track of column, and advancing to newline if at or beyond column 75.\"\n",
|
" \"Print a string, keeping track of column, and advancing to newline if at or beyond column 100.\"\n",
|
||||||
" global column\n",
|
" global column\n",
|
||||||
" print(s, end='')\n",
|
" print(s, end='')\n",
|
||||||
" column += len(s)\n",
|
" column += len(s)\n",
|
||||||
" if column >= 75: newline()\n",
|
" if column >= 100: newline()\n",
|
||||||
" \n",
|
" \n",
|
||||||
"def pad(width): \n",
|
"def pad(width): \n",
|
||||||
" \"Pad out to the column that is the next multiple of width.\"\n",
|
" \"Pad out to the column that is the next multiple of width.\"\n",
|
||||||
@ -1284,9 +1301,8 @@
|
|||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
"output_type": "stream",
|
"output_type": "stream",
|
||||||
"text": [
|
"text": [
|
||||||
"1 2 3 4 5 \n",
|
"1 2 3 4 5 6 7 \n",
|
||||||
"6 7 8 9 10 \n",
|
"8 9 10 11 12 "
|
||||||
"11 12 "
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -1330,14 +1346,12 @@
|
|||||||
"N = 5 I^N:\n",
|
"N = 5 I^N:\n",
|
||||||
"1 32 243 1024 3125 \n",
|
"1 32 243 1024 3125 \n",
|
||||||
"\n",
|
"\n",
|
||||||
"\n",
|
|
||||||
"N = 6 I^N:\n",
|
"N = 6 I^N:\n",
|
||||||
"1 64 729 4096 15625 \n",
|
"1 64 729 4096 15625 46656 \n",
|
||||||
"46656 \n",
|
|
||||||
"\n",
|
"\n",
|
||||||
"N = 7 I^N:\n",
|
"N = 7 I^N:\n",
|
||||||
"1 128 2187 16384 78125 \n",
|
"1 128 2187 16384 78125 279936 823543 \n",
|
||||||
"279936 823543 \n",
|
"\n",
|
||||||
"\n"
|
"\n"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -1372,10 +1386,9 @@
|
|||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
"output_type": "stream",
|
"output_type": "stream",
|
||||||
"text": [
|
"text": [
|
||||||
"1e+06 941192 884736 830584 778688 729000 681472 636056 592704 \n",
|
"1e+06 941192 884736 830584 778688 729000 681472 636056 592704 551368 512000 474552 \n",
|
||||||
"551368 512000 474552 438976 405224 373248 343000 314432 287496 \n",
|
"438976 405224 373248 343000 314432 287496 262144 238328 216000 195112 175616 157464 \n",
|
||||||
"262144 238328 216000 195112 175616 157464 140608 125000 110592 \n",
|
"140608 125000 110592 97336 85184 74088 64000 54872 46656 39304 32768 27000 21952 17576 13824 10648 \n",
|
||||||
"97336 85184 74088 64000 54872 46656 39304 32768 27000 21952 17576 13824 10648 \n",
|
|
||||||
"8000 5832 4096 2744 1728 1000 512 216 64 8 0 "
|
"8000 5832 4096 2744 1728 1000 512 216 64 8 0 "
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -1454,27 +1467,27 @@
|
|||||||
"data": {
|
"data": {
|
||||||
"text/plain": [
|
"text/plain": [
|
||||||
"defaultdict(float,\n",
|
"defaultdict(float,\n",
|
||||||
" {('P', (1.0,)): 1.25,\n",
|
" {('S', (2.0, 1.0)): 10.0,\n",
|
||||||
" ('S', (3.0, 5.0)): 33.0,\n",
|
|
||||||
" ('S', (3.0, 4.0)): 16.0,\n",
|
|
||||||
" ('S', (1.0, 5.0)): 42.0,\n",
|
|
||||||
" ('S', (2.0, 1.0)): 10.0,\n",
|
|
||||||
" ('P', (3.0,)): 2.5,\n",
|
|
||||||
" ('S', (1.0, 4.0)): 29.0,\n",
|
|
||||||
" ('S', (1.0, 2.0)): 20.0,\n",
|
|
||||||
" ('S', (3.0, 1.0)): 35.0,\n",
|
|
||||||
" 'I': 3.0,\n",
|
|
||||||
" ('S', (2.0, 4.0)): 21.0,\n",
|
|
||||||
" ('P', (2.0,)): 4.3,\n",
|
|
||||||
" ('S', (2.0, 5.0)): 8.0,\n",
|
|
||||||
" ('S', (1.0, 1.0)): 40.0,\n",
|
|
||||||
" ('S', (3.0, 3.0)): 29.0,\n",
|
|
||||||
" 'J': 5.0,\n",
|
" 'J': 5.0,\n",
|
||||||
|
" ('S', (1.0, 1.0)): 40.0,\n",
|
||||||
|
" ('S', (3.0, 5.0)): 33.0,\n",
|
||||||
|
" ('P', (2.0,)): 4.3,\n",
|
||||||
" ('S', (3.0, 2.0)): 47.0,\n",
|
" ('S', (3.0, 2.0)): 47.0,\n",
|
||||||
|
" ('S', (2.0, 5.0)): 8.0,\n",
|
||||||
|
" 'I': 3.0,\n",
|
||||||
|
" ('P', (1.0,)): 1.25,\n",
|
||||||
|
" ('S', (1.0, 4.0)): 29.0,\n",
|
||||||
|
" ('S', (2.0, 4.0)): 21.0,\n",
|
||||||
|
" ('S', (3.0, 1.0)): 35.0,\n",
|
||||||
|
" ('S', (3.0, 4.0)): 16.0,\n",
|
||||||
" 'S': 169.4,\n",
|
" 'S': 169.4,\n",
|
||||||
" ('S', (2.0, 2.0)): 16.0,\n",
|
" ('S', (1.0, 2.0)): 20.0,\n",
|
||||||
|
" ('S', (1.0, 3.0)): 37.0,\n",
|
||||||
" ('S', (2.0, 3.0)): 3.0,\n",
|
" ('S', (2.0, 3.0)): 3.0,\n",
|
||||||
" ('S', (1.0, 3.0)): 37.0})"
|
" ('S', (2.0, 2.0)): 16.0,\n",
|
||||||
|
" ('S', (1.0, 5.0)): 42.0,\n",
|
||||||
|
" ('P', (3.0,)): 2.5,\n",
|
||||||
|
" ('S', (3.0, 3.0)): 29.0})"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 35,
|
"execution_count": 35,
|
||||||
@ -1495,10 +1508,9 @@
|
|||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
"output_type": "stream",
|
"output_type": "stream",
|
||||||
"text": [
|
"text": [
|
||||||
"7 2 8 4 9 1 9 8 0 8 3 0 3 4 5 6 4 2 1 6 9 9 9 7 5 \n",
|
"3 1 1 0 2 4 4 5 1 1 8 5 5 0 1 0 4 9 4 6 2 7 7 9 4 4 1 5 6 7 3 6 4 1 \n",
|
||||||
"8 4 1 5 9 9 7 5 5 7 2 0 3 2 1 2 1 8 3 9 9 3 0 0 2 \n",
|
"1 2 0 8 7 2 5 4 1 2 1 5 1 0 2 5 7 8 2 9 3 4 7 5 9 6 8 6 9 4 9 1 6 6 \n",
|
||||||
"2 8 9 7 5 8 9 0 2 7 8 6 7 4 9 9 4 2 5 4 0 9 6 5 3 \n",
|
"1 6 9 2 8 1 4 8 4 7 2 2 6 0 0 5 6 4 9 5 8 7 1 3 8 8 1 9 4 2 8 3 "
|
||||||
"3 3 5 1 7 1 6 1 0 7 3 5 8 1 9 0 4 7 1 7 4 5 1 7 6 \n"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -1655,54 +1667,61 @@
|
|||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
"output_type": "stream",
|
"output_type": "stream",
|
||||||
"text": [
|
"text": [
|
||||||
"Error in line '10 X = 1' at 'X = 1': unknown statement type\n",
|
"Error in line '1 X = 1' at 'X = 1': unknown statement type\n",
|
||||||
"Error in line '20 GO TO JAIL' at 'J A I L': missing line number\n",
|
"Error in line '2 GO TO JAIL' at 'J A I L': missing line number\n",
|
||||||
"Error in line '30 FOR I = 1 ' at '': expected 'TO'\n",
|
"Error in line '3 FOR I = 1 ' at '': expected 'TO'\n",
|
||||||
"Error in line '40 IF X > 0 & X < 10 GOTO 999' at '& X < 10 GOTO 999': expected 'THEN'\n",
|
"Error in line '4 IF X > 0 & X < 10 GOTO 999' at '& X < 10 GOTO 999': expected 'THEN'\n",
|
||||||
"Error in line '50 LET Z = (Z + 1' at '': expected \")\" to end expression\n",
|
"Error in line '5 LET Z = (Z + 1' at '': expected \")\" to end expression\n",
|
||||||
"Error in line '60 PRINT \"OH CANADA\", EH?' at '?': unknown expression\n",
|
"Error in line '6 PRINT \"OH CANADA\", EH?' at '?': unknown expression\n",
|
||||||
"Error in line '70 LET Z = +3' at '+ 3': unknown expression\n",
|
"Error in line '7 LET Z = +3' at '+ 3': unknown expression\n",
|
||||||
"Error in line '80 LET X = Y ** 2' at '* 2': unknown expression\n",
|
"Error in line '8 LET X = Y ** 2' at '* 2': unknown expression\n",
|
||||||
"Error in line '90 LET A(I = 1' at '= 1': expected \")\" to close subscript\n",
|
"Error in line '9 LET A(I = 1' at '= 1': expected \")\" to close subscript\n",
|
||||||
"Error in line '100 IF A = 0 THEN 900 + 99' at '+ 99': extra tokens at end of line\n",
|
"Error in line '10 IF A = 0 THEN 900 + 99' at '+ 99': extra tokens at end of line\n",
|
||||||
"Error in line '110 NEXT A(I)' at '( I )': extra tokens at end of line\n",
|
"Error in line '11 NEXT A(I)' at '( I )': extra tokens at end of line\n",
|
||||||
"Error in line '120 DEF F(X) = X ^ 2 + 1' at 'F ( X ) = X ^ 2 + 1': expected a function name\n",
|
"Error in line '12 DEF F(X) = X ^ 2 + 1' at 'F ( X ) = X ^ 2 + 1': expected a function name\n",
|
||||||
"Error in line '130 IF X != 0 THEN 999' at '! = 0 THEN 999': expected a relational operator\n",
|
"Error in line '13 IF X != 0 THEN 999' at '! = 0 THEN 999': expected a relational operator\n",
|
||||||
"Error in line '140 DEF FNS(X + 2*P1) = SIN(X)' at '+ 2 * P1 ) = SIN ( X )': expected ')'\n",
|
"Error in line '14 DEF FNS(X + 2*P1) = SIN(X)' at '+ 2 * P1 ) = SIN ( X )': expected ')'\n",
|
||||||
"Error in line '150 DEF FNY(M, B) = M * X + B' at ', B ) = M * X + B': expected ')'\n",
|
"Error in line '15 DEF FNY(M, B) = M * X + B' at ', B ) = M * X + B': expected ')'\n",
|
||||||
"Error in line '160 LET 3 = X' at '3 = X': expected a variable name\n",
|
"Error in line '16 LET 3 = X' at '3 = X': expected a variable name\n",
|
||||||
"Error in line '170 LET SIN = 7 * DEADLY' at 'SIN = 7 * D E A D L Y': expected a variable name\n",
|
"Error in line '17 LET SIN = 7 * DEADLY' at 'SIN = 7 * D E A D L Y': expected a variable name\n",
|
||||||
"Error in line '180 LET X = A-1(I)' at '( I )': extra tokens at end of line\n",
|
"Error in line '18 LET X = A-1(I)' at '( I )': extra tokens at end of line\n",
|
||||||
"Error in line 'STOP' at 'STOP': missing line number\n",
|
"Error in line '19 FOR SCORE + 7' at 'C O R E + 7': expected '='\n",
|
||||||
"Error in line '200 STOP IT, ALREADY' at 'I T , A L READ Y': extra tokens at end of line\n",
|
"Error in line '20 STOP IN NAME(LOVE)' at 'I N N A M E ( L O V E )': extra tokens at end of line\n",
|
||||||
"PROGRAM STILL EXECUTES: 2 + 2 = 4 \n"
|
"Error in line '85 ENDURANCE.' at 'U R A N C E .': extra tokens at end of line\n",
|
||||||
|
"ADD 2 + 2 = 4 \n"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"source": [
|
"source": [
|
||||||
"run('''\n",
|
"run('''\n",
|
||||||
"10 X = 1\n",
|
"1 X = 1\n",
|
||||||
"20 GO TO JAIL\n",
|
"2 GO TO JAIL\n",
|
||||||
"30 FOR I = 1 \n",
|
"3 FOR I = 1 \n",
|
||||||
"40 IF X > 0 & X < 10 GOTO 999\n",
|
"4 IF X > 0 & X < 10 GOTO 999\n",
|
||||||
"50 LET Z = (Z + 1\n",
|
"5 LET Z = (Z + 1\n",
|
||||||
"60 PRINT \"OH CANADA\", EH?\n",
|
"6 PRINT \"OH CANADA\", EH?\n",
|
||||||
"70 LET Z = +3\n",
|
"7 LET Z = +3\n",
|
||||||
"80 LET X = Y ** 2\n",
|
"8 LET X = Y ** 2\n",
|
||||||
"90 LET A(I = 1\n",
|
"9 LET A(I = 1\n",
|
||||||
"100 IF A = 0 THEN 900 + 99\n",
|
"10 IF A = 0 THEN 900 + 99\n",
|
||||||
"110 NEXT A(I)\n",
|
"11 NEXT A(I)\n",
|
||||||
"120 DEF F(X) = X ^ 2 + 1\n",
|
"12 DEF F(X) = X ^ 2 + 1\n",
|
||||||
"130 IF X != 0 THEN 999\n",
|
"13 IF X != 0 THEN 999\n",
|
||||||
"140 DEF FNS(X + 2*P1) = SIN(X)\n",
|
"14 DEF FNS(X + 2*P1) = SIN(X)\n",
|
||||||
"150 DEF FNY(M, B) = M * X + B\n",
|
"15 DEF FNY(M, B) = M * X + B\n",
|
||||||
"160 LET 3 = X\n",
|
"16 LET 3 = X\n",
|
||||||
"170 LET SIN = 7 * DEADLY\n",
|
"17 LET SIN = 7 * DEADLY\n",
|
||||||
"180 LET X = A-1(I)\n",
|
"18 LET X = A-1(I)\n",
|
||||||
"STOP\n",
|
"19 FOR SCORE + 7\n",
|
||||||
"200 STOP IT, ALREADY\n",
|
"20 STOP IN NAME(LOVE)\n",
|
||||||
"998 PRINT \"PROGRAM STILL EXECUTES: 2 + 2 = \" 2 + 2\n",
|
"80 REMARKABLY, THE INTERPRETER\n",
|
||||||
"999 END\n",
|
"81 REMEDIES THE ERRORS, AND THE PROPGRAM\n",
|
||||||
|
"82 REMAINS AN EXECUTABLE ENTITY, UN-\n",
|
||||||
|
"83 REMITTENTLY RUNNING, WITH NO\n",
|
||||||
|
"84 REMORSE OR REGRETS, AND WITH GREAT\n",
|
||||||
|
"85 ENDURANCE.\n",
|
||||||
|
"98 PRINT \"ADD 2 + 2 = \" 2 + 2\n",
|
||||||
|
"99 END\n",
|
||||||
"''')"
|
"''')"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -1710,10 +1729,9 @@
|
|||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"source": [
|
"source": [
|
||||||
"# Final Program\n",
|
"# Longer Program: Life\n",
|
||||||
"\n",
|
"\n",
|
||||||
"Now for a final, longer example, Conway's Game of [Life](https://en.wikipedia.org/wiki/Conway's_Game_of_Life),\n",
|
"Now for a final, slightly more complicated example: Conway's Game of [Life](https://en.wikipedia.org/wiki/Conway's_Game_of_Life). "
|
||||||
"which shows that BASIC is capable of handling a non-trivial problem—but I wouldn't want to rely on it for anything much bigger. This should give us some added confidence in the validity of the interpreter, but I would say the interpreter needs more work before I would trust it. I hope you found working through the interpreter infortative, and maybe you have ideas for how to improve it, or to develop an interpreter for another language."
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1725,7 +1743,7 @@
|
|||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
"output_type": "stream",
|
"output_type": "stream",
|
||||||
"text": [
|
"text": [
|
||||||
" GENERATION 0 \n",
|
"GEN 0 \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
@ -1736,7 +1754,7 @@
|
|||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
" GENERATION 1 \n",
|
"GEN 1 \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
@ -1747,7 +1765,7 @@
|
|||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
" GENERATION 2 \n",
|
"GEN 2 \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
@ -1758,7 +1776,7 @@
|
|||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
" GENERATION 3 \n",
|
"GEN 3 \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
@ -1769,7 +1787,7 @@
|
|||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
" GENERATION 4 \n",
|
"GEN 4 \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
@ -1780,7 +1798,7 @@
|
|||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
" GENERATION 5 \n",
|
"GEN 5 \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . O O . . . . . \n",
|
". . . O O . . . . . \n",
|
||||||
@ -1791,7 +1809,7 @@
|
|||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
" GENERATION 6 \n",
|
"GEN 6 \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . O O O . . . . \n",
|
". . . O O O . . . . \n",
|
||||||
@ -1802,7 +1820,7 @@
|
|||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
" GENERATION 7 \n",
|
"GEN 7 \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . O . . . . . \n",
|
". . . . O . . . . . \n",
|
||||||
". . . O . O . . . . \n",
|
". . . O . O . . . . \n",
|
||||||
@ -1813,7 +1831,7 @@
|
|||||||
". . . . O . . . . . \n",
|
". . . . O . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
" GENERATION 8 \n",
|
"GEN 8 \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . O . . . . . \n",
|
". . . . O . . . . . \n",
|
||||||
". . . O O O . . . . \n",
|
". . . O O O . . . . \n",
|
||||||
@ -1824,7 +1842,7 @@
|
|||||||
". . . . O . . . . . \n",
|
". . . . O . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
" GENERATION 9 \n",
|
"GEN 9 \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . O O O . . . . \n",
|
". . . O O O . . . . \n",
|
||||||
". . O . . . O . . . \n",
|
". . O . . . O . . . \n",
|
||||||
@ -1835,7 +1853,7 @@
|
|||||||
". . . O O O . . . . \n",
|
". . . O O O . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
". . . . . . . . . . \n",
|
". . . . . . . . . . \n",
|
||||||
" GENERATION 10 \n",
|
"GEN 10 \n",
|
||||||
". . . . O . . . . . \n",
|
". . . . O . . . . . \n",
|
||||||
". . . O O O . . . . \n",
|
". . . O O O . . . . \n",
|
||||||
". . O O O O O . . . \n",
|
". . O O O O O . . . \n",
|
||||||
@ -1852,15 +1870,17 @@
|
|||||||
"source": [
|
"source": [
|
||||||
"run('''\n",
|
"run('''\n",
|
||||||
"100 REM CONWAY'S GAME OF LIFE\n",
|
"100 REM CONWAY'S GAME OF LIFE\n",
|
||||||
"102 REM G IS NUMBER OF GENERATIONS, M IS MATRIX SIZE (M X M)\n",
|
"\n",
|
||||||
"104 REM A(X, Y) IS 1 IFF CELL AT (X, Y) IS LIVE\n",
|
"102 REM G IS NUMBER OF GENERATIONS, \n",
|
||||||
"106 REM L(SELF_ALIVE, NEIGHBORS_ALIVE) IS 1 IFF CELL WITH THOSE COUNTS SHOULD LIVE ON\n",
|
"104 REM M IS MATRIX SIZE (M X M)\n",
|
||||||
"110 LET G = 10\n",
|
"106 REM L(SELF, NEIGHBORS_ALIVE) IS 1 IFF CELL WITH THOSE COUNTS LIVES\n",
|
||||||
"120 LET M = 10\n",
|
"108 REM A(X, Y) IS 1 IFF CELL AT (X, Y) IS LIVE\n",
|
||||||
"125 READ A(3,4), A(3,5), A(3,6), A(6,5), A(6,6), A(7,5), A(7,6)\n",
|
"110 REM B(X, Y) GETS THE NEXT GENERATION\n",
|
||||||
"130 DATA 1, 1, 1, 1, 1, 1, 1\n",
|
"\n",
|
||||||
"140 READ L(0, 3), L(1, 3), L(1, 2)\n",
|
"120 READ G, M, L(0,3), L(1,3), L(1,2)\n",
|
||||||
"145 DATA 1, 1, 1\n",
|
"121 DATA 10, 10, 1, 1, 1\n",
|
||||||
|
"130 READ A(3,4), A(3,5), A(3,6), A(6,5), A(6,6), A(7,5), A(7,6)\n",
|
||||||
|
"131 DATA 1, 1, 1, 1, 1, 1, 1\n",
|
||||||
"\n",
|
"\n",
|
||||||
"150 REM MAIN LOOP: PRINT, THEN REPEAT G TIMES: UPDATE / COPY / PRINT\n",
|
"150 REM MAIN LOOP: PRINT, THEN REPEAT G TIMES: UPDATE / COPY / PRINT\n",
|
||||||
"155 LET I = 0\n",
|
"155 LET I = 0\n",
|
||||||
@ -1872,7 +1892,7 @@
|
|||||||
"210 NEXT I\n",
|
"210 NEXT I\n",
|
||||||
"220 STOP\n",
|
"220 STOP\n",
|
||||||
"\n",
|
"\n",
|
||||||
"300 REM SUBROUTINE: UPDATE B = NEXT_GENERATION(A)\n",
|
"300 REM ========== UPDATE B = NEXT_GEN(A)\n",
|
||||||
"310 FOR Y = 1 TO M\n",
|
"310 FOR Y = 1 TO M\n",
|
||||||
"320 FOR X = 1 TO M\n",
|
"320 FOR X = 1 TO M\n",
|
||||||
"325 LET N = A(X-1,Y)+A(X+1,Y)+A(X,Y-1)+A(X,Y+1)+A(X-1,Y-1)+A(X+1,Y+1)+A(X-1,Y+1)+A(X+1,Y-1)\n",
|
"325 LET N = A(X-1,Y)+A(X+1,Y)+A(X,Y-1)+A(X,Y+1)+A(X-1,Y-1)+A(X+1,Y+1)+A(X-1,Y+1)+A(X+1,Y-1)\n",
|
||||||
@ -1881,7 +1901,7 @@
|
|||||||
"350 NEXT Y\n",
|
"350 NEXT Y\n",
|
||||||
"360 RETURN\n",
|
"360 RETURN\n",
|
||||||
"\n",
|
"\n",
|
||||||
"500 REM SUBROUTINE: COPY A = B\n",
|
"500 REM ========== COPY A = B\n",
|
||||||
"510 FOR Y = 1 TO M\n",
|
"510 FOR Y = 1 TO M\n",
|
||||||
"520 FOR X = 1 TO M\n",
|
"520 FOR X = 1 TO M\n",
|
||||||
"530 LET A(X, Y) = B(X, Y)\n",
|
"530 LET A(X, Y) = B(X, Y)\n",
|
||||||
@ -1889,14 +1909,14 @@
|
|||||||
"550 NEXT Y\n",
|
"550 NEXT Y\n",
|
||||||
"560 RETURN\n",
|
"560 RETURN\n",
|
||||||
"\n",
|
"\n",
|
||||||
"700 REM SUBROUTINE: PRINT A\n",
|
"700 REM ========== PRINT A\n",
|
||||||
"705 PRINT \" GENERATION \" I\n",
|
"705 PRINT \"GEN \" I\n",
|
||||||
"710 FOR Y = 1 TO M\n",
|
"710 FOR Y = 1 TO M\n",
|
||||||
"720 FOR X = 1 TO M\n",
|
"720 FOR X = 1 TO M\n",
|
||||||
"730 IF A(X, Y) = 0 THEN 750\n",
|
"730 IF A(X, Y) = 1 THEN 760\n",
|
||||||
"740 PRINT \"O\";\n",
|
"740 PRINT \".\";\n",
|
||||||
"750 IF A(X, Y) = 1 THEN 770\n",
|
"750 GOTO 770\n",
|
||||||
"760 PRINT \".\";\n",
|
"760 PRINT \"O\";\n",
|
||||||
"770 NEXT X\n",
|
"770 NEXT X\n",
|
||||||
"780 PRINT\n",
|
"780 PRINT\n",
|
||||||
"790 NEXT Y\n",
|
"790 NEXT Y\n",
|
||||||
@ -1907,13 +1927,144 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "markdown",
|
||||||
"execution_count": null,
|
"metadata": {},
|
||||||
"metadata": {
|
"source": [
|
||||||
"collapsed": true
|
"Actually, this was an assignment in my high school BASIC class. (We used a [slightly different](https://www.grc.com/pdp-8/docs/os8_basic_reference.pdf) version of BASIC.) Back then, output was on rolls of paper, and I thought it was wasteful to print only one generation per line. So I arranged to print multiple generations on the same line, storing them until it was time to print them out. But BASIC doesn't have three-dimensional arrays, so I needed to store several generations worth of data in one `A(X, Y)` value. Today, I know that that could be done by allocating one bit for each generation, but back then I don't think I knew about binary representation, so I stored one generation in each decimal digit. That means I no longer need two matrixes, `A` and `B`; instead, the current generation will always be the value in the one's place, the previous generation in the ten's place, and the one before that in the hundred's place. (Also, I admit I cheated: I added the mod operatoir, `%`, which did not appear in early versions of BASIC, just because it was useful for this program.)"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"outputs": [],
|
{
|
||||||
"source": []
|
"cell_type": "code",
|
||||||
|
"execution_count": 43,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"GEN 0 GEN 1 GEN 2 \n",
|
||||||
|
". . . . . . . . . . | . . . . . . . . . . | . . . . . . . . . . | \n",
|
||||||
|
". . . . . . . . . . | . . . . . . . . . . | . . . . . . . . . . | \n",
|
||||||
|
". . . . . . . . . . | . . . . . . . . . . | . . . . . . . . . . | \n",
|
||||||
|
". . O . . . . . . . | . . . . . . . . . . | . . O . . . . . . . | \n",
|
||||||
|
". . O . . O O . . . | . O O O . O O . . . | . . O . O O O . . . | \n",
|
||||||
|
". . O . . O O . . . | . . . . . O O . . . | . . O . O O O . . . | \n",
|
||||||
|
". . . . . . . . . . | . . . . . . . . . . | . . . . . . . . . . | \n",
|
||||||
|
". . . . . . . . . . | . . . . . . . . . . | . . . . . . . . . . | \n",
|
||||||
|
". . . . . . . . . . | . . . . . . . . . . | . . . . . . . . . . | \n",
|
||||||
|
". . . . . . . . . . | . . . . . . . . . . | . . . . . . . . . . | \n",
|
||||||
|
"GEN 3 GEN 4 GEN 5 \n",
|
||||||
|
". . . . . . . . . . | . . . . . . . . . . | . . . . . . . . . . | \n",
|
||||||
|
". . . . . . . . . . | . . . . . . . . . . | . . . . . . . . . . | \n",
|
||||||
|
". . . . . . . . . . | . . . . . . . . . . | . . . O O . . . . . | \n",
|
||||||
|
". . . O . O . . . . | . . O O O O . . . . | . . O . O O . . . . | \n",
|
||||||
|
". O O . O . O . . . | . . O . O . O . . . | . . O . . . O . . . | \n",
|
||||||
|
". . . . O . O . . . | . . . O O . O . . . | . . . O O . O . . . | \n",
|
||||||
|
". . . . . O . . . . | . . . . . O . . . . | . . . . O O . . . . | \n",
|
||||||
|
". . . . . . . . . . | . . . . . . . . . . | . . . . . . . . . . | \n",
|
||||||
|
". . . . . . . . . . | . . . . . . . . . . | . . . . . . . . . . | \n",
|
||||||
|
". . . . . . . . . . | . . . . . . . . . . | . . . . . . . . . . | \n",
|
||||||
|
"GEN 6 GEN 7 GEN 8 \n",
|
||||||
|
". . . . . . . . . . | . . . . . . . . . . | . . . . . . . . . . | \n",
|
||||||
|
". . . . . . . . . . | . . . . O . . . . . | . . . . O . . . . . | \n",
|
||||||
|
". . . O O O . . . . | . . . O . O . . . . | . . . O O O . . . . | \n",
|
||||||
|
". . O . O O . . . . | . . O . . . O . . . | . . O O . O O . . . | \n",
|
||||||
|
". . O . . . O . . . | . . O . . . O . . . | . O O O . O O O . . | \n",
|
||||||
|
". . . O O . O . . . | . . O . . . O . . . | . . O O . O O . . . | \n",
|
||||||
|
". . . O O O . . . . | . . . O . O . . . . | . . . O O O . . . . | \n",
|
||||||
|
". . . . . . . . . . | . . . . O . . . . . | . . . . O . . . . . | \n",
|
||||||
|
". . . . . . . . . . | . . . . . . . . . . | . . . . . . . . . . | \n",
|
||||||
|
". . . . . . . . . . | . . . . . . . . . . | . . . . . . . . . . | \n",
|
||||||
|
"GEN 9 GEN 10 GEN 11 \n",
|
||||||
|
". . . . . . . . . . | . . . . O . . . . . | . . . O O O . . . . | \n",
|
||||||
|
". . . O O O . . . . | . . . O O O . . . . | . . O . . . O . . . | \n",
|
||||||
|
". . O . . . O . . . | . . O O O O O . . . | . O . . . . . O . . | \n",
|
||||||
|
". O . . . . . O . . | . O O . . . O O . . | O . . . O . . . O . | \n",
|
||||||
|
". O . . . . . O . . | O O O . . . O O O . | O . . O . O . . O . | \n",
|
||||||
|
". O . . . . . O . . | . O O . . . O O . . | O . . . O . . . O . | \n",
|
||||||
|
". . O . . . O . . . | . . O O O O O . . . | . O . . . . . O . . | \n",
|
||||||
|
". . . O O O . . . . | . . . O O O . . . . | . . O . . . O . . . | \n",
|
||||||
|
". . . . . . . . . . | . . . . O . . . . . | . . . O O O . . . . | \n",
|
||||||
|
". . . . . . . . . . | . . . . . . . . . . | . . . . . . . . . . | \n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"run('''\n",
|
||||||
|
"100 REM CONWAY'S GAME OF LIFE\n",
|
||||||
|
"\n",
|
||||||
|
"102 REM G IS NUMBER OF GENERATIONS, \n",
|
||||||
|
"104 REM M IS MATRIX SIZE (M X M)\n",
|
||||||
|
"106 REM L(SELF, NEIGHBORS_ALIVE) IS 1 IFF CELL WITH THOSE COUNTS LIVES\n",
|
||||||
|
"108 REM A(X, Y) STORES THE HISTORY OF THE CELL AT (X, Y); 1 MEANS LIVE,\n",
|
||||||
|
"110 REM BUT WE STORE SEVERAL GENERATIONS: A(X, Y) = 100 MEANS THE CELL\n",
|
||||||
|
"112 REM IS DEAD IN THE CURRENT AND PREVIOUS GENERATION (00), BUT LIVE IN THE\n",
|
||||||
|
"114 REM GENERATION BEFORE THAT (1). WE STORE MULTIPLE GENERATIONS SO THAT\n",
|
||||||
|
"116 REM WE CAN PRINT THEM OUT ON ONE LINE, SAVING SPACE/PAPER.\n",
|
||||||
|
"\n",
|
||||||
|
"120 READ G, M, L(0,3), L(1,3), L(1,2)\n",
|
||||||
|
"122 DATA 11, 10, 1, 1, 1\n",
|
||||||
|
"124 READ A(3,4), A(3,5), A(3,6), A(6,5), A(6,6), A(7,5), A(7,6)\n",
|
||||||
|
"126 DATA 1, 1, 1, 1, 1, 1, 1\n",
|
||||||
|
"\n",
|
||||||
|
"130 REM FNA(N) = THE PREVIOUS GENERATION'S VALUE\n",
|
||||||
|
"132 DEF FNA(N) = INT(N / 10) % 10\n",
|
||||||
|
"\n",
|
||||||
|
"134 REM FNC(N) = THE GENERATION IN COLUMN C; FNC(123) = C FOR EACH C IN 1..3\n",
|
||||||
|
"136 DEF FNC(N) = FNA(N / (10 ^ (2 - C)))\n",
|
||||||
|
"\n",
|
||||||
|
"150 REM MAIN LOOP: DO 3 UPDATES (2 FIRST TIME), THEN PRINT AND SHIFT\n",
|
||||||
|
"160 FOR I = 1 TO G\n",
|
||||||
|
"170 GOSUB 300\n",
|
||||||
|
"175 IF I % 3 <> 2 THEN 200\n",
|
||||||
|
"180 GOSUB 700\n",
|
||||||
|
"190 GOSUB 800\n",
|
||||||
|
"200 NEXT I\n",
|
||||||
|
"210 STOP\n",
|
||||||
|
"\n",
|
||||||
|
"300 REM ========== UPDATE A: SHIFT OLD GENS LEFT; ADD IN NEW GEN\n",
|
||||||
|
"310 FOR Y = 1 TO M\n",
|
||||||
|
"320 FOR X = 1 TO M \n",
|
||||||
|
"330 LET A(X, Y) = 10 * A(X, Y)\n",
|
||||||
|
"340 NEXT X\n",
|
||||||
|
"350 NEXT Y\n",
|
||||||
|
"360 FOR Y = 1 TO M\n",
|
||||||
|
"370 FOR X = 1 TO M \n",
|
||||||
|
"380 LET N1 = FNA(A(X+1,Y-1)) + FNA(A(X+1,Y)) + FNA(A(X+1,Y+1)) + FNA(A(X,Y-1))\n",
|
||||||
|
"390 LET N2 = FNA(A(X-1,Y-1)) + FNA(A(X-1,Y)) + FNA(A(X-1,Y+1)) + FNA(A(X,Y+1))\n",
|
||||||
|
"400 LET S = FNA(A(X, Y))\n",
|
||||||
|
"410 LET A(X, Y) = A(X, Y) + L(S, N1 + N2)\n",
|
||||||
|
"420 NEXT X\n",
|
||||||
|
"430 NEXT Y\n",
|
||||||
|
"440 RETURN\n",
|
||||||
|
"\n",
|
||||||
|
"700 REM ========== PRINT A (3 GENERATIONS ACROSS THE PAGE)\n",
|
||||||
|
"705 PRINT \"GEN \" I-2, \" \", \" GEN \" I-1, \" \", \" GEN \" I\n",
|
||||||
|
"710 FOR Y = 1 TO M\n",
|
||||||
|
"715 FOR C = 1 TO 3\n",
|
||||||
|
"720 FOR X = 1 TO M\n",
|
||||||
|
"730 IF FNC(A(X, Y)) = 1 THEN 760\n",
|
||||||
|
"740 PRINT \".\";\n",
|
||||||
|
"750 GOTO 770\n",
|
||||||
|
"760 PRINT \"O\";\n",
|
||||||
|
"770 NEXT X\n",
|
||||||
|
"775 PRINT \"|\";\n",
|
||||||
|
"777 NEXT C\n",
|
||||||
|
"780 PRINT\n",
|
||||||
|
"790 NEXT Y\n",
|
||||||
|
"795 RETURN\n",
|
||||||
|
"\n",
|
||||||
|
"800 REM ========== FORGET ALL BUT THE MOST RECENT GENERATION IN A\n",
|
||||||
|
"810 FOR Y = 1 TO M\n",
|
||||||
|
"820 FOR X = 1 TO M\n",
|
||||||
|
"830 LET A(X, Y) = A(X, Y) % 10\n",
|
||||||
|
"840 NEXT X\n",
|
||||||
|
"850 NEXT Y\n",
|
||||||
|
"860 RETURN\n",
|
||||||
|
"\n",
|
||||||
|
"999 END \n",
|
||||||
|
"''')"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"metadata": {
|
"metadata": {
|
||||||
|
Loading…
Reference in New Issue
Block a user