Add solutions for part 1

This commit is contained in:
2020-11-15 13:57:48 -05:00
parent e4f9fd2682
commit 742db6d102
479 changed files with 202980 additions and 13 deletions

View File

@@ -0,0 +1,27 @@
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/09/Average/Main.jack
// Inputs some numbers and computes their average
class Main {
function void main() {
var Array a;
var int length;
var int i, sum;
let length = Keyboard.readInt("How many numbers? ");
let a = Array.new(length); // constructs the array
let i = 0;
while (i < length) {
let a[i] = Keyboard.readInt("Enter a number: ");
let sum = sum + a[i];
let i = i + 1;
}
do Output.printString("The average is ");
do Output.printInt(sum / length);
return;
}
}

View File

@@ -0,0 +1,200 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Sokoban Bitmap Editor</title>
<script type="text/javascript">
var grid = new Array(0);
function Init() {
grid = InitGrid();
DisplayGrid();
}
function InitGrid() {
var _grid = new Array(16);
for (i=0; i<16; i++) {
_grid[i] = new Array(16);
for (j=0; j<16; j++) {
_grid[i][j]=false;
}
}
return _grid;
}
function RotateBitmapRight() {
var _grid = InitGrid();
for (i=0; i<16; i++) {
for (j=0; j<16; j++) {
_grid[j][15-i]=grid[i][j];
}
}
grid = _grid;
DisplayGrid();
}
function MirrorBitmap() {
var _grid = InitGrid();
for (i=0; i<16; i++) {
for (j=0; j<16; j++) {
_grid[i][15-j]=grid[i][j];
}
}
grid = _grid;
DisplayGrid();
}
function DisplayGrid() {
var str = "<table border=1 cellspacing=0>";
var i,j, backgroundColor;
for (i=-1; i<16; i++) {
str=str+"<tr>";
for (j=-1; j<16; j++) {
if (i == -1 && j != -1) {
str=str+"<td>" + (j+1) + "</td>";
} else if (i != -1 && j == -1) {
str=str+"<td>" + (i+1) + "</td>";
} else if (i ==-1 && j == -1) {
str=str+"<td/>";
} else {
if (grid[i][j] == true)
backgroundColor = "black";
else
backgroundColor = "white";
str=str+"<td onclick=\"OnCellClicked(this)\" id="; str=str+(i*16+j); str=str+" width=16 height=16 bgcolor=" + backgroundColor + "></td>";
}
}
str=str+"</tr>";
}
str=str+"</table>"
gridElement = document.getElementById('grid');
gridElement.innerHTML = str;
GenerateBitMap() ;
}
function OnCellClicked(cell) {
var i = cell.id / 16 |0;
var j = cell.id - i*16;
grid[i][j] = !grid[i][j];
if (grid[i][j])
cell.style.backgroundColor = "black";
else
cell.style.backgroundColor = "white";
GenerateBitMap();
}
function GenerateBitMap() {
var i, j;
var value;
var functionTypeSelect = document.getElementById('functionType');
methodType = functionTypeSelect.options[functionTypeSelect.selectedIndex].value;
generateCode = document.getElementById('generatedCode');
generateCode.value = methodType + " void " +
document.getElementById('functionName').value +
"(int location) {\n\tlet memAddress = 16384+location;\n";
for (i=0; i<16; i++) {
//get grid binary representation
binary = "";
for (j=0; j<16; j++) {
if (grid[i][j])
binary = "1" + binary;
else
binary = "0" + binary;
}
isNegative = false;
//if number is negative, get its one's complement
if (binary[0] == "1") {
isNegative = true;
oneComplement = "";
for (k=0; k<16; k++) {
if (binary[k] == "1")
oneComplement = oneComplement + "0";
else
oneComplement = oneComplement + "1";
}
binary = oneComplement;
}
//calculate one's complement decimal value
value = 0;
for (k=0; k<16; k++) {
value = value * 2;
if (binary[k] == "1")
value=value+1;
}
//two's complement value if it is a negative value
if (isNegative == true)
value = -(value + 1)
generateCode.value = generateCode.value + GenerateCodeLine(i, value);
}
generateCode.value = generateCode.value + "\treturn;\n}";
}
function GenerateCodeLine(row, value) {
str = "\tdo Memory.poke(memAddress+" + row*32 + ", " + value + ");\n";
return str;
}
</script>
</head>
<body onload="Init();">
<h4><i>IDC Herzliya / Efi Arazi School of Computer Science / Digital Systems Construction, Spring 2011 / Project 09 / Golan Parashi</i></h4>
<h1>Sokoban Bitmap Editor</h1>
<p>This javascript applicaiton is used to generate highly optimized jack code for drawing a 16x16 bitmap to the screen.</p>
<p>Using the mouse, click the desired cell to mark/unmark it. You may use 90 degrees rotation and vertical mirroring by<br>
clicking the appropriate buttons.</p>
<p>When you are finished drawing, you may select function type and enter function's name.</p>
<p>
<table>
<thead>
<tr>
<th align="left">Bitmap</th>
<th align="left"></th>
<th align="left">Generated Jack Code</th>
</tr>
</thead>
<tr>
<td><div id="grid"/></td>
<td>
<form action="javascript:GenerateBitMap();">
<table>
<tr><td align="left">Function Type:</td></tr>
<tr><td align="center">
<select id="functionType" onChange="GenerateBitMap()">
<option value="function" selected="selected">function</option>
<option value="method">method</option>
</select>
</td></tr>
<tr><td align="left">Function Name:</td></tr>
<tr><td align="left"><input type="text" value="draw" id="functionName" onkeyup="GenerateBitMap()"/></td></tr>
<tr><td></td></tr>
<tr><td align="center"><input type="button" value="Generate Code >>" onclick="GenerateBitMap()"/></td></tr>
</table>
</form>
</td>
<td><textarea id="generatedCode" cols="50" rows="20" readonly="read-only"></textarea></td>
</tr>
<tr>
<table>
<tr>
<td align="center"><input type="button" value="Rotate right" onclick="RotateBitmapRight()"/></td>
<td align="center"><input type="button" value="Vertical Mirror" onclick="MirrorBitmap()"/></td>
</tr>
</table>
</tr>
</table>
</body>
</html>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@@ -0,0 +1,205 @@
/** Represents a 1D cellular automaton that can be printed to the screen. */
class CellularAutomaton {
field Array currentConfig; // an array where each field represents one cell
field int currentRule; // the current rule used by nextState
field int currentRow; // the row on the screen where the last state was printed
field int size; // cells per row
field boolean debug; // print debugging help to screen if true
/** Create a new automaton where size is the number of cells per row. */
constructor CellularAutomaton new() {
var int i;
let currentRule = 0;
let currentRow = 0;
let size = 512;
let debug = false;
let currentConfig = Array.new(size);
let i = 0;
while (i < size) {
let currentConfig[i] = 0;
let i = i + 1;
}
return this;
}
/** Returns a reference to the current config. Be careful, step creates a
* new configuration so using the reference after calling step points to
* invalid memory.
*/
method Array getCurrentConfig() {
return currentConfig;
}
method void dispose() {
do currentConfig.dispose();
do Memory.deAlloc(this);
return;
}
method void setRule(int rule) {
let currentRule = rule;
return;
}
/** Draws the current configuration to the currentRow on the screen. */
method void draw() {
if (currentRow > 255) {
// This works, but is slow and I don't know how to make it faster.
// So we simply start from the top instead again.
// do drawLastRow();
let currentRow = 0;
do Screen.clearScreen();
do drawNewRow();
} else {
do drawNewRow();
}
if (debug) {
do Screen.setColor(true);
do Output.moveCursor(0, 0);
do Output.printInt(currentRow);
}
return;
}
/** If we are not yet in the last row we can simply
* print the new config to the next row. */
method void drawNewRow() {
var int i;
let i = 0;
while (i < size) {
if (currentConfig[i]) {
do Screen.setColor(true);
} else {
do Screen.setColor(false);
}
do Screen.drawPixel(i, currentRow);
let i = i + 1;
}
return;
}
method void copy(int sourceAddress, int targetAddress) {
var int value;
let value = Memory.peek(sourceAddress);
do Memory.poke(targetAddress, value);
return;
}
/** If we are in the last row we first have to move all existing rows one
* row up. We can then draw the last row. XXX: This works, but we are
* currently not using it because it is too slow. */
method void drawLastRow() {
var int i;
var int sourceAddress;
// Screen Base + Words = 16384 + 8160 = 24544
let i = 16383;
while (i < 24544) {
let sourceAddress = i + 32;
do copy(sourceAddress, i);
let i = i + 1;
}
let i = 0;
while (i < size) {
if (currentConfig[i]) {
do Screen.setColor(true);
} else {
do Screen.setColor(false);
}
do Screen.drawPixel(i, currentRow);
let i = i + 1;
}
return;
}
method int rule_57(int left, int middle, int right) {
if (left = 1) { if (middle = 1) { if (right = 1) { return 0; } } }
if (left = 1) { if (middle = 1) { if (right = 0) { return 0; } } }
if (left = 0) { if (middle = 1) { if (right = 0) { return 0; } } }
if (left = 0) { if (middle = 0) { if (right = 1) { return 0; } } }
return 1;
}
method int rule_90(int left, int middle, int right) {
let middle = left + right;
if (middle = 1) {
return 1;
}
return 0;
}
method int rule_101(int left, int middle, int right) {
if (left = 1) { if (middle = 1) { if (right = 1) { return 0; } } }
if (left = 1) { if (middle = 0) { if (right = 0) { return 0; } } }
if (left = 0) { if (middle = 1) { if (right = 1) { return 0; } } }
if (left = 0) { if (middle = 0) { if (right = 1) { return 0; } } }
return 1;
}
method int rule_110(int left, int middle, int right) {
if (left = 1) { if (middle = 1) { if (right = 1) { return 0; } } }
if (left = 1) { if (middle = 0) { if (right = 0) { return 0; } } }
if (left = 0) { if (middle = 0) { if (right = 0) { return 0; } } }
return 1;
}
/** Calculates the next configuration based on currentConfig and
* currentRule */
method void step() {
var int i, limit;
var Array newConfig;
let newConfig = Array.new(size);
let currentRow = currentRow + 1;
if (currentRule = 57) {
// Calculate new state of first cell
let newConfig[0] = rule_57(0, currentConfig[0], currentConfig[1]);
// Calculate new state of last cell
let newConfig[511] = rule_57(currentConfig[510], currentConfig[511], 0);
// All the other cells
let i = 1; // Skip first cell and last cell
while (i < 511) {
let newConfig[i] = rule_57(currentConfig[i - 1], currentConfig[i], currentConfig[i + 1]);
let i = i + 1;
}
}
if (currentRule = 90) {
let newConfig[0] = rule_90(0, currentConfig[0], currentConfig[1]);
let newConfig[511] = rule_90(currentConfig[510], currentConfig[511], 0);
let i = 1;
while (i < 511) {
let newConfig[i] = rule_90(currentConfig[i - 1], currentConfig[i], currentConfig[i + 1]);
let i = i + 1;
}
}
if (currentRule = 101) {
let newConfig[0] = rule_101(0, currentConfig[0], currentConfig[1]);
let newConfig[511] = rule_101(currentConfig[510], currentConfig[511], 0);
let i = 1;
while (i < 511) {
let newConfig[i] = rule_101(currentConfig[i - 1], currentConfig[i], currentConfig[i + 1]);
let i = i + 1;
}
}
if (currentRule = 110) {
let newConfig[0] = rule_110(0, currentConfig[0], currentConfig[1]);
let newConfig[511] = rule_110(currentConfig[510], currentConfig[511], 0);
let i = 1;
while (i < 511) {
let newConfig[i] = rule_110(currentConfig[i - 1], currentConfig[i], currentConfig[i + 1]);
let i = i + 1;
}
}
do currentConfig.dispose();
let currentConfig = newConfig;
return;
}
}

View File

@@ -0,0 +1,370 @@
/** Manages the cellular automaton and interacts with the user. */
class CellularAutomatonController {
field CellularAutomaton automaton;
field Array config;
field Array rules;
field int numRules;
constructor CellularAutomatonController new() {
// Turned out it is easiest to manage the Automaton itself from here.
let automaton = CellularAutomaton.new();
// We need the cell state array to write the initial configuration
// by the user into it.
let config = automaton.getCurrentConfig();
// Array to switch between rules.
let numRules = 4;
let rules = Array.new(numRules);
let rules[0] = 57;
let rules[1] = 90;
let rules[2] = 101;
let rules[3] = 110;
return this;
}
method void dispose() {
// config gets deAllocated by CellularAutomaton!
do automaton.dispose();
do rules.dispose();
do Memory.deAlloc(this);
return;
}
/** Greets the user and guides through the initial configuration. */
method void initialConfiguration() {
do Screen.clearScreen();
do Screen.setColor(true);
do sayHello();
do printHelpInitialConfiguration();
do createInitialConfiguration();
do selectRule();
do finishConfiguration();
return;
}
/** Prints some dots on the screen to simulate loading, because why not? */
method void makeWaitDots() {
do Sys.wait(30);
do Output.printString(".");
do Sys.wait(30);
do Output.printString(".");
do Sys.wait(30);
do Output.printString(".");
do Sys.wait(30);
do Output.printString(" ");
return;
}
method void waitForEnter() {
var int key;
var boolean exit;
let key = 0;
let exit = false;
do Output.printString("<Enter> to continue. ");
while (~exit) {
while (key = 0) {
let key = Keyboard.keyPressed();
}
if (key = 128) { let exit = true; } // enter key
while (~(key = 0)) {
let key = Keyboard.keyPressed();
}
}
return;
}
method void sayHello() {
do Output.moveCursor(0, 0);
do Output.printString("> Welcome to cellular automaton 1D! ");
do makeWaitDots();
do Output.moveCursor(1, 0);
do Output.printString("> Let's configure the automaton");
do makeWaitDots();
return;
}
method void printHelpInitialConfiguration() {
do Output.moveCursor(3, 0);
do Output.printString("> Toggle the cells that should be alive with <space>");
do makeWaitDots();
do Output.moveCursor(4, 0);
do Output.printString("> Move with <h>/<l> and use <u>/<i> to change the step size");
do makeWaitDots();
do Output.moveCursor(6, 0);
do Output.printString("> stepSize = 1 - position = - activeCells = ");
return;
}
method void printStepSize(int n) {
do Output.moveCursor(6, 15);
do Output.printString(" ");
do Output.moveCursor(6, 15);
do Output.printInt(n);
return;
}
method void printCursorPosition(int n) {
do Output.moveCursor(6, 32);
do Output.printString(" ");
do Output.moveCursor(6, 32);
do Output.printInt(n);
return;
}
method void printActiveCellsj(int n) {
do Output.moveCursor(6, 52);
do Output.printString(" ");
do Output.moveCursor(6, 52);
do Output.printInt(n);
return;
}
method void createInitialConfiguration() {
var int key;
var boolean exit;
var int cursorPosition;
var int stepSize;
var int activeCells;
// Variables for printing the cell selction UI.
var int cursorY1, cursorY2, cellY1, cellY2;
let key = 0;
let cursorY1 = 90;
let cursorY2 = 95;
let cellY1 = 85;
let cellY2 = 88;
let stepSize = 1;
let cursorPosition = 0;
let activeCells = 0;
do printStepSize(stepSize);
do printCursorPosition(cursorPosition);
do printActiveCellsj(activeCells);
do Screen.drawLine(cursorPosition, cursorY1, cursorPosition, cursorY2);
let exit = false;
while (~exit) {
while (key = 0) {
let key = Keyboard.keyPressed();
}
if (key = 128) { // enter key
if (activeCells > 0) {
let exit = true;
} else {
do Output.moveCursor(9, 0);
do Output.printString("> Toggle at least one cell!");
}
} // enter key
if (key = 72) { // h key
do Screen.setColor(false);
do Screen.drawLine(cursorPosition, cursorY1, cursorPosition, cursorY2);
if ((cursorPosition - stepSize) > 0) {
let cursorPosition = cursorPosition - stepSize;
} else {
let cursorPosition = 0;
}
do Screen.setColor(true);
do Screen.drawLine(cursorPosition, cursorY1, cursorPosition, cursorY2);
do printCursorPosition(cursorPosition);
}
if (key = 76) { // l key
do Screen.setColor(false);
do Screen.drawLine(cursorPosition, cursorY1, cursorPosition, cursorY2);
if ((cursorPosition + stepSize) < 511) {
let cursorPosition = cursorPosition + stepSize;
} else {
let cursorPosition = 511;
}
do Screen.setColor(true);
do Screen.drawLine(cursorPosition, cursorY1, cursorPosition, cursorY2);
do printCursorPosition(cursorPosition);
}
if (key = 73) { // i key
if (stepSize < 512) {
let stepSize = stepSize * 2;
do printStepSize(stepSize);
}
}
if (key = 85) { // u key
if (stepSize > 1) {
let stepSize = stepSize / 2;
do printStepSize(stepSize);
}
}
if (key = 32) { // space key
if (config[cursorPosition]) { // cell is alive -> make dead
do Screen.setColor(false);
do Screen.drawLine(cursorPosition, cellY1, cursorPosition, cellY2);
let config[cursorPosition] = 0;
let activeCells = activeCells - 1;
} else { // cell is dead -> make alive
do Screen.setColor(true);
do Screen.drawLine(cursorPosition, cellY1, cursorPosition, cellY2);
let config[cursorPosition] = 1;
let activeCells = activeCells + 1;
}
do Screen.setColor(true);
do printActiveCellsj(activeCells);
}
while (~(key = 0)) {
let key = Keyboard.keyPressed();
}
}
return;
}
method void printRule(int n) {
do Output.moveCursor(12, 8);
do Output.printString(" ");
do Output.moveCursor(12, 8);
do Output.printInt(n);
return;
}
method void selectRule() {
var int i;
var int rule;
var int key;
var boolean exit;
let i = 1;
let rule = rules[i];
let exit = false;
do Output.moveCursor(10, 0);
do Output.printString("> Good. Let's select which rule you want to simulate");
do makeWaitDots();
do Output.moveCursor(11, 0);
do Output.printString("> Use <h>/<l> to switch between rules");
do makeWaitDots();
do Output.moveCursor(12, 0);
do Output.printString("> Rule selected. Confirm with <enter>.");
do printRule(rule);
while (~exit) {
while (key = 0) {
let key = Keyboard.keyPressed();
}
if (key = 128) { // enter key
let exit = true;
}
if (key = 72) { // h key -> prev rule
if (i > 0) {
let i = i - 1;
}
}
if (key = 76) {
if (i < (numRules - 1)) {
let i = i + 1;
}
}
let rule = rules[i];
do printRule(rule);
do automaton.setRule(rule);
while (~(key = 0)) {
let key = Keyboard.keyPressed();
}
}
return;
}
method void finishConfiguration() {
do Output.moveCursor(15, 0);
do Output.printString("> Okay, nice. We are ready to go");
do makeWaitDots();
do Output.moveCursor(16, 0);
do Output.printString("> Once you press enter you will no longer see the menu");
do makeWaitDots();
do Output.moveCursor(17, 0);
do Output.printString("> So remember the following keys (or at least <q> for quit)");
do makeWaitDots();
do Output.moveCursor(19, 0);
do Output.printString("> Controls: ");
do makeWaitDots();
do Output.moveCursor(20, 0);
do Output.printString("> <p>ause, <c>ontinue, <s>tep, <r>restart, <q>quit! ");
do Output.moveCursor(22, 0);
do Output.printString(" ");
do waitForEnter();
do Screen.clearScreen();
return;
}
method void run() {
var int key;
var boolean quit;
var boolean running;
var boolean restart;
var boolean step;
let quit = false;
let restart = false;
let running = true;
let step = false;
while (~quit) {
if (restart) {
do automaton.dispose();
let automaton = CellularAutomaton.new();
do initialConfiguration();
let quit = false;
let restart = false;
let running = true;
let step = false;
}
if (running) {
do automaton.draw();
do automaton.step();
}
if (step) {
do automaton.draw();
do automaton.step();
let step = false;
}
let key = Keyboard.keyPressed();
if (key = 82) { // r key
let restart = true;
}
if (key = 80) { // p key
let running = false;
}
if (key = 67) { // c key
let running = true;
}
if (key = 83) { // s key
if (~running) {
let step = true;
}
}
if (key = 81) { // q key
let quit = true;
}
while (~(key = 0)) {
let key = Keyboard.keyPressed();
}
}
return;
}
}

View File

@@ -0,0 +1,32 @@
/** Implements a cellular automaton.
*
* In the first state the user can define the initial configuration (the cells
* that are alive in the beginning. If the user is not sure about which cells
* to enable choosing the one in the middle (255/256) is ususually a good
* start.
*
* Next, the user selects the rule they want to simulate. A list of all rules
* is available on Wikipedia. If the user is not sure which rule they want Rule
* 90 is a good start to get the idea.
*
* https://en.wikipedia.org/wiki/Elementary_cellular_automaton
*
* In the second stage the user can select the initial configuration of the
* automaton. The keys 'h' and 'l' move the cursor one pixel to the left or
* right respectively. By pressing the space bar the user can toggle the
* current pixel. By pressing the 'r' key the simulation is started. Pressing
* 'q' ends the simulator.
*/
/** Initializes a new Cellular Automaton Game and runs it. */
class Main {
function void main() {
var CellularAutomatonController controller;
let controller = CellularAutomatonController.new();
do controller.initialConfiguration();
do controller.run();
do controller.dispose();
return;
}
}

View File

@@ -0,0 +1,20 @@
Cellular Automaton 1D
---------------------
This project implements a one dimensional cellular automaton. It is like the
famous *Game of Life*, but in 1D. If you are not familiar with the concept you
can read more on
[mathworld.wolfram.com](https://mathworld.wolfram.com/CellularAutomaton.html)
so I recommend simply try the application. It should be self explanatory and
you will be surprised.
The program runs in two stages. In the first stage the user configures the
initial population of the one automaton as well as the rule that is used for
creating the following populations. If you are not familiar with the rules
*Rule 90* with an initial cell in the middle is good enough.
In the second stage the program computes and visualizes the automaton. The
program can be paused with `p`, continued with `c`, single stepped with `s`,
reset with `r`, and terminated with `q`.
Have fun!

View File

@@ -0,0 +1,65 @@
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/09/Fraction/Fraction.jack
/** Represents the Fraction type and related operations. */
class Fraction {
field int numerator, denominator; // field = property = member variable.
/** Constructs a (reduced) fraction from the given numerator and denominator. */
constructor Fraction new(int x, int y) {
let numerator = x;
let denominator = y;
do reduce(); // reduces the fraction
return this; // a constructor is expected to return a reference to the new object
}
// Reduces this fraction.
method void reduce() {
var int g;
let g = Fraction.gcd(numerator, denominator);
if (g > 1) {
let numerator = numerator / g;
let denominator = denominator / g;
}
return;
}
/** Accessors. */
method int getNumerator() { return numerator; }
method int getDenominator() { return denominator; }
/** Returns the sum of this fraction and the other one. */
method Fraction plus(Fraction other) {
var int sum;
let sum = (numerator * other.getDenominator()) + (other.getNumerator() * denominator);
return Fraction.new(sum, denominator * other.getDenominator());
}
// More fraction-related methods (minus, times, div, etc.) can be added here.
/** Disposes this fraction. */
method void dispose() {
do Memory.deAlloc(this); // uses an OS routine to recycle the memory held by the object
return;
}
/** Prints this fraction in the format x/y. */
method void print() {
do Output.printInt(numerator);
do Output.printString("/");
do Output.printInt(denominator);
return;
}
// Computes the greatest common divisor of the given integers.
function int gcd(int a, int b) {
var int r;
while (~(b = 0)) { // applies Euclid's algorithm
let r = a - (b * (a / b)); // r = remainder of the integer division a/b
let a = b; let b = r;
}
return a;
}
}

View File

@@ -0,0 +1,16 @@
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/09/Fraction/Main.jack
// Computes the sum of 2/3 and 1/5.
class Main {
function void main() {
var Fraction a, b, c;
let a = Fraction.new(2,3);
let b = Fraction.new(1,5);
let c = a.plus(b); // Computes c = a + b
do c.print(); // Prints "13/15"
return;
}
}

View File

@@ -0,0 +1,14 @@
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/09/HelloWorld/Main.jack
/** Hello World program. */
class Main {
function void main() {
/* Prints some text using the standard library. */
do Output.printString("Hello world!");
do Output.println(); // New line
return;
}
}

BIN
projects/09/Jack OS API.pdf Normal file

Binary file not shown.

View File

@@ -0,0 +1,46 @@
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/09/List/List.jack
/** Represents a linked list of integers. */
class List {
field int data; // a list consists of a data field,
field List next; // followed by a list
/* Creates a List. */
constructor List new(int car, List cdr) {
let data = car; // the identifiers car and cdr are used in
let next = cdr; // memory of the Lisp programming language
return this;
}
/** Accessors. */
method int getData() { return data; }
method int getNext() { return next; }
/** Prints this list. */
method void print() {
var List current; // initializes current to the first item
let current = this; // of this list
while (~(current = null)) {
do Output.printInt(current.getData());
do Output.printChar(32); // prints a space
let current = current.getNext();
}
return;
}
/** Disposes this List by recursively disposing its tail. */
method void dispose() {
if (~(next = null)) {
do next.dispose();
}
// Uses an OS routine to recycle this object.
do Memory.deAlloc(this);
return;
}
// More list processing methods can come here.
}

View File

@@ -0,0 +1,17 @@
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/09/List/Main.jack
/** Demonstrates the use of the List abstraction. */
class Main {
function void main() {
// Creates and uses the list (2,3,5).
var List v;
let v = List.new(5,null);
let v = List.new(2,List.new(3,v));
do v.print(); // prints 2 3 5
do v.dispose(); // disposes the list
return;
}
}

View File

@@ -0,0 +1,15 @@
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/09/Square/Main.jack
/** Initializes a new Square Dance game and starts running it. */
class Main {
function void main() {
var SquareGame game;
let game = SquareGame.new();
do game.run();
do game.dispose();
return;
}
}

View File

@@ -0,0 +1,108 @@
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/09/Square/Square.jack
/** Implements a graphical square. */
class Square {
field int x, y; // screen location of the square's top-left corner
field int size; // length of this square, in pixels
/** Constructs a new square with a given location and size. */
constructor Square new(int Ax, int Ay, int Asize) {
let x = Ax;
let y = Ay;
let size = Asize;
do draw();
return this;
}
/** Disposes this square. */
method void dispose() {
do Memory.deAlloc(this);
return;
}
/** Draws the square on the screen. */
method void draw() {
do Screen.setColor(true);
do Screen.drawRectangle(x, y, x + size, y + size);
return;
}
/** Erases the square from the screen. */
method void erase() {
do Screen.setColor(false);
do Screen.drawRectangle(x, y, x + size, y + size);
return;
}
/** Increments the square size by 2 pixels. */
method void incSize() {
if (((y + size) < 254) & ((x + size) < 510)) {
do erase();
let size = size + 2;
do draw();
}
return;
}
/** Decrements the square size by 2 pixels. */
method void decSize() {
if (size > 2) {
do erase();
let size = size - 2;
do draw();
}
return;
}
/** Moves the square up by 2 pixels. */
method void moveUp() {
if (y > 1) {
do Screen.setColor(false);
do Screen.drawRectangle(x, (y + size) - 1, x + size, y + size);
let y = y - 2;
do Screen.setColor(true);
do Screen.drawRectangle(x, y, x + size, y + 1);
}
return;
}
/** Moves the square down by 2 pixels. */
method void moveDown() {
if ((y + size) < 254) {
do Screen.setColor(false);
do Screen.drawRectangle(x, y, x + size, y + 1);
let y = y + 2;
do Screen.setColor(true);
do Screen.drawRectangle(x, (y + size) - 1, x + size, y + size);
}
return;
}
/** Moves the square left by 2 pixels. */
method void moveLeft() {
if (x > 1) {
do Screen.setColor(false);
do Screen.drawRectangle((x + size) - 1, y, x + size, y + size);
let x = x - 2;
do Screen.setColor(true);
do Screen.drawRectangle(x, y, x + 1, y + size);
}
return;
}
/** Moves the square right by 2 pixels. */
method void moveRight() {
if ((x + size) < 510) {
do Screen.setColor(false);
do Screen.drawRectangle(x, y, x + 1, y + size);
let x = x + 2;
do Screen.setColor(true);
do Screen.drawRectangle((x + size) - 1, y, x + size, y + size);
}
return;
}
}

View File

@@ -0,0 +1,79 @@
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/09/Square/SquareGame.jack
/**
* Implements the Square Dance game.
* This simple game allows the user to move a black square around
* the screen, and change the square's size during the movement.
* When the game starts, a square of 30 by 30 pixels is shown at the
* top-left corner of the screen. The user controls the square as follows.
* The 4 arrow keys are used to move the square up, down, left, and right.
* The 'z' and 'x' keys are used, respectively, to decrement and increment
* the square's size. The 'q' key is used to quit the game.
*/
class SquareGame {
field Square square; // the square of this game
field int direction; // the square's current direction:
// 0=none, 1=up, 2=down, 3=left, 4=right
/** Constructs a new Square Game. */
constructor SquareGame new() {
// Creates a 30 by 30 pixels square and positions it at the top-left
// of the screen.
let square = Square.new(0, 0, 30);
let direction = 0; // initial state is no movement
return this;
}
/** Disposes this game. */
method void dispose() {
do square.dispose();
do Memory.deAlloc(this);
return;
}
/** Moves the square in the current direction. */
method void moveSquare() {
if (direction = 1) { do square.moveUp(); }
if (direction = 2) { do square.moveDown(); }
if (direction = 3) { do square.moveLeft(); }
if (direction = 4) { do square.moveRight(); }
do Sys.wait(5); // delays the next movement
return;
}
/** Runs the game: handles the user's inputs and moves the square accordingly */
method void run() {
var char key; // the key currently pressed by the user
var boolean exit;
let exit = false;
while (~exit) {
// waits for a key to be pressed
while (key = 0) {
let key = Keyboard.keyPressed();
do moveSquare();
}
if (key = 81) { let exit = true; } // q key
if (key = 90) { do square.decSize(); } // z key
if (key = 88) { do square.incSize(); } // x key
if (key = 131) { let direction = 1; } // up arrow
if (key = 133) { let direction = 2; } // down arrow
if (key = 130) { let direction = 3; } // left arrow
if (key = 132) { let direction = 4; } // right arrow
// waits for the key to be released
while (~(key = 0)) {
let key = Keyboard.keyPressed();
do moveSquare();
}
} // while
return;
}
}