More Projects

Continuation of my Java practice set and mini demos. This page mixes my own practice programs with selected creative exercises from the Princeton Java book. Each project includes the working version and (when relevant) a short reflection.

Project — Word Scoring (Java)

Reads a word and five start positions; scores 4-letter slices with letter/word multipliers.

import java.util.*;

public class MyProgram {
  public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    String word = scanner.nextLine()
                         .replaceAll(",", "")
                         .replaceAll(" ", "")
                         .toUpperCase();

    int p1 = scanner.nextInt();
    int p2 = scanner.nextInt();
    int p3 = scanner.nextInt();
    int p4 = scanner.nextInt();
    int p5 = scanner.nextInt();

    System.out.println(scoreWord(word, p1));
    System.out.println(scoreWord(word, p2));
    System.out.println(scoreWord(word, p3));
    System.out.println(scoreWord(word, p4));
    System.out.println(scoreWord(word, p5));
  }

  public static int scoreWord(String word, int start) {
    int total = 0;
    boolean wordMultiplied = false;
    int multiplier = 1;

    for (int i = 0; i < 4; i++) {
      int pos = start + i;
      char c = word.charAt(pos);
      int score = letterScore(c);

      if (pos % 3 == 0 && (pos / 3) % 2 == 1) {
        score *= 2;           // double letter
      } else if (pos % 5 == 0) {
        score *= 3;           // triple letter
      } else if (pos % 7 == 0 && !wordMultiplied) {
        multiplier *= 2;      // double word
        wordMultiplied = true;
      } else if (pos % 8 == 0 && !wordMultiplied) {
        multiplier *= 3;      // triple word
        wordMultiplied = true;
      }
      total += score;
    }
    return total * multiplier;
  }

  public static int letterScore(char letter) {
    if (letter == 'A' || letter == 'E') return 1;
    else if (letter == 'D' || letter == 'R') return 2;
    else if (letter == 'B' || letter == 'M') return 3;
    else if (letter == 'V' || letter == 'Y') return 4;
    else if (letter == 'J' || letter == 'X') return 8;
    return 0;
  }
}

Reflection: The handwritten version used charAt(i) instead of charAt(start + i), so the scoring squares didn't line up with the intended board positions.

Project — Turtle & Car (Java)

Simple OOP demo with two classes (Turtle and Car) and a runner.

// ThingsRunner.java
public class ThingsRunner {
  public static void main(String[] args) {
    Turtle turtle1 = new Turtle(15, 18, 0, 0, "Doruk");
    turtle1.Forward();
    turtle1.printOut();
    turtle1.moveTo(8, 8);
    turtle1.printOut();
    turtle1.setWidth(192);
    turtle1.setHeight(89);
    turtle1.printOut();

    Car car1 = new Car("Toyota", 180, 150, 0, 0);
    car1.drive(50);
    car1.printOut();
    car1.setWidth(200);
    car1.setHeight(160);
    car1.printOut();
    car1.openDoor();
    car1.printOut();
    car1.closeDoor();
    car1.printOut();
  }
}

// Turtle.java
public class Turtle {
  private double width, height, xPos, yPos;
  private String name;

  public Turtle(double width, double height, double xPos, double yPos, String name) {
    this.width = width;
    this.height = height;
    this.xPos = xPos;
    this.yPos = yPos;
    this.name = name;
  }

  public void Forward()       { xPos += 1; }
  public void Forward(int px) { xPos += px; }
  public void backward(int px){ xPos -= px; }
  public void moveTo(int x,int y){ xPos = x; yPos = y; }
  public void setWidth(double w){ width = w; }
  public void setHeight(double h){ height = h; }

  public void printOut() {
    System.out.println(toString());
  }

  public String toString() {
    return "Turtle{" +
           "name='" + name + '\'' +
           ", width=" + width +
           ", height=" + height +
           ", xPos=" + xPos +
           ", yPos=" + yPos +
           '}';
  }
}

// Car.java
public class Car {
  private String model;
  private double width, height, kmDriven, acceleration;
  private boolean doorOpen;

  public Car(String model, double width, double height,
             double kmDriven, double acceleration) {
    this.model = model;
    this.width = width;
    this.height = height;
    this.kmDriven = kmDriven;
    this.acceleration = acceleration;
    this.doorOpen = false;
  }

  public void drive(double distance){ kmDriven += distance; }
  public void setWidth(double w){ width = w; }
  public void setHeight(double h){ height = h; }
  public void openDoor(){ doorOpen = true; }
  public void closeDoor(){ doorOpen = false; }

  public void printOut() {
    System.out.println("Car{" +
                       "model='" + model + '\'' +
                       ", width=" + width +
                       ", height=" + height +
                       ", kmDriven=" + kmDriven +
                       ", acceleration=" + acceleration +
                       ", doorOpen=" + doorOpen +
                       '}');
  }
}

Reflection: In the handwritten draft, inconsistent method names and missing toString() made it hard to inspect the state. This version standardizes printing and encapsulates the fields.

Project — Leap Year & Loops

Checks if a given year is a leap year, then prints a line of * characters using a for loop.

import java.util.Scanner;

public class LoopsAndLeap {
  public static void main(String[] args) {
    int year = 2024;
    if (isLeap(year)) System.out.println(year + " is a leap year.");
    else              System.out.println(year + " is not a leap year.");

    Scanner scanner = new Scanner(System.in);
    int a = scanner.nextInt();

    for (int i = 0; i <= a; i++) {
      System.out.print("*");
    }
  }

  public static boolean isLeap(int year) {
    if (year % 400 == 0) return true;
    if (year % 100 == 0) return false;
    return year % 4 == 0;
  }
}

Reflection: The pen-and-paper version used = instead of == and had mismatched parentheses. Fixing the boolean logic made the leap year rule correct.

Click to view image

Project — Palindrome Checker

Reads an integer and checks whether its decimal representation is a palindrome.

import java.util.Scanner;

public class PalindromeCheck {
  public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    int q = scanner.nextInt();
    String str = "" + q;

    String rev = new StringBuilder(str).reverse().toString();
    if (str.equals(rev)) {
      System.out.println("It's a palindrome!");
    } else {
      System.out.println("Not a palindrome.");
    }
  }
}

Reflection: The original draft tried to index from the end with negative indices and used == for strings. Java needs equals() for content comparison.

Click to view image

Project — Comparison & Binary Converter

First compares three integers, then converts a 4-bit binary string to decimal.

import java.util.Scanner;

public class CompareAndBinary {
  public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);

    int a = scanner.nextInt();
    int b = scanner.nextInt();
    int c = scanner.nextInt();

    if (a != 0 || b != 0 || c != 0) {
      System.out.println("Values are not zero, continue.");
    }

    if (b != 0 && c != 0 && (a / b) == (b / c)) {
      System.out.println("All are equal.");
    }

    System.out.print("Enter a 4-bit binary number: ");
    String s = scanner.next();
    int total = 0;

    if (s.length() == 4) {
      char b3 = s.charAt(0);
      char b2 = s.charAt(1);
      char b1 = s.charAt(2);
      char b0 = s.charAt(3);

      if (b3 == '1') total += 8;
      if (b2 == '1') total += 4;
      if (b1 == '1') total += 2;
      if (b0 == '1') total += 1;

      System.out.println("Decimal value: " + total);
    } else {
      System.out.println("Please enter exactly 4 bits (e.g. 1010).");
    }
  }
}

Reflection: In the handwritten version, wrong logical operators and strange symbols (like ±) broke compilation. Using clear &&, == and explicit bit weights fixed it.

Click to view image

Creative Exercise — DayOfWeek (Switch Version)

Rewrite of the classic Zeller’s congruence exercise: prints Sunday, Monday, ... instead of an int 0–6 using a switch.

import java.util.Scanner;

public class DayOfWeekSwitch {
  public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    System.out.println("Please enter the day:");
    int day = scanner.nextInt();
    System.out.println("Please enter the month:");
    int month = scanner.nextInt();
    System.out.println("Please enter the year:");
    int year = scanner.nextInt();

    int y0 = year - (14 - month) / 12;
    int x  = y0 + y0 / 4 - y0 / 100 + y0 / 400;
    int m0 = month + 12 * ((14 - month) / 12) - 2;
    int d0 = (day + x + (31 * m0) / 12) % 7;

    String name;
    switch (d0) {
      case 0:  name = "Sunday";    break;
      case 1:  name = "Monday";    break;
      case 2:  name = "Tuesday";   break;
      case 3:  name = "Wednesday"; break;
      case 4:  name = "Thursday";  break;
      case 5:  name = "Friday";    break;
      case 6:  name = "Saturday";  break;
      default: name = "Unknown";   break;
    }

    System.out.println("Day of week: " + name);
  }
}

Creative Exercise — GymnasticsScorer.java

Reads 6 judge scores, discards the highest and lowest, and averages the remaining 4.

import java.util.Scanner;

public class GymnasticsScorer {
  public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    double[] scores = new double[6];

    for (int i = 0; i < 6; i++) {
      scores[i] = scanner.nextDouble();
    }

    double min = scores[0];
    double max = scores[0];
    double sum = 0.0;

    for (int i = 0; i < 6; i++) {
      if (scores[i] < min) min = scores[i];
      if (scores[i] > max) max = scores[i];
      sum += scores[i];
    }

    double finalSum = sum - min - max;
    double average = finalSum / 4.0;
    System.out.println("Final score = " + average);
  }
}

Creative Exercise — QuarterbackRating.java

Implements the NFL quarterback rating formula with proper clamping of intermediate values.

public class QuarterbackRating {
  private static double clamp(double v) {
    double hi = 475.0 / 12.0;
    if (v < 0.0) return 0.0;
    if (v > hi) return hi;
    return v;
  }

  public static void main(String[] args) {
    if (args.length != 5) {
      System.out.println("Usage: java QuarterbackRating A B C D E");
      return;
    }

    double A = Double.parseDouble(args[0]); // completions
    double B = Double.parseDouble(args[1]); // attempts
    double C = Double.parseDouble(args[2]); // yards
    double D = Double.parseDouble(args[3]); // touchdowns
    double E = Double.parseDouble(args[4]); // interceptions

    double W = (250.0 / 3.0) * (A / B - 0.3);
    double X = (25.0  / 6.0) * (C / B - 3.0);
    double Y = (1000.0 / 3.0) * (D / B);
    double Z = (1250.0 / 3.0) * (0.095 - E / B);

    W = clamp(W);
    X = clamp(X);
    Y = clamp(Y);
    Z = clamp(Z);

    double rating = (W + X + Y + Z) / 6.0;
    System.out.println("QB rating = " + rating);
  }
}

Creative Exercise — DecimalExpansion.java

Prints the decimal expansion of p / q, marking the repeating cycle in parentheses.

import java.util.HashMap;

public class DecimalExpansion {
  public static void main(String[] args) {
    if (args.length != 2) {
      System.out.println("Usage: java DecimalExpansion p q");
      return;
    }

    long p = Long.parseLong(args[0]);
    long q = Long.parseLong(args[1]);

    if (q == 0) {
      System.out.println("undefined (division by zero)");
      return;
    }

    StringBuilder sb = new StringBuilder();
    boolean negative = (p < 0) ^ (q < 0);
    long num = Math.abs(p);
    long den = Math.abs(q);

    if (negative && num != 0) sb.append('-');

    long integerPart = num / den;
    sb.append(integerPart);
    long remainder = num % den;

    if (remainder == 0) {
      sb.append(".0");
      System.out.println(sb.toString());
      return;
    }

    sb.append('.');
    StringBuilder frac = new StringBuilder();
    HashMap<Long, Integer> seen = new HashMap<>();
    int repeatIndex = -1;

    while (remainder != 0) {
      if (seen.containsKey(remainder)) {
        repeatIndex = seen.get(remainder);
        break;
      }
      seen.put(remainder, frac.length());
      remainder *= 10;
      long digit = remainder / den;
      remainder %= den;
      frac.append(digit);
    }

    if (repeatIndex == -1) {
      sb.append(frac);
    } else {
      sb.append(frac.substring(0, repeatIndex));
      sb.append('(');
      sb.append(frac.substring(repeatIndex));
      sb.append(')');
    }

    System.out.println(sb.toString());
  }
}

Creative Exercise — NPerLine.java (10–99)

Prints the integers from 10 to 99 with n integers per line (command-line argument).

public class NPerLine {
  public static void main(String[] args) {
    if (args.length != 1) {
      System.out.println("Usage: java NPerLine n");
      return;
    }

    int n = Integer.parseInt(args[0]);
    int count = 0;

    for (int i = 10; i <= 99; i++) {
      System.out.print(i + " ");
      count++;
      if (count % n == 0) {
        System.out.println();
      }
    }

    if (count % n != 0) {
      System.out.println();
    }
  }
}

Creative Exercise — NPerLine2.java (1–1000, Aligned)

Prints 1–1000 with n integers per line, aligning the numbers in columns.

public class NPerLine2 {
  public static void main(String[] args) {
    if (args.length != 1) {
      System.out.println("Usage: java NPerLine2 n");
      return;
    }

    int n = Integer.parseInt(args[0]);
    int count = 0;

    for (int i = 1; i <= 1000; i++) {
      System.out.printf("%4d", i);
      count++;

      if (count % n == 0) {
        System.out.println();
      }
    }

    if (count % n != 0) {
      System.out.println();
    }
  }
}

Creative Exercise — MakingChange.java

Uses the greedy algorithm to make change for N pennies using US coins.

public class MakingChange {
  public static void main(String[] args) {
    if (args.length != 1) {
      System.out.println("Usage: java MakingChange N");
      return;
    }

    int N = Integer.parseInt(args[0]);

    int quarters = N / 25;
    N %= 25;
    int dimes = N / 10;
    N %= 10;
    int nickels = N / 5;
    N %= 5;
    int pennies = N;

    System.out.println(quarters + " quarters");
    System.out.println(dimes + " dimes");
    System.out.println(nickels + " nickels");
    System.out.println(pennies + " pennies");
  }
}

Creative Exercise — Season.java

Prints the season in the northern hemisphere for a given month and day.

public class Season {
  public static void main(String[] args) {
    if (args.length != 2) {
      System.out.println("Usage: java Season M D");
      return;
    }

    int M = Integer.parseInt(args[0]);
    int D = Integer.parseInt(args[1]);
    String season;

    // Spring: March 21 – June 20
    if ((M == 3 && D >= 21) ||
        (M >  3 && M <  6)  ||
        (M == 6 && D <= 20)) {
      season = "Spring";
    }
    // Summer: June 21 – September 22
    else if ((M == 6 && D >= 21) ||
             (M >  6 && M <  9)  ||
             (M == 9 && D <= 22)) {
      season = "Summer";
    }
    // Fall: September 23 – December 21
    else if ((M == 9  && D >= 23) ||
             (M >  9  && M < 12)  ||
             (M == 12 && D <= 21)) {
      season = "Fall";
    }
    // Winter: December 22 – March 20
    else {
      season = "Winter";
    }

    System.out.println(season);
  }
}

Creative Exercise — Zodiac.java

Prints the Zodiac sign corresponding to a given month and day.

public class Zodiac {
  public static void main(String[] args) {
    if (args.length != 2) {
      System.out.println("Usage: java Zodiac M D");
      return;
    }

    int M = Integer.parseInt(args[0]);
    int D = Integer.parseInt(args[1]);
    String sign;

    if      ((M == 12 && D >= 22) || (M ==  1 && D <= 19)) sign = "Capricorn";
    else if ((M ==  1 && D >= 20) || (M ==  2 && D <= 17)) sign = "Aquarius";
    else if ((M ==  2 && D >= 18) || (M ==  3 && D <= 19)) sign = "Pisces";
    else if ((M ==  3 && D >= 20) || (M ==  4 && D <= 19)) sign = "Aries";
    else if ((M ==  4 && D >= 20) || (M ==  5 && D <= 20)) sign = "Taurus";
    else if ((M ==  5 && D >= 21) || (M ==  6 && D <= 20)) sign = "Gemini";
    else if ((M ==  6 && D >= 21) || (M ==  7 && D <= 22)) sign = "Cancer";
    else if ((M ==  7 && D >= 23) || (M ==  8 && D <= 22)) sign = "Leo";
    else if ((M ==  8 && D >= 23) || (M ==  9 && D <= 22)) sign = "Virgo";
    else if ((M ==  9 && D >= 23) || (M == 10 && D <= 22)) sign = "Libra";
    else if ((M == 10 && D >= 23) || (M == 11 && D <= 21)) sign = "Scorpio";
    else if ((M == 11 && D >= 22) || (M == 12 && D <= 21)) sign = "Sagittarius";
    else sign = "Unknown";

    System.out.println(sign);
  }
}

Creative Exercise — MuayThaiWeightClass.java

Reads a kickboxer’s weight in pounds and prints their Muay Thai weight class.

public class MuayThaiWeightClass {
  public static void main(String[] args) {
    if (args.length != 1) {
      System.out.println("Usage: java MuayThaiWeightClass weight");
      return;
    }

    int w = Integer.parseInt(args[0]);
    int code;

    if      (w < 112)           code = 0;
    else if (w <= 115)          code = 1;
    else if (w <= 118)          code = 2;
    else if (w <= 122)          code = 3;
    else if (w <= 126)          code = 4;
    else if (w <= 130)          code = 5;
    else if (w <= 135)          code = 6;
    else if (w <= 140)          code = 7;
    else if (w <= 147)          code = 8;
    else if (w <= 154)          code = 9;
    else if (w <= 160)          code = 10;
    else if (w <= 167)          code = 11;
    else if (w <= 175)          code = 12;
    else if (w <= 183)          code = 13;
    else if (w <= 190)          code = 14;
    else if (w <= 220)          code = 15;
    else                        code = 16;

    String klass;
    switch (code) {
      case 0:  klass = "Flyweight";             break;
      case 1:  klass = "Super flyweight";       break;
      case 2:  klass = "Bantamweight";          break;
      case 3:  klass = "Super bantamweight";    break;
      case 4:  klass = "Featherweight";         break;
      case 5:  klass = "Super featherweight";   break;
      case 6:  klass = "Lightweight";           break;
      case 7:  klass = "Super lightweight";     break;
      case 8:  klass = "Welterweight";          break;
      case 9:  klass = "Super welterweight";    break;
      case 10: klass = "Middleweight";          break;
      case 11: klass = "Super middleweight";    break;
      case 12: klass = "Light heavyweight";     break;
      case 13: klass = "Super light heavyweight"; break;
      case 14: klass = "Cruiserweight";         break;
      case 15: klass = "Heavyweight";           break;
      default: klass = "Super heavyweight";     break;
    }

    System.out.println(klass);
  }
}

Creative Exercise — ISBN2.java

Reads a 9-digit code, computes the ISBN-10 check digit, and prints the formatted ISBN.

public class ISBN2 {
  public static void main(String[] args) {
    if (args.length != 1) {
      System.out.println("Usage: java ISBN2 9digitcode");
      return;
    }

    String s = args[0];
    if (s.length() != 9) {
      System.out.println("Input must be 9 digits.");
      return;
    }

    int sum = 0;
    for (int i = 0; i < 9; i++) {
      int digit = s.charAt(i) - '0';
      sum += (i + 1) * digit;
    }

    int check = (11 - (sum % 11)) % 11;
    char checkChar = (check == 10) ? 'X' : (char)('0' + check);

    String part1 = s.substring(0, 1);
    String part2 = s.substring(1, 4);
    String part3 = s.substring(4, 9);

    System.out.println(part1 + "-" + part2 + "-" + part3 + "-" + checkChar);
  }
}

Creative Exercise — UPC.java

Reads an 11-digit UPC prefix and computes the 12th check digit according to the standard rule.

public class UPC {
  public static void main(String[] args) {
    if (args.length != 1) {
      System.out.println("Usage: java UPC 11digitcode");
      return;
    }

    String s = args[0];
    if (s.length() != 11) {
      System.out.println("Input must be 11 digits.");
      return;
    }

    int sumOdd = 0;
    int sumEven = 0;

    for (int i = 0; i < 11; i++) {
      int digit = s.charAt(i) - '0';
      if ((i + 1) % 2 == 1) sumOdd += digit;
      else                  sumEven += digit;
    }

    int total = sumOdd * 3 + sumEven;
    int check = (10 - (total % 10)) % 10;

    System.out.println("Full UPC: " + s + check);
  }
}

Creative Exercise — Triangle.java

Prints an N-by-N triangular pattern of * and ..

public class Triangle {
  public static void main(String[] args) {
    if (args.length != 1) {
      System.out.println("Usage: java Triangle N");
      return;
    }

    int N = Integer.parseInt(args[0]);

    for (int i = 0; i < N; i++) {
      for (int j = 0; j < N; j++) {
        if (j < i) System.out.print(". ");
        else       System.out.print("* ");
      }
      System.out.println();
    }
  }
}

Creative Exercise — Ex.java

Prints a (2N + 1)-by-(2N + 1) “X” pattern using two nested loops and one if-else statement.

public class Ex {
  public static void main(String[] args) {
    if (args.length != 1) {
      System.out.println("Usage: java Ex N");
      return;
    }

    int N = Integer.parseInt(args[0]);
    int size = 2 * N + 1;

    for (int i = 0; i < size; i++) {
      for (int j = 0; j < size; j++) {
        if (i == j || i + j == 2 * N) {
          System.out.print("* ");
        } else {
          System.out.print(". ");
        }
      }
      System.out.println();
    }
  }
}

Creative Exercise — Diamond.java

Prints a diamond pattern of size 2N + 1 by 2N + 1 using Manhattan distance.

public class Diamond {
  public static void main(String[] args) {
    if (args.length != 1) {
      System.out.println("Usage: java Diamond N");
      return;
    }

    int N = Integer.parseInt(args[0]);

    for (int i = -N; i <= N; i++) {
      for (int j = -N; j <= N; j++) {
        if (Math.abs(i) + Math.abs(j) <= N) {
          System.out.print("* ");
        } else {
          System.out.print(". ");
        }
      }
      System.out.println();
    }
  }
}
← Back to Projects Next: Projects 3 →