Difficulty: Intermediate to Advanced
Prerequisites: Java Expression Evaluation (Doc 1), Code Tracing (Doc 2), comfort with writing methods, loops, and conditionals.
The programming section of the CS 312 exam asks you to write complete methods from scratch. Questions cover the Critter simulator pattern, file processing with Scanner, array manipulation (both creating new arrays and modifying in place), ArrayList element removal, and 2D array traversal. These problems test whether you can translate a problem description into working Java code under time pressure. Each problem restricts which Java classes and methods you may use.
The programming questions ask you to write methods that manipulate arrays in place, process file data with Scanner, remove elements from ArrayLists, implement Critter subclasses with state, and traverse 2D arrays with a greedy algorithm. The common thread is careful index management and knowing which built-in methods are allowed.
Critter (abstract class)
A base class for a grid-based simulation. Subclasses override methods like fight(), getMove(), eat(), getColor(), and toString() to define behaviour. The simulator calls these methods at specific times; you do not call them yourself.
Think of it as: you define the rules for how your creature behaves, and the simulator runs the game.
Scanner line-by-line processing
Using Scanner.hasNextLine() and Scanner.nextLine() to process a file one line at a time, then creating a second Scanner on each line to parse its individual tokens. hasNextInt() distinguishes numbers from other tokens.
In-place array modification
Changing the contents of an existing array without creating a new one. Typically involves shifting elements (right-to-left or left-to-right) to make room or fill gaps.
Reversed sublist (new array creation)
Creating a new array from a slice of an existing one, with elements in reverse order. The start index is inclusive, the stop index is exclusive (matching String.substring() convention).
ArrayList removal pattern
When removing elements from an ArrayList while iterating, either iterate backwards (so removals do not shift unvisited elements) or do not increment the index after a removal (since the next element slides into the current position).
Greedy algorithm (2D array traversal)
At each step, the robot moves to the adjacent cell (up, down, or right) with the highest value. Ties are broken in order: up, down, right. The robot never revisits a cell and stops upon entering the rightmost column.
The JumpingBean tracks state across method calls using instance variables. The key insight: the simulator calls fight() and getMove() at different times, and the JumpingBean must infer whether it won a fight by observing whether getMove() is called after fight().
Instance variables needed: movesRemaining (how many moves left in the current burst), currentDirection (NORTH or WEST), fought (whether a fight just happened), totalMoves (the base number of moves, starts at 0 and increases by 2 each win).
fight(): if currently sitting still (movesRemaining == 0), return SCRATCH. If currently moving (would move on next getMove call), return FORFEIT.
getMove(): if fought is true, the bean won (since getMove was called after fight). Pick a random direction, set moves, clear the flag. If movesRemaining > 0, decrement and return the direction. Otherwise return CENTER.
Random direction: Math.random() < 0.5 ? Direction.NORTH : Direction.WEST.
The printMoney method processes a file where each line has a name (one or more non-integer tokens) followed by pairs of integer and symbol.
Outer loop: while (sc.hasNextLine()) reads each line.
Create a new Scanner on the line: Scanner lineSc = new Scanner(sc.nextLine()).
Read the name: while !lineSc.hasNextInt(), append tokens to the name string.
Read pairs: while lineSc.hasNextInt(), read the int, then read the symbol. Check if the symbol equals "K", "S", or "G" and accumulate the value accordingly.
Convert everything to Galleons: totalKnuts / 29.0 / 17.0 for knuts, totalSickles / 17.0 for sickles, galleons as-is.
Edge case: the output uses "Galleon" (singular) when the total is exactly 1.0, "Galleons" otherwise.
Create and return a new array containing elements from startIndex (inclusive) to stopIndex (exclusive) in reverse order.
public static int[] getReversedSubList(int[] vals,
int startIndex, int stopIndex) {
int[] result = new int[stopIndex - startIndex];
for (int i = 0; i < result.length; i++) {
result[i] = vals[stopIndex - 1 - i];
}
return result;
}The trick: result[0] gets vals[stopIndex - 1], result[1] gets vals[stopIndex - 2], and so on.
Shift existing elements right, then copy elements from the second array into the front. No new arrays allowed.
public static void insertElementsAtFront(int[] one,
int[] two) {
int numToInsert = Math.min(two.length, one.length);
// Shift existing elements right
for (int i = one.length - 1; i >= numToInsert; i--) {
one[i] = one[i - numToInsert];
}
// Copy from two into the front
for (int i = 0; i < numToInsert; i++) {
one[i] = two[i];
}
}The shift must go right-to-left to avoid overwriting. Only Math.min(two.length, one.length) elements from two can fit. Note: Math.min may not be allowed on some exams; if so, use a conditional.
Remove strings that contain a target char in the first n characters.
public static int removeValues(ArrayListThe critical pattern: do not increment i after a removal, because the next element slides into position i.
The robot starts at (initialRow, 0), collects coins, and moves to the adjacent cell (up, down, right) with the most coins. Tie-breaking order: up, down, right. Mark visited cells (set to 0 or negative) to prevent revisiting.
public int coinsCollected(int[][] mat, int initialRow) {
int row = initialRow;
int col = 0;
int total = mat[row][col];
mat[row][col] = 0;
while (col < mat[0].length - 1) {
int bestVal = -1;
int bestRow = row;
int bestCol = col + 1;
// Check up
if (row - 1 >= 0 && mat[row-1][col] > bestVal) {
bestVal = mat[row-1][col];
bestRow = row - 1; bestCol = col;
}
// Check down
if (row + 1 < mat.length && mat[row+1][col] > bestVal) {
bestVal = mat[row+1][col];
bestRow = row + 1; bestCol = col;
}
// Check right
if (mat[row][col+1] > bestVal) {
bestVal = mat[row][col+1];
bestRow = row; bestCol = col + 1;
}
row = bestRow;
col = bestCol;
total += mat[row][col];
mat[row][col] = 0;
}
return total;
}Setting visited cells to 0 works because all values start greater than 0. The tie-breaking order (up, down, right) is handled by using > (strict greater than) when checking each direction in order: if up ties with down, up was checked first and wins.
Students often increment the loop index after removing an element from an ArrayList, which skips the element that slid into the removed position. Either hold the index steady after a removal, or iterate backwards.
Students often shift array elements left-to-right when inserting at the front, which overwrites values before they are moved. Always shift from the far end when making room.
Students often forget that startIndex == stopIndex means an empty sublist (zero-length array), not an error.
Students often check only right and down in the 2D greedy problem, forgetting that the robot can move up. The robot can move in any direction except left.
Students often use Scanner.next() when they need Scanner.nextLine(), or vice versa. next() reads one token; nextLine() reads the rest of the line. Mixing them without understanding the newline buffer causes bugs.
Students often forget that the Critter simulator controls when methods are called. You do not call fight() or getMove() yourself; you only define what they return.
True or false: When removing elements from an ArrayList in a forward loop, you should always increment the index. (False. Skip the increment when you remove, because the next element slides into the current index.)
Fill in the blank: getReversedSubList({1,2,3,4,5}, 1, 4) returns ___. ({4, 3, 2})
True or false: In the greedy robot problem, when up and right tie, the robot moves right. (False. Tie-breaking order is up, then down, then right.)
True or false: new int[stopIndex - startIndex] gives the correct size for a sublist from startIndex (inclusive) to stopIndex (exclusive). (True.)
Fill in the blank: When shifting elements right to insert at the front, you should iterate from index ___ to index ___. (From the last index down to the number of elements being inserted.)
Q: What does getReversedSubList({0,1,2,3,4,5}, 0, 6) return?
A: {5, 4, 3, 2, 1, 0}. The full array reversed.
Q: What does getReversedSubList({0,1,2,3,4,5}, 2, 2) return?
A: {}. Start equals stop, so the sublist is empty.
Q: After insertElementsAtFront({5,12,6,3,9,0,-2}, {4,-3,2}), what does the first array contain?
A: {4, -3, 2, 5, 12, 6, 3}. The last 3 elements of the original (9, 0, -2) are pushed out.
Q: After insertElementsAtFront({2,6,1}, {17,19,37,41}), what does the first array contain?
A: {17, 19, 37}. The second array is larger, so only the first 3 elements fit.
Q: Given the ArrayList ["CK", "Omer", "Carla", "Fatima", "Anthony", "Aish", "Hailey", "Bri", "Dayanny", "Chris", "Olivia"], target char 'a', and n = 3, what is the result of removeValues?
A: Returns 4. The ArrayList becomes ["CK", "Omer", "Anthony", "Aish", "Bri", "Chris", "Olivia"]. Removed: "Carla" (has 'a' at index 1), "Fatima" (has 'a' at index 1), "Hailey" (has 'a' at index 1), "Dayanny" (has 'a' at index 1). Note: "Anthony" stays because its first 3 characters are "Ant", which contain no lowercase 'a'. "Aish" stays because its first 3 characters are "Ais", no lowercase 'a' (the 'A' is uppercase).
Q: In the greedy robot problem, starting at row 0 in the grid [[6,10,4,5,3],[1,1,2,3,2],[5,7,30,5,2],[2,1,10,2,10],[2,2,5,8,1]], how many coins does the robot collect?
A: 45 coins. Path: (0,0)=6, (0,1)=10, (0,2)=4, then down to (1,3)? No, let us trace carefully. From (0,0) with value 6: up is out of bounds, down is (1,0)=1, right is (0,1)=10. Move right. From (0,1): up OOB, down (1,1)=1, right (0,2)=4. Move right. From (0,2): up OOB, down (1,2)=2, right (0,3)=5. Move right. From (0,3): up OOB, down (1,3)=3, right (0,4)=3. Tie between down and right; prefer down. Move to (1,3)=3. From (1,3): up (0,3) visited=0, down (2,3)=5, right (1,4)=2. Move down to (2,3)=5. From (2,3): up (1,3) visited=0, down (3,3)=2, right (2,4)=2. Tie between down and right; prefer down. Move to (3,3)=2. From (3,3): up (2,3) visited=0, down (4,3)=8, right (3,4)=10. Move right to (3,4)=10. That is the rightmost column, so stop. Total: 6+10+4+5+3+5+2+10 = 45.
The programming problems synthesise everything from the other two study notes. Expression evaluation rules (Doc 1) determine how arithmetic and comparisons behave inside your methods. Code tracing skills (Doc 2) help you mentally verify your solution by walking through it with sample data before writing. The Critter pattern is a practical exercise in inheritance and overriding, and the Scanner problem combines file I/O with String manipulation.
Java Critter assignment, JumpingBean state machine, Scanner file processing Java, hasNextInt hasNextLine, getReversedSubList array, insertElementsAtFront in-place shift, ArrayList remove while iterating, 2D array greedy algorithm, CS 312 UT Austin programming exam, array sublist reverse, off-by-one error, start inclusive stop exclusive, shift elements array Java, greedy tie-breaking, robot coin collector