Showing posts with label CS106A Computer Methodology. Show all posts
Showing posts with label CS106A Computer Methodology. Show all posts

Thursday, September 1, 2011

CS106A Computer Methodology: Files Now Available for Download

I have added a new page named CS106A Assignments that contains the list of problems that I have completed for the course. There, you would be able to download the source code files quite easily.

So why did I decide to do so? Well, on the pages that I explain the problems one by one (example), I wasn't able to get the page anchors to work (stupid Blogger...), and as a result it became quite troublesome to get to the sections at the bottom of the page. Also, the SyntaxHighlighter would sometimes not work for certain codes (the codes would mess up), and it'd look ugly if I were to post the codes without them being highlighted by the Syntax Highlighter.

Anyway, if you want to download the files, don't hesitate to do so!

Wednesday, August 31, 2011

CS106A Programming Methodology Problem Solutions: Assignment 2

EDIT: Source code files now available for download!
For full problem descriptions, click here.

Assignment two has a total of six problems, and the problems are considerably harder than those in assignment one. This is partly because of the introduction of the graphics program, and partly because of the introduction of return methods (for it creates a lot more possibilities for program decomposition). On the bright side, in this assignment we are allowed to use variables as well as various keywords (e.g., "break"), making it a lot easier to program.

Anyway, without further ado, I'll get to the problems:

Problem 1: Quadratic (Quadratic.java):
For this problem, you have to ask the user for the coefficients of a quadratic equation. Then, using the quadratic formula, your program should output the solutions. Or, if the equation has no solution, then your program should output a line saying so.

click to enlarge

This problem is very straight-forward.
//File: Quadratic.java
// --------------------
//This program is a stub for the Quadratic problem, which finds the
// roots of the quadratic equation.

import acm.program.*;

public class Quadratic extends ConsoleProgram {

	
	private void userInput() {
		//Get user input:
		println("Enter coefficients for the quadratic equation ");
		a=readInt("a: ");
		b=readInt("b: ");
		c=readInt("c: ");
	}
	
	private void printSolutions() {
		int  discriminant=b*b-4*a*c; //calculates number inside the root
		double firstSolution, secondSolution;

		//Display appropriate messages based on whether there are solutions
		if (discriminant<0){
			println("This quadratic equation has no real roots.");
		} else {
			//Calculate solutions
			firstSolution=(-b+Math.sqrt(discriminant))/(2*a);
			secondSolution=(-b-Math.sqrt(discriminant))/(2*a);
			//Output solutions
			println("The first solution is: "+firstSolution);
			println("The second solution is: "+secondSolution);
		}
	}
	public void run() {
		userInput (); //get the coefficients
		printSolutions(); //output message
	}
	
	//Private instance variables
	private static int a,b,c;

}



Problem 2: Find Range (FindRange.java)
 This program reads in a list of integers, one per line, until a sentinel value of 0 (which could be easily changed to some other value) is entered. Then, the program would output the largest and smallest integers from the list, excluding the sentinel. If the very first line of input contains the sentinel value, then the program should indicate so. And if the second line of input contains the sentinel value, the program should output the first integer as both the largest and the smallest integer.

click to enlarge

Although the program itself is simple, it is quite easy to make some logic errors. In fact, I had to fix my code a couple of times, for it failed a few certain cases.

//File: FindRange.java
//--------------------
//This program is a stub for the FindRange problem, which finds the
//smallest and largest values in a list of integers.


import acm.program.*;

public class FindRange extends ConsoleProgram {

	private static final int SENTINEL=0;
	
	//Intro: description of program
	private void intro () {
		println ("This proram finds the largest and the smallest numbers.");
	}
	
	//Gets user input until sentinel is entered
	private void userInput () {
		int input;
		while (true) {
		    input=readInt ("? ");
		 
		    //Exits when sentinel is entered
		    if (input==SENTINEL) {
			break;                 
		    }
		 
		    //Update values of maxNum and minNum if appropriate
		    if (input>maxNum||maxNum==SENTINEL) {
			maxNum=input;
		    }

         if (minNum>input||minNum==SENTINEL) {
			minNum=input;
		    }


		}
	}
	
	private void printResults() {
		
		//If the first input is the sentinel, then the boolean expression will
		//be false and no values will be output. If not, then the largest and
		//smallest numbers will be output
		if (minNum!=SENTINEL) {
		    println ("smallest: "+minNum);
		    println ("largest: "+maxNum);
		
		} else {
		    println ("No value was entered.");
		}
		
	}
	public void run() {
		intro(); //outputs program description
		userInput(); //gets a list of numbers from user
		printResults(); //Outputs the largest and smallest nums
	}
	
	//Private instance variables:
	private static int maxNum=SENTINEL, minNum=SENTINEL;
}




Problem 3: Hailstone (Hailstone.java)
 This program is extremely simple. You first take an integer from the user, then,
  • if the number is odd, multiply the integer by 3, then add one to the product
  • if the number is even, divide it by two
You then repeat this process until the resulting number is 1. At this point, the program will output the number of steps that the process took.

// File: Hailstone.java
//--------------------
//This program is a stub for the Hailstone problem, which computes
//Hailstone sequence described in Assignment #2.

//A while loop will do...	

import acm.program.*;

public class Hailstone extends ConsoleProgram {


	public void run() {
		int num;
		int count=0 ;//The number of steps it takes
		num=readInt("Enter a number: ");
		
		while (num!=1) {
			if (num%2==0) {
				print (num+" is even so I take half: ");
				num=num/2;
			} else {
				print (num+" is odd, so I make 3n + 1: ");
				num=num*3+1;
			}
			println(num);
			count++;
			
		}
		println("This process took "+ count+ " to reach 1");
	}
}



Problem 4: Target (Target.java)
 For this program, you basically have to draw three filled ovals centered in the screen:

// File: Target.java
// ------------------
//This program is a stub for the Target problem, which displays
//a target by adding concentric circles to the canvas.

//The only thing problem is that the final size might be off by one pixel because
//of rounding

import java.awt.Color;
import acm.graphics.*;
import acm.program.GraphicsProgram;

public class Target extends GraphicsProgram {

	private static final double INCHES_1=1, INCHES_2=0.65, INCHES_3=0.3;// the three radii
	
	public void run() {
		//Specify the radius (in inches) and color for each circle:
		addFilledCricleToCenter (INCHES_1, Color.red);
		addFilledCricleToCenter (INCHES_2, Color.white);
		addFilledCricleToCenter (INCHES_3, Color.red);
	}
	
	//This method adds a filled circle (with specified color and size) to the center of the canvas
	private void addFilledCricleToCenter (double radiusInInches, Color col) {
		int radiusInPixels= convertToPixels(radiusInInches); //convert radius to pixels
		int diameter= radiusInPixels*2; //calculate diameter
		int startX= (getWidth()/2)- radiusInPixels;  //The leftmost x-location of the circle
		int startY= (getHeight()/2)- radiusInPixels; //the topmost y-location of the circle
		
		//create filled circle with the appropriate attributes, and add it to the canvas:
		add(fillOval(startX, startY, diameter, diameter, col));
		
	}
	
	private int convertToPixels (double inches){
		return (int)(Math.round(inches*72));
	}
	
	//This method creates a filled oval with the appropriate color, location and size
	private GOval fillOval (int x, int y, int width, int height, Color col) {
		GOval oval= new GOval(x, y, width, height); //Create oval with the appropriate size and loc.
		oval.setColor(col); //Change colour
		oval.setFillColor (col); //change colour
		oval.setFilled(true); //make it a filled circle
		return oval;
	}
}



Problem 5: GraphicsHierarchy (GraphicsHierarchy.java)
This program should output something similar to the image below:


The diagram should always be centered in the screen regardless of the width and height of the boxes. Also, the texts should be centered in the boxes. This was probably the program that I worked the longest on, for I am pretty slow at centering objects. It also took me quite a while to simplify the code and make it more general. But besides that, there wasn't any complicated logic needed to code this program.
//
// File: GraphicsHierarchy.java
//----------------------------
//This program is a stub for the GraphicsHierarchy problem, which
//draws a partial diagram of the acm.graphics hierarchy.


import acm.program.*;
import acm.graphics.*;

public class GraphicsHierarchy extends GraphicsProgram {
	
	private static final int BOX_HEIGHT=50, BOX_WIDTH=200;
	private static final int VERT_DISTANCE=40, HORI_DISTANCE=50; // The horizontal and vertical distance between any two adjacent boxes
	

	public void run() {
		assignValues(); //Assign values to the variables that hold the coordinates of the boxes
		
		drawBoxes();
		drawLines();
		
		addLabel("Program", centerBoxX, topBoxY);
		addLabel("ConsoleProgram", centerBoxX, bottomBoxY);
		addLabel("GraphicsProgram", centerBoxX-(BOX_WIDTH+HORI_DISTANCE), bottomBoxY);
		addLabel("DialogProgram", centerBoxX+(BOX_WIDTH+HORI_DISTANCE), bottomBoxY);
	}
	
	private void assignValues() {
		//the console window will only be created after the run method is called, and before that, the height and width will both be
		//zero. Therefore, to get the following three variables to have proper values, the values must be assigned in a method.
		topBoxY=getHeight()/2-(BOX_HEIGHT*2+VERT_DISTANCE)/2;
	    bottomBoxY=getHeight()/2+ VERT_DISTANCE/2;
		centerBoxX=(getWidth()-BOX_WIDTH)/2;
	}
	
	//Add the labels. StartX and startY are the coordinates of the top-left corner of the rectangle that they're in
	private void addLabel(String labelText, int startX, int startY) {
		GLabel lab= new GLabel (labelText, startX, startY); //Create label
		lab.move ((BOX_WIDTH-lab.getWidth())/2,(BOX_HEIGHT+lab.getAscent())/2 ); //move to center	
		add(lab); //add to canvas
	}
	
	//Draw the lines
	private void drawLines() {
		//All three lines branch out of one point, and startX and startY are the coordinates of that point
		int startX=getWidth()/2;
		int startY=(int)((getHeight()-VERT_DISTANCE)/2);
		
		//Draw the three lines
		for(int i=-1; i<=1; i++) {
			add(new GLine(startX, startY, startX+i*(BOX_WIDTH+HORI_DISTANCE), startY+VERT_DISTANCE));
		}
		
	}
	
	//Draws the four boxes
	private void drawBoxes () {
		//The box at the top:
		add(new GRect(centerBoxX, topBoxY, BOX_WIDTH, BOX_HEIGHT));
		
		//The boxes at the bottom
		for (int i=-1; i<=1; i++) {
			add(new GRect(centerBoxX+(BOX_WIDTH+HORI_DISTANCE)*i, bottomBoxY, BOX_WIDTH, BOX_HEIGHT));
		}
	}
	
	//Private instance variables:
	//These are the variables that hold the coordinates of the boxes. See "assignValues" method for more info.
	private static int topBoxY;
	private static int bottomBoxY;
	private static int centerBoxX;
}


Problem 6: Pyramid (Pyramid.java)
With the specified brick width, brick height, and number of rows, the program should output a pyramid like the one below, centered in the screen.

// File: Pyramid.java
// ------------------
// This program is a stub for the Pyramid problem, which draws
// a brick pyramid.


import acm.graphics.*;
import acm.program.*;

public class Pyramid extends GraphicsProgram {
	
	private static int BRICK_WIDTH=18;
	private static int BRICK_HEIGHT=10;
	private static int BRICKS_IN_BASE=35;
	
	public void run() {
		
		//Draw the rectangles row by row, from the bottom row to the top row
		for (int i=BRICKS_IN_BASE; i>=1; i--) {
			int yLocation=getHeight()-(BRICKS_IN_BASE-i+1)*BRICK_HEIGHT-1;
			fillRow (yLocation, i);
		}
	}
	
	private void fillRow (int yLocation, int numOfBricks) {
		int startX=(getWidth()- numOfBricks*BRICK_WIDTH)/2; //the x-Location of the leftmost brick
		//Use for loop to draw the bricks
		//!!!Code continued at the bottom because of the syntaxHighlighter's glitch!
This is the rest of the code:
for (int i=0; i<numOfBricks; i++) { add(new GRect(startX+i*BRICK_WIDTH, yLocation, BRICK_WIDTH, BRICK_HEIGHT)); } } }

Monday, August 15, 2011

CS106A Programming Methodology Problem Solutions: Assignment 1

EDIT: Source code files now available for download!
For the full assignment problem descriptions, click here.

Assignment one has four problems, and to be honest none of them is hard. Still, it took me quite a long time to complete all of them, for there were such strict restrictions on the operators and programming structures that I could use. For instance, I wasn't even allowed to have variables, do-while loops, or the ! and && operators! As a result, some of the solutions weren't as neat as they could have been.

 Anyway, here are my solutions to the problems:
 Problem 1: Collect Newspaper Karel (CollectNewspaperKarel.java)



This problem is extremely simple. As shown in the image above, you basically have to write a program that will let Karel pick up the beeper and return to his orginial position. The world will always be the same, so there's no need to include any if structure at all. Just a straight-forward program that directly tells Karel what to do.
import stanford.karel.*;

public class CollectNewspaperKarel extends SuperKarel {

 public void run() {
   moveToNewsPaper();
   pickUpNewsPaper();
   returnToStartingPoint();
  
 }
 
 //Karel picks up the newspaper
 private void pickUpNewsPaper() {
  pickBeeper();

 }
  
 //Karel returns to original position
 private void returnToStartingPoint() {
  turnAround();
  for (int i=0; i<3; i++) {     move();   }      turnRight();   move();   turnRight();     }    //Karel exits the room and gets to the newspaper  private void moveToNewsPaper() {   turnRight();   move();   turnLeft();      for (int i=0; i<3; i++) {     move();   }     }  }  


Problem Two: Stone Mason Karel (StoneMasonKarel.java)


This problem is also very straight-forward. You basically have to create a program that will make Karel fill up the columns (i.e., 1,5,9,13...).
import stanford.karel.*;

public class StoneMasonKarel extends SuperKarel {

 public void run() {
  repairCurrentColumn();
  while (frontIsClear()){
   repairNextColumn();
  }
 }

//Pre-condition: Karel is at the upper-end of a column, facing North
//Post-condition: Karel is at the lower-end of a column, facing east
public void backToOriginalPosition(){
  turnAround();
  while(frontIsClear()){
   move();
  }
  turnLeft();
}

//Pre-condition: Karel is at the lower-end of a column that may needs to be repaired, facing east
//Post-condition: Karel is at the same position, and the entire column is repaired
public void repairCurrentColumn (){
  turnLeft();
 
  while (frontIsClear()){
   if (noBeepersPresent()){
    putBeeper();
   }
   move();
  }
  //This is to repair the last bit of the column
  if (noBeepersPresent()){
   putBeeper();
  }
 
  backToOriginalPosition();
 
}

/*Pre-condition: Karel is at the lower-end of a certain column that has already
  been repaired, and there is an unrepaired column to the right
 *Post-condition: Karel is has moved to and repaired the adjacent column that is
  east of that certain column, and is at the lower-end of it
 */
public void repairNextColumn(){
  goToNextColumn();
  repairCurrentColumn();
}

//Pre-condition: Karel is facing east, at the bottom on a column, and there is another
//column to the right
//Post-condition: Karel has moved eastward, onto the next column
public void goToNextColumn(){
  for (int i=0; i<4; i++){
   move();
  }
}
}



Problem 3: Checkerboard Karel (CheckerboardKarel.java)


For this problem, you have to create a checker pattern for any given world (even a 1*1 square). Took me a little while to figure out how to decompose this problem.
import stanford.karel.*;

public class CheckerboardKarel extends SuperKarel {

 public void run() {
  finishRow();
  while (frontIsClear()){ //If there's a next row, then finish that row
   goToNextRow();
   if (frontIsClear()){ //In case that the world is a one column-world
    finishRow();
   }
   
  }
   
 }
 
 //Pre-condition: Karel is at a square where a beeper needs to be in place
 //Post-condition: The whole row that the square is in is now completed.
 public void finishRow(){
  putBeeper();
  
  //Put down a beeper every other step
  while (frontIsClear()){
   move();
   
   //If structure in place to ensure that
   //Karel doesn't run into a wall
   if (frontIsClear()){
    move();
    putBeeper();
   }
  }
  faceNorth();
 }
 
 //Pre-Condition: Karel is facing east or west
 //Post-Condition: Karel is facing north
 public void faceNorth (){
  if (facingEast()){
   turnLeft();
  }
  else{
   if (facingWest()){
    turnRight();
   }
  }
 }
 
  //pre-condition: Karel is facing north, with at least
  //a wall beside it
 
  //Post-Conidtion: Karel is facing east or west, with a wall
  //right behind it
                   
 public void turn (){
  
  //The following assignment
  if (leftIsClear()){
   turnLeft();
  }else{
   turnRight();
  }
 }
   
    
  
 
 
 //Pre-condition: There is at least one row above the row that Karel is currently in
 //Post-condition: Karel has moved onto the next row, to a space that needs a beeper
 //                (Exception: when it is in a one-column world, he may move by two rows
 //                instead)
 
 //How this method works:
 //Suppose Karel is at point K. If there is a beeper at point K, Karel will move to
 //point X. Otherwise, it will move to point Y
 //...........XY
 //............K
 
 public void goToNextRow(){
  if (noBeepersPresent()){
   move();
   turn();
  }
  else{
   move();
   turn();
   
   /*If this condition is not satisfied, it means that the world is only
   one-column wide. In this case, Karel will move onto the next available row
   (if there is one)*/
   if (frontIsClear()) {
    move();
   }
   else{
    //Move onto the next row if there is one
    faceNorth();
    if (frontIsClear()) {
     move();
    }
    
   }
    
  }
 }

}



Problem Four: Midpoint Finding Karel (MidpointFindingKarel.java)


The goal of this program is to be able to let Karel find and stop at the midpoint of any given width. The first time it took me more than 1.5 hours to finish all the coding, so I was beyond miserable when the whole file got accidentally deleted. Fortunately, the second time it only took me about 10 to 15 minutes.
import stanford.karel.*;

public class MidpointFindingKarel extends SuperKarel {
//My algorithm is quite simple. running the program and reading the comment lines
//should be enough for you to understand
 
public void run() {
  layBeepers(); //Put one beeper in each square in the row
  cleanUpBeepers(); //Alternately remove one beeper from each end. This way Karel will
         //be removing the beeper at the middle square last
  putBeeper(); //Put one beeper back in the middle square

}

//Put one beeper in each square of the row
public void layBeepers(){
  putBeeper();
  while (frontIsClear()){
   move();
   putBeeper();
  }
  turnAround(); //Turn around so that Karel is facing the center
}

//Only move if front is clear
public void moveIfSafe(){
  if(frontIsClear()){
   move();
  }
}

//Pre-condition: Karel is facing west or east
//Post-condition: Karel is facing south
public void turnSouth(){
  if(facingEast()){
   turnRight();
  }else{
   turnLeft();
  }
 
}

//Turn around, move one space (if possible), and then pick up the beeper (if possible)
public void turnAroundAndPickBeeper(){
  turnAround();
  moveIfSafe();
  if (beepersPresent()){
   pickBeeper();
  }
}

//The purpose of this method is basically to let Karel pick up a beeper from the opposite end
public void pickUpEndBeeper(){
  while (beepersPresent()){//Karel keeps walking until there isn't a beeper at his
                        //location or until he reaches the wall
   if (frontIsClear()){
    move();
   }
   else{
    pickBeeper();
    turnSouth();//Turning south is a signal for "already picked up a beeper)
   }
  }
 
  if (frontIsClear()){
   turnAroundAndPickBeeper();//Turn around and pick up the beeper located at the end
  }
  else{
   if (facingSouth()) //If Karel has already picked up a beeper, then he will
                   //simply change direction
   {
    faceCenter();
   }
   else{
    turnAroundAndPickBeeper();//If not, he will pick up the beeper at the end
   }
   
  }
  
}

//Let Karel face the center
public void faceCenter(){
  if (rightIsClear()){
   turnRight();
  }else{
   turnLeft();
  }

 
}

//Karel alternately picks up a beeper from each end. Eventually, Karely will stop at the
//middle square
public void cleanUpBeepers(){
  while (notFacingSouth()){
  
   pickUpEndBeeper();
   moveIfSafe();
   if (noBeepersPresent()){//If this is satisfied, it means that all beepers have been
                        //cleared
    //Move back to the middle square:
    turnAround();
    moveIfSafe();
    turnSouth();//Since no variable can be used, facing south is the only way
                //to break out of the while loop
   }
  }
 
}
}