How to resolve the algorithm Ulam spiral (for primes) step by step in the Java programming language
How to resolve the algorithm Ulam spiral (for primes) step by step in the Java programming language
Table of Contents
Problem Statement
An Ulam spiral (of primes) is a method of visualizing primes when expressed in a (normally counter-clockwise) outward spiral (usually starting at 1), constructed on a square grid, starting at the "center".
An Ulam spiral is also known as a prime spiral.
The first grid (green) is shown with sequential integers, starting at 1.
In an Ulam spiral of primes, only the primes are shown (usually indicated by some glyph such as a dot or asterisk), and all non-primes as shown as a blank (or some other whitespace).
Of course, the grid and border are not to be displayed (but they are displayed here when using these Wiki HTML tables).
Normally, the spiral starts in the "center", and the 2nd number is to the viewer's right and the number spiral starts from there in a counter-clockwise direction.
There are other geometric shapes that are used as well, including clock-wise spirals.
Also, some spirals (for the 2nd number) is viewed upwards from the 1st number instead of to the right, but that is just a matter of orientation.
Sometimes, the starting number can be specified to show more visual striking patterns (of prime densities).
[A larger than necessary grid (numbers wise) is shown here to illustrate the pattern of numbers on the diagonals (which may be used by the method to orientate the direction of spiral-construction algorithm within the example computer programs)].
Then, in the next phase in the transformation of the Ulam prime spiral, the non-primes are translated to blanks.
In the orange grid below, the primes are left intact, and all non-primes are changed to blanks.
Then, in the final transformation of the Ulam spiral (the yellow grid), translate the primes to a glyph such as a • or some other suitable glyph.
The Ulam spiral becomes more visually obvious as the grid increases in size.
For any sized N × N grid, construct and show an Ulam spiral (counter-clockwise) of primes starting at some specified initial number (the default would be 1), with some suitably dotty (glyph) representation to indicate primes, and the absence of dots to indicate non-primes.
You should demonstrate the generator by showing at Ulam prime spiral large enough to (almost) fill your terminal screen.
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Ulam spiral (for primes) step by step in the Java programming language
Ulam Spiral Generator (ulam.java)
- genUlam(int n): Generates a Ulam spiral of size
n
. - genUlam(int n, int i): Generates a Ulam spiral of size
n
, starting from the valuei
. - Internal implementation:
- Initializes a square matrix of strings
spiral
of sizen
. - Tracks the current position
(y, x)
and directiondir
(RIGHT, UP, LEFT, DOWN). - Fills the matrix with prime numbers in string format, otherwise with " ---".
- Changes direction and moves in a clockwise spiral pattern, filling in the next prime numbers.
-isPrime(int a)**: Checks if an integer
a
is prime using Fermat's little theorem.
- Initializes a square matrix of strings
Large Ulam Spiral (LargeUlamSpiral.java)
- Provides a graphical representation of a large Ulam spiral.
- Extends JPanel and implements the paintComponent method.
- Iterates through the spiral, drawing prime numbers as filled rectangles.
- The angle, step size, and direction are updated to create the spiral pattern.
Ulam Spiral (UlamSpiral.java)
- Similar to LargeUlamSpiral but with smaller size and different visualization style.
- Draws a spiral with lines connecting prime numbers.
- Uses a different font for prime and composite numbers.
Usage
To use these classes:
- UlamSpiralGenerator: Call
genUlam(n)
to generate a text-based Ulam spiral and print it to the console. - LargeUlamSpiral: Create an instance of
LargeUlamSpiral
and add it to a JFrame to display the graphical representation. - UlamSpiral: Create an instance of
UlamSpiral
and add it to a JFrame to display the smaller, line-drawn Ulam spiral.
Source code in the java programming language
import java.util.Arrays;
public class Ulam{
enum Direction{
RIGHT, UP, LEFT, DOWN;
}
private static String[][] genUlam(int n){
return genUlam(n, 1);
}
private static String[][] genUlam(int n, int i){
String[][] spiral = new String[n][n];
Direction dir = Direction.RIGHT;
int j = i;
int y = n / 2;
int x = (n % 2 == 0) ? y - 1 : y; //shift left for even n's
while(j <= ((n * n) - 1 + i)){
spiral[y][x] = isPrime(j) ? String.format("%4d", j) : " ---";
switch(dir){
case RIGHT:
if(x <= (n - 1) && spiral[y - 1][x] == null && j > i) dir = Direction.UP; break;
case UP:
if(spiral[y][x - 1] == null) dir = Direction.LEFT; break;
case LEFT:
if(x == 0 || spiral[y + 1][x] == null) dir = Direction.DOWN; break;
case DOWN:
if(spiral[y][x + 1] == null) dir = Direction.RIGHT; break;
}
switch(dir){
case RIGHT: x++; break;
case UP: y--; break;
case LEFT: x--; break;
case DOWN: y++; break;
}
j++;
}
return spiral;
}
public static boolean isPrime(int a){
if(a == 2) return true;
if(a <= 1 || a % 2 == 0) return false;
long max = (long)Math.sqrt(a);
for(long n = 3; n <= max; n += 2){
if(a % n == 0) return false;
}
return true;
}
public static void main(String[] args){
String[][] ulam = genUlam(9);
for(String[] row : ulam){
System.out.println(Arrays.toString(row).replaceAll(",", ""));
}
System.out.println();
for(String[] row : ulam){
System.out.println(Arrays.toString(row).replaceAll("\\[\\s+\\d+", "[ * ").replaceAll("\\s+\\d+", " * ").replaceAll(",", ""));
}
}
}
import java.awt.*;
import javax.swing.*;
public class LargeUlamSpiral extends JPanel {
public LargeUlamSpiral() {
setPreferredSize(new Dimension(605, 605));
setBackground(Color.white);
}
private boolean isPrime(int n) {
if (n <= 2 || n % 2 == 0)
return n == 2;
for (int i = 3; i * i <= n; i += 2)
if (n % i == 0)
return false;
return true;
}
@Override
public void paintComponent(Graphics gg) {
super.paintComponent(gg);
Graphics2D g = (Graphics2D) gg;
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(getForeground());
double angle = 0.0;
int x = 300, y = 300, dx = 1, dy = 0;
for (int i = 1, step = 1, turn = 1; i < 40_000; i++) {
if (isPrime(i))
g.fillRect(x, y, 2, 2);
x += dx * 3;
y += dy * 3;
if (i == turn) {
angle += 90.0;
if ((dx == 0 && dy == -1) || (dx == 0 && dy == 1))
step++;
turn += step;
dx = (int) Math.cos(Math.toRadians(angle));
dy = (int) Math.sin(Math.toRadians(-angle));
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setTitle("Large Ulam Spiral");
f.setResizable(false);
f.add(new LargeUlamSpiral(), BorderLayout.CENTER);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
import java.awt.*;
import javax.swing.*;
public class UlamSpiral extends JPanel {
Font primeFont = new Font("Arial", Font.BOLD, 20);
Font compositeFont = new Font("Arial", Font.PLAIN, 16);
public UlamSpiral() {
setPreferredSize(new Dimension(640, 640));
setBackground(Color.white);
}
private boolean isPrime(int n) {
if (n <= 2 || n % 2 == 0)
return n == 2;
for (int i = 3; i * i <= n; i += 2)
if (n % i == 0)
return false;
return true;
}
@Override
public void paintComponent(Graphics gg) {
super.paintComponent(gg);
Graphics2D g = (Graphics2D) gg;
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setStroke(new BasicStroke(2));
double angle = 0.0;
int x = 280, y = 330, dx = 1, dy = 0;
g.setColor(getForeground());
g.drawLine(x, y - 5, x + 50, y - 5);
for (int i = 1, step = 1, turn = 1; i < 100; i++) {
g.setColor(getBackground());
g.fillRect(x - 5, y - 20, 30, 30);
g.setColor(getForeground());
g.setFont(isPrime(i) ? primeFont : compositeFont);
g.drawString(String.valueOf(i), x + (i < 10 ? 4 : 0), y);
x += dx * 50;
y += dy * 50;
if (i == turn) {
angle += 90.0;
if ((dx == 0 && dy == -1) || (dx == 0 && dy == 1))
step++;
turn += step;
dx = (int) Math.cos(Math.toRadians(angle));
dy = (int) Math.sin(Math.toRadians(-angle));
g.translate(9, -5);
g.drawLine(x, y, x + dx * step * 50, y + dy * step * 50);
g.translate(-9, 5);
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setTitle("Ulam Spiral");
f.setResizable(false);
f.add(new UlamSpiral(), BorderLayout.CENTER);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
You may also check:How to resolve the algorithm Find common directory path step by step in the Lingo programming language
You may also check:How to resolve the algorithm Literals/Integer step by step in the Insitux programming language
You may also check:How to resolve the algorithm Ethiopian multiplication step by step in the Object Pascal programming language
You may also check:How to resolve the algorithm FizzBuzz step by step in the Huginn programming language
You may also check:How to resolve the algorithm Strip comments from a string step by step in the COBOL programming language