The 50 Programs Challenge — Muscle Memory

Reading Java without typing Java is memorization theater. This is the actual work of Phase 01: fifty small programs, hand-typed, no AI, no copy-paste, no Stack Overflow for syntax. Concept lookups are fine — syntax lookups are the thing you are trying to eliminate.

The programs are grouped in five sets of ten. Each program is small (5–30 minutes) but forces one specific slice of the language into your fingers. Do them in order. Do not skip. If a program takes over the estimated time by 2×, you found a hole — fill it before moving on.

The rules

  1. No AI assistant. Copilot off, Claude tab closed, ChatGPT closed. Even for autocomplete.

  2. No copy-paste of code, even from your own earlier programs. Retype.

  3. You may read the docs (https://docs.oracle.com/en/java/javase/21/docs/api/). You may not search “how to do X in Java”.

  4. Each program lives in its own file or its own class inside main. One repo: java-50-programs.

  5. Log time-taken per program in a LOG.md. After all 50, look at the outliers — those are the areas to shore up.

  6. Write JUnit or a main-based smoke test for every program. No exception — the point is verified correctness, not “looks right”.

Repo layout suggestion

java-50-programs/
 ├── pom.xml                       (Maven, Java 21, JUnit 5)
 ├── LOG.md                        (per-program time log)
 └── src/main/java/dev/raghul/
      ├── set1_warmup/             P01..P10
      ├── set2_collections/        P11..P20
      ├── set3_io/                 P21..P30
      ├── set4_oop/                P31..P40
      └── set5_mixed/              P41..P50

Set 1 — Strings & Arrays Warmup (10 programs, ~90 min)

Basic syntax reflex. Loops, arrays, String, StringBuilder.

#

Program

What it tests

Acceptance

Est

P01

Reverse a string without StringBuilder.reverse()

char-array, loops, index math

"hello""olleh"; empty & single-char cases

5 min

P02

Check if a string is a palindrome (ignore case, ignore non-alphanumeric)

Character.isLetterOrDigit, two-pointer

"A man, a plan, a canal: Panama" → true

8 min

P03

Count vowels and consonants in a string

switch on char, char classification

Returns two ints; test with mixed case

5 min

P04

Find the first non-repeating char in a string

LinkedHashMap<Character, Integer>

"swiss"'w'; none case returns Optional.empty

10 min

P05

Fizz-buzz 1..100 using switch expression

switch expression on modulo booleans

Exact expected output

5 min

P06

Print all prime numbers up to N

Sieve of Eratosthenes with boolean[]

N=30 → 2,3,5,7,11,13,17,19,23,29

10 min

P07

Rotate an int array left by K positions in place

reverse trick or extra array

[1,2,3,4,5] k=2 → [3,4,5,1,2]; k > n handled

10 min

P08

Find the missing number in an array of 1..N with one missing

sum formula OR XOR trick

Two implementations, both O(n)

8 min

P09

Compress a string: "aaabbc""a3b2c1"; if compressed >= original, return original

StringBuilder, run counting

Correct behavior on both paths

10 min

P10

Given a 2D int array (matrix), print its transpose

nested loops, index swap

Non-square matrix works

8 min


Set 2 — Collections Drills (10 programs, ~2 hours)

Every List, Set, Map, Queue, Deque API in your fingers.

#

Program

What it tests

Acceptance

Est

P11

Word frequency counter from a List<String> using merge

Map.merge, printing sorted by count

Output stable, ties broken alphabetically

10 min

P12

Find top-K frequent words using PriorityQueue

min-heap of size K, custom Comparator

O(n log k), test with k=3

15 min

P13

Group a List<Person> by city into Map<String, List<Person>> — two versions

computeIfAbsent and Collectors.groupingBy

Same output both ways

10 min

P14

LRU cache with capacity 5 by extending LinkedHashMap

accessOrder=true, removeEldestEntry

Test sequence: put 6 items, verify eviction of eldest-accessed

15 min

P15

Detect duplicates in a List<Integer> using HashSet in one pass

add returns false on duplicate

Test with all unique and with duplicates

5 min

P16

Merge two sorted List<Integer> into a new sorted list

two-pointer, iterators

No Collections.sort; O(n+m)

10 min

P17

Given List<String>, find longest common prefix

vertical scan or String::compareTo

["flower","flow","flight"]"fl"

10 min

P18

Rotate a Deque<Integer> right by K using ArrayDeque

pollLast, offerFirst

k > size handled with modulo

8 min

P19

Given List<Integer> return a Map<Boolean, List<Integer>> split by even/odd

Collectors.partitioningBy

Verify both keys present even if empty

5 min

P20

Implement a bounded Stack<T> (max size N, throws on overflow) using ArrayDeque

generic class, custom exception

Push/pop/peek/isFull; test overflow

15 min


Set 3 — File I/O Tasks (10 programs, ~2 hours)

NIO.2 in your fingers. Every one uses Path / Files.

#

Program

What it tests

Acceptance

Est

P21

Read a text file, print each line prefixed with line number

Files.readAllLines, indexed loop

1-indexed line numbers, no trailing blank line

8 min

P22

Count lines, words, chars in a file (mini wc)

Files.lines in try-with-resources

Compare to real wc -lwc output

10 min

P23

Copy a file byte-for-byte using buffered streams

Files.newInputStream, buffer loop

Verify size and MD5 match

10 min

P24

Split a large text file into N smaller files by line count

streaming write with buffered writer

Line total preserved; no ordering bugs

15 min

P25

Recursively list all files under a directory larger than 1 MB

Files.walk, filter by size

Correct on nested dirs with symlinks handled

15 min

P26

Grep-lite: given a regex and a file, print matching lines with line numbers

Pattern/Matcher, Files.lines

Case-insensitive flag -i supported

15 min

P27

Write a Map<String,Integer> to a properties file and read it back

Properties class or manual key=value

Round-trip preserves all entries

10 min

P28

Given a directory, compute total size and file count in it (non-recursive vs recursive)

Files.list vs Files.walk

Two methods, both return same on flat dir

10 min

P29

Watch a directory and print any newly-created file names for 30 seconds

WatchService

Create a file externally, event fires

20 min

P30

Read a CSV without a library: 3 columns, quotes may contain commas

manual state machine on chars

Test with "a,b",c,d line

20 min


Set 4 — Basic OOP Kata (10 programs, ~2.5 hours)

Records, sealed types, interfaces, equals/hashCode, exception design.

#

Program

What it tests

Acceptance

Est

P31

record Point(int x, int y) with distanceTo(Point) and static origin()

record with methods & static factory

equals/hashCode auto-correct

8 min

P32

Sealed interface Shape with Circle, Rectangle, Triangle records + area() via pattern switch

sealed + pattern switch

Exhaustive switch, no default

15 min

P33

Money(BigDecimal, Currency) record with compact constructor rejecting negatives / null

compact constructor validation

Throws on bad input

10 min

P34

BankAccount class with deposit, withdraw, balance; withdraw throws custom InsufficientFundsException

encapsulation, custom exception

Balance never goes negative silently

15 min

P35

Generic Pair<A,B> record and a method returning a Pair<Integer,Integer> of min and max in an array

generics, single-pass min-max

Handles empty via Optional<Pair>

10 min

P36

Employee class implementing Comparable<Employee> by salary, then a Comparator by name

Comparable vs Comparator

Sort a List<Employee> both ways

15 min

P37

Enum HttpStatus with code + message and a fromCode(int) static

enum with fields & static lookup map

Unknown code → IllegalArgumentException

10 min

P38

Interface PaymentProcessor with default method refund calling charge with negative

interface default methods

Two impls: Stripe, PayPal (mock)

15 min

P39

Abstract class Animal with abstract sound() and concrete describe(); Dog/Cat subclasses

abstract vs concrete methods

Test polymorphic dispatch

10 min

P40

Result<T> sealed interface with Success<T>(T value) and Failure<T>(String error) records

sealed generics, ADT

switch returns value or throws

15 min


Set 5 — Mixed / Integration (10 programs, ~3 hours)

Combines everything. Slightly larger. Each is basically a mini-project.

#

Program

What it tests

Acceptance

Est

P41

CLI calculator: parses "3 + 4 * 2" respecting precedence, prints result

Shunting-yard or recursive descent, Deque as stack

5 correctness tests incl. parentheses

30 min

P42

Word-count from a directory of text files, aggregated across all files

Files.walk, streams, Collectors.summingLong

Matches cat *.txt | wc -w

20 min

P43

Roman numeral ↔ integer converter (both directions)

switch expression, order-sensitive parsing

3999 max; symmetric round-trip test

20 min

P44

In-memory key-value store with put, get, delete, TTL per key; expired reads return Optional.empty

HashMap, System.currentTimeMillis, background cleanup

Test with 100ms TTL

25 min

P45

Log-line parser: given "[2026-07-05 10:15:32] LEVEL user=xxx msg=...", parse into a record and group by level & hour

regex, LocalDateTime, records, streams

Output a Map<Level, Map<Hour, count>>

30 min

P46

Priority-based task scheduler: takes tasks with priority, poll() returns highest first; break ties by insertion order

PriorityQueue with custom Comparator including insertion counter

Ties correct

20 min

P47

JSON-ish printer for arbitrary records (single-level): use reflection to print {field1=val1, field2=val2}

Class.getRecordComponents() (Java 16+)

Works on any record you pass in

20 min

P48

Directory-diff: given two dirs, print files added / removed / modified (by size) between them

Files.walk, sets, comparison

Symlink-safe

25 min

P49

Rate limiter: allow max N calls per T seconds, boolean tryAcquire()

Deque<Long> of timestamps OR token-bucket

Concurrent-unsafe is fine for now

20 min

P50

Simple TCP echo server that handles multiple clients using virtual threads

ServerSocket, Executors.newVirtualThreadPerTaskExecutor

Telnet-testable; graceful shutdown

30 min


After you finish

Open LOG.md and look at:

  1. The three programs that took longest. Which topic? Re-read the corresponding file, then redo one of them from scratch.

  2. Programs where you looked up syntax. Which syntax? That’s your weak spot. Write two more programs exercising it.

  3. Programs where your tests failed on first run. What did you miss (edge case? null? empty input?). Make a mental note of the pattern.

⚠️ What most people get wrong

They race through the list to feel productive. The point is not to reach 50. The point is that when you sit down for a coding round in month 8, Files.lines(path).filter(...).collect(...) flows out without a pause. If you rush and don’t verify with tests, you finish 50 shaky programs and gain nothing.

Also: do not skip the OOP kata (Set 4) because “you know OOP”. That set drills modern Java’s specific OOP surface — records, sealed, pattern switch — which is what employers screen for on Java 21.


Return to README.md · Next: projects.md