DEV Community

Lluís Josep Martínez
Lluís Josep Martínez

Posted on

Making ChatGPT do Clean Code

Just for fun, I asked chatGPT to give me a Java implementation of the sieve of Eratosthenes to find the first 100 prime numbers.
It gave me this:

public class SieveOfEratosthenes { public static void main(String[] args) { int n = 100; // Change this to the desired limit to find prime numbers up to n. boolean[] isPrime = new boolean[n + 1]; Arrays.fill(isPrime, true); isPrime[0] = isPrime[1] = false; for (int p = 2; p * p <= n; p++) { if (isPrime[p]) { for (int i = p * p; i <= n; i += p) { isPrime[i] = false; } } } System.out.println("Prime numbers up to " + n + ":"); for (int i = 2; i <= n; i++) { if (isPrime[i]) { System.out.print(i + " "); } } } } 
Enter fullscreen mode Exit fullscreen mode

So far so good. Now I asked for an implementation with lambdas. That pesky for loops are just too old.

public class SieveOfEratosthenesWithLambdas { public static void main(String[] args) { int n = 100; // Change this to the desired limit to find prime numbers up to n. List<Integer> primes = IntStream.rangeClosed(2, n) .boxed() .filter(SieveOfEratosthenesWithLambdas::isPrime) .collect(Collectors.toList()); System.out.println("Prime numbers up to " + n + ":"); primes.forEach(System.out::print); } static boolean isPrime(int number) { return IntStream.rangeClosed(2, (int) Math.sqrt(number)) .allMatch(i -> number % i != 0); } } 
Enter fullscreen mode Exit fullscreen mode

Looks good. Compact and efficient.
Now it's when the fun starts. I ask for a "clean code" implementation, whatever that means. Here's the result:

public class SieveOfEratosthenesCleanCode { public static void main(String[] args) { int limit = 100; // Change this to the desired limit to find prime numbers up to 'limit'. List<Integer> primes = findPrimesUpTo(limit); System.out.println("Prime numbers up to " + limit + ":"); for (int prime : primes) { System.out.print(prime + " "); } } public static List<Integer> findPrimesUpTo(int limit) { boolean[] isPrime = new boolean[limit + 1]; List<Integer> primes = new ArrayList<>(); // Initialize the array for (int i = 2; i <= limit; i++) { isPrime[i] = true; } // Sieve of Eratosthenes for (int p = 2; p * p <= limit; p++) { if (isPrime[p]) { for (int i = p * p; i <= limit; i += p) { isPrime[i] = false; } } } // Collect the prime numbers for (int i = 2; i <= limit; i++) { if (isPrime[i]) { primes.add(i); } } return primes; } } 
Enter fullscreen mode Exit fullscreen mode

I don't think it's "clean" enough. Methods are too large. I ask for a "cleaner" version:

public class PrimeNumberFinder { public static void main(String[] args) { int upperLimit = 100; // Change this to the desired limit to find prime numbers up to 'upperLimit'. List<Integer> primeNumbers = findPrimeNumbers(upperLimit); displayPrimeNumbers(primeNumbers); } public static List<Integer> findPrimeNumbers(int upperLimit) { List<Integer> primeNumbers = new ArrayList<>(); boolean[] isComposite = new boolean[upperLimit + 1]; for (int number = 2; number * number <= upperLimit; number++) { if (!isComposite[number]) { for (int multiple = number * number; multiple <= upperLimit; multiple += number) { isComposite[multiple] = true; } } } for (int number = 2; number <= upperLimit; number++) { if (!isComposite[number]) { primeNumbers.add(number); } } return primeNumbers; } public static void displayPrimeNumbers(List<Integer> primeNumbers) { System.out.println("Prime numbers found:"); for (int prime : primeNumbers) { System.out.print(prime + " "); } System.out.println(); } } 
Enter fullscreen mode Exit fullscreen mode

Methods are still too large. Refactor till you die.

public class PrimeNumberFinder { public static void main(String[] args) { int upperLimit = 100; // Change this to the desired limit to find prime numbers up to 'upperLimit'. List<Integer> primeNumbers = findPrimeNumbers(upperLimit); displayPrimeNumbers(primeNumbers); } public static List<Integer> findPrimeNumbers(int upperLimit) { boolean[] isComposite = new boolean[upperLimit + 1]; sieveOfEratosthenes(isComposite, upperLimit); return collectPrimes(isComposite); } private static void sieveOfEratosthenes(boolean[] isComposite, int upperLimit) { for (int number = 2; number * number <= upperLimit; number++) { if (!isComposite[number]) { markMultiplesAsComposite(isComposite, number, upperLimit); } } } private static void markMultiplesAsComposite(boolean[] isComposite, int number, int upperLimit) { for (int multiple = number * number; multiple <= upperLimit; multiple += number) { isComposite[multiple] = true; } } private static List<Integer> collectPrimes(boolean[] isComposite) { List<Integer> primeNumbers = new ArrayList<>(); for (int number = 2; number < isComposite.length; number++) { if (!isComposite[number]) { primeNumbers.add(number); } } return primeNumbers; } public static void displayPrimeNumbers(List<Integer> primeNumbers) { System.out.println("Prime numbers found:"); for (int prime : primeNumbers) { System.out.print(prime + " "); } System.out.println(); } } 
Enter fullscreen mode Exit fullscreen mode

Well, that's it! A perfectly good algorithm has been "cleaned" until it is an incomprehensible garbage that needs much more cognitive load to understand than the original version.
Thanks Clean Code!

PS: the version in the book is even worse.

Top comments (0)