Java 2D Array Spiral/Clockwise Traversal - java

The problem has been discussed on stackoverflow before, I'm specifically asking for opinion or answers regarding my code and whether or not it can work with imbalanced 2d arrays without a major overhaul. The reason it's failing to print the end of some balanced arrays must be some smaller issue. Update at the bottom
Basically we have a 2d array supplied by a command line driven text file. That file has each trial separated by a newline and follows like this: rows;columns;values(white space delimited)
Example: 4;4;1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Output: 1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package spiralprinting;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/**
*
* #author Paul
*/
public class SpiralPrinting {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws FileNotFoundException, IOException {
// TODO code application logic here
File file = new File(args[0]);
BufferedReader in = new BufferedReader(new FileReader(file));
String line;
while ((line = in.readLine()) != null) {
String[] lineArray = line.split(";");
if (lineArray.length > 0) {//ignore blank line inputs
//Process line of input Here
//Max ,minimum, and current indexes in our matrix.
int maxX = Integer.parseInt(lineArray[0]) - 1;
int maxY = Integer.parseInt(lineArray[1]) - 1;
int minX = 0;
int minY = 0;
int x = 0;
int y = 0;
//Build our matrix
String[] valueArray = lineArray[2].split("\\s");
String[][] matrix = new String [Integer.parseInt(lineArray[0])][Integer.parseInt(lineArray[1])];
int count = 0;
for (int j = 0; j <= maxY; j++){
for (int i = 0; i <= maxX; i++){
matrix[i][j] = (valueArray[count]);
count++;
}
}
StringBuilder printString = new StringBuilder();
//Traverse and print our matrix in a spiral!
while (maxX > minX && maxY > minY){
//Leaving this in and commented so you can see my train of thought.
if (x != maxX){
while (x < maxX){
printString.append(matrix[x][y]).append(" ");
x++;
}maxX--;
}
if (y != maxY){
while (y < maxY){
printString.append(matrix[x][y]).append(" ");
y++;
}maxY--;
}
if (x != minX){
while (x > minX){
printString.append(matrix[x][y]).append(" ");
x--;
}minX++;
}
if (y != minY){
while (y > minY){
printString.append(matrix[x][y]).append(" ");
y--;
}minY++;
}
//One border done (4 passes). Next iteration of while-loop begins.
x = minX;
y = minY;
}//end of our traversal loop
//Print it !
System.out.println(printString.toString().trim());
}
}//end of input line analysis
}
}//end of class
Sample input and current output:
4;4;1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ---> 1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10 good
3;3;1 2 3 4 5 6 7 8 9 ---> 1 2 3 6 9 8 7 4 This fails to print the 5
3;4;1 2 3 4 5 6 7 8 9 10 11 12 ---> 1 2 3 6 9 12 11 10 7 4 ..fails to print the 5, 8 at the end...
4;3;1 2 3 4 5 6 7 8 9 10 11 12 ---> 1 2 3 4 8 12 11 10 9 5 ..fails to print the last 2 again: 6, 7"
2;10;1......20 ---> 1, 2, 4, 6, 8....good
After some quick revisions, my issue appears to be that it is not printing the last 2 for some sets. I'm convinced this is a special case and I'm going to sleep on it :)
Any help is still appreciated, especially if you think the issue is larger than I currently believe. My sleepy brain thinks I need 2 special cases to go along with my 4 checks in the while-loop...
Thank you =]

When your debugging something and you just CANT wrap your mind around whats going wrong... break it down into something easy to debug, throw out your hard test cases and try something very simple then move up to harder ones and find where it breaks, heres how i found it.
I commented out all your code where you input the file and made your input to a fixed string:
String[] lineArray = ("3;2;" +
"1 2 3 " +
"6 5 4 ").split(";");
// see how the output should be 123456...very easy to see and debug
Putting a breakpoint at while (maxX > minX || maxY > minY), I looked at the matrix array and saw that the matrix was of size 2x3 not 3x2, and my numbers were not stored how I would think they should be. And voila problem found.
/*if (maxY >= maxX){*/
// This for loop is what you want
for (int j = 0; j <= maxY; j++){
for (int i = 0; i <= maxX; i++){
matrix[i][j] = (valueArray[count]);
count++;
}
}
/*}/*delete this junk/ else if (maxX > maxY){
for (int i = 0; i <= maxX; i++){
for (int j = 0; j <= maxY; j++){
matrix[i][j] = (valueArray[count]);
count++;
}
}
}*/
This is a fun one for recursion. I assume you already submitted your code for your project so I took a stab at it. Heres what I ended up with: (I left in the printlns so you could see the program flow)
// called by System.out.println(getSpiral(matrix,0,0,0,0));
public static String getSpiral(String[][] array, int x, int y, double direction, int turnCount) {
int [] velocity = getDirection(direction);
if(x+velocity[0] >= array.length || y+velocity[1] >= array[x].length ||
x+velocity[0] < 0 || y+velocity[1] < 0 ||
array[x+velocity[0]][y+velocity[1]].equals("done")) {
System.out.println("turn");
if(turnCount>=3)
return array[x][y];
return getSpiral(array, x, y, direction+Math.PI/2,turnCount+1);
}
String value = array[x][y].toLowerCase();
array[x][y]="done";
System.out.println(value);
return value + " " + getSpiral(array, x+velocity[0], y+velocity[1], direction,0);
}
public static int[] getDirection(double angle) {
return new int[] {(int)Math.round(Math.cos(angle)), (int)Math.round(Math.sin(angle))};
}

clockwise traversal
public static String matrixTraverse(int[][] matrix, int startX, int startY){
String result = "";
boolean baseCase = startX + 1 == Math.ceil(matrix[0].length / 2.0)
|| startY + 1 == Math.ceil(matrix.length / 2.0);
for (int i = startX ; i < matrix[0].length - startX ; i++) {
result += " " + matrix[startY][i];
}
for (int i = startY + 1 ; i < matrix.length - startY - 1 ; i++){
result += " " + matrix[i][matrix[0].length - 1 - startX];
}
for (int i = startX ; (matrix.length - 1 != 2 * startY) && (i < matrix[0].length - startX) ; i++){
result += " " + matrix[matrix.length - 1 - startY][matrix[0].length - 1 - i];
}
for (int i = startY ; (matrix[0].length - 1 != 2 * startX) && (i < matrix.length - startY - 2) ; i++){
result += " " + matrix[matrix.length - 2 - i][startX];
}
if (!baseCase) {
result += matrixTraverse(matrix, ++startX, ++startY);
}
return result;
}

Related

pyramid printing using Java

Pyramid example
Note:
System.our.printf(“%n.mf”, num) will print out a float number num with width n and m decimal places.
Calculation of a^b in Java: Math.pow(a,b)
For the above pyramid printing, you may break the pattern into three parts: spaces on the left, numbers on the left and numbers on the right. For each line i, there are total 2*i-1 numbers.
public static void main(String[] args) {
int rows = 5, k = 0, count = 0, count1 = 0;
for(int i = 1; i <= rows; ++i) {
for(int space = 1; space <= rows - i; ++space) {
System.out.print(" ");
++count;
}
while(k != 2 * i - 1) {
if (count <= rows - 1) {
System.out.print((i + k) + " ");
++count;
}
else {
++count1;
System.out.print((i + k - 2 * count1) + " ");
}
++k;
}
count1 = count = k = 0;
System.out.println();
}
}
}
I decided to give this a try, mainly because I wanted to present some concepts having to do with problem-solving.
First, I made the height of the pyramid a variable. This forced me to consider how different pyramid heights would affect the width of each segment of each line.
Next, I decided to pre-calculate the powers of two. There's no point in recalculating the values for each line. So, I wrote a method to return a precalculated array of integers.
Next, I calculated how much space the largest power of two would take up. I formatted the number using the NumberFormat class. The NumberFormat class will format the number according to the Locale in which you're running the code. I used the format method of the String class to give each number enough space.
Next, I divided each line into a blank area, a number area, and a blank area. That way, I could work on each part of a line separately. The blank area on the left side of the pyramid line is the same length as the blank area on the right side of the line, so I only had to create it one time for each line.
I used a StringBuilder to create each line of the pyramid. It's faster to use a StringBuilder than to concatenate String values. I used StringBuilder segments to create the parts of a pyramid line.
I didn't use static methods because I wanted to show how you instantiate the class in the main method. In general, I try to avoid the use of static methods.
Here's the result of one test run. I assure you, I ran several dozen tests on this code.
1
1 2 1
1 2 4 2 1
1 2 4 8 4 2 1
1 2 4 8 16 8 4 2 1
1 2 4 8 16 32 16 8 4 2 1
1 2 4 8 16 32 64 32 16 8 4 2 1
1 2 4 8 16 32 64 128 64 32 16 8 4 2 1
1 2 4 8 16 32 64 128 256 128 64 32 16 8 4 2 1
1 2 4 8 16 32 64 128 256 512 256 128 64 32 16 8 4 2 1
Here's the code.
import java.text.NumberFormat;
public class NumberPyramid {
public static void main(String[] args) {
int power = 10;
NumberPyramid np = new NumberPyramid();
np.createPyramid(power);
}
private static final NumberFormat NF =
NumberFormat.getNumberInstance();
public void createPyramid(int power) {
int[] values = createPowersArray(power);
String maximum = NF.format(values[power - 1]);
int segmentSize = maximum.length() + 2;
String format = "%" + segmentSize + "s";
for (int index = 0; index < power; index++) {
StringBuilder builder = new StringBuilder();
StringBuilder blankArea = createBlankArea(
index, power, segmentSize);
builder.append(blankArea);
builder.append(createNumberArea(index, values, format));
builder.append(blankArea);
System.out.println(builder.toString());
}
}
private int[] createPowersArray(int power) {
int[] values = new int[power];
values[0] = 1;
for (int i = 1; i < power; i++) {
values[i] = values[i - 1] * 2;
}
return values;
}
private StringBuilder createNumberArea(int index,
int[] values, String format) {
StringBuilder builder = new StringBuilder();
for (int j = 0; j <= index; j++) {
builder.append(String.format(format,
NF.format(values[j])));
}
for (int j = index - 1; j >= 0; j--) {
builder.append(String.format(format,
NF.format(values[j])));
}
return builder;
}
private StringBuilder createBlankArea(int index,
int power, int segmentSize) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < power - index - 1; i++) {
builder.append(createBlankSegment(segmentSize));
}
return builder;
}
private StringBuilder createBlankSegment(int length) {
StringBuilder builder = new StringBuilder(length);
for (int i = 0; i < length; i++) {
builder.append(" ");
}
return builder;
}
}
find the answer below:
public class Main {
static int rows = 10;
public static void main(String[] args) {
LinkedList<Integer> numbers = new LinkedList<>();
for(int i = 1 ; i <= rows ; i++){
if(i ==1 ) numbers.add(1);
else {
int totalNumber = i * 2 -1;
insertNumbers(totalNumber, numbers);
}
printNumbers(numbers, i);
System.out.println();
numbers.clear();
}
}
private static void insertNumbers(int totalNumber, LinkedList<Integer> numbers) {
int numbersOnEachSide = (totalNumber - 1) / 2;
for (int i = 0; i < numbersOnEachSide ; i++ ) numbers.add((int) Math.pow(2, i));
numbers.add((int) Math.pow(2,numbersOnEachSide));
for(int i = 0 ; i < numbersOnEachSide ; i++) numbers.add((int) Math.pow(2, numbersOnEachSide-1-i));
}
private static void printNumbers(LinkedList<Integer> numbers, int i) {
int spaceNorows = rows - i;
printSpaces(spaceNorows);
for (Integer number : numbers) {
System.out.print(number + "\t");
}
printSpaces(spaceNorows);
}
private static void printSpaces(int spaceNorows) {
for(int j = 0 ; j< spaceNorows ; j++) System.out.print("\t");
}
}
output:
1
1 2 1
1 2 4 2 1
1 2 4 8 4 2 1
1 2 4 8 16 8 4 2 1
1 2 4 8 16 32 16 8 4 2 1
1 2 4 8 16 32 64 32 16 8 4 2 1
1 2 4 8 16 32 64 128 64 32 16 8 4 2 1
1 2 4 8 16 32 64 128 256 128 64 32 16 8 4 2 1
1 2 4 8 16 32 64 128 256 512 256 128 64 32 16 8 4 2 1
p.s please take a look at https://stackoverflow.com/tour to ask a proper question in later posts.
EDIT : How to run the code in CMD
To run the application above:
1- save all the code above in a file named - for example - Main.java
2- run CMD in windows or terminal in linux and compile the Main.java using javac Main.java.
3- The compiled file will be put in the same directory as the java file.
4- run the compiled class using java Main.
change Main to whatever name you give to the file
Since you are running the code in the cmd it might not display the 10 row pyramid properly(due to screen resolution, size, etc). So,
change the row field in static int rows = 10; to 5 to see the
pyramid properly.
You can further changing the fixed row number to dynamically get it from user.

Print numerals in order in a sine wave

Background:
I've successfully written code that generates a sine wave from 0 to 2pi. Adjusting the constants xPrecision and yPrecision, you can stretch the graph horizontally or vertically.
I gain this neat output (in Eclipse), when xPrecision = yPrecision = 10:
My query:
I now wish to display digits 0 to 9 instead of the stars. So, the leftmost star is replaced by 0, the second left-most star is replaced by 1, and so on. When you reach 9, the next digit is again zero.
I am clueless as to how to do this. I have looked at wave patterns like this, but they are fixed width patterns, while mine is scalable.
The only way I can think of is converting my output to a 2D character array, then scraping the *s manually from left to right, and replacing them with the digits, and then printing it. However, this is extremely memory consuming at bigger values of x/yPrecision.
What is the most optimized way to achieve this output?
Code to print sine wave:
class sine {
static final double xPrecision = 10.0; // (1/xPrecision) is the precision on x-values
static final double yPrecision = 10.0; // (1/yPrecision) is the precision on y-values
static final int PI = (int) (3.1415 * xPrecision);
static final int TPI = 2 * PI; // twice PI
static final int HPI = PI / 2; // half PI
public static void main(String[] args) {
double xd;
for(int start = (int) (1 * yPrecision), y = start; y >= -start; y--){
double x0 = Math.asin(y / yPrecision),
x1 = bringXValueWithinPrecision(x0),
x2 = bringXValueWithinPrecision(x0 + TPI / xPrecision),
x3 = bringXValueWithinPrecision(PI/xPrecision - x0);
// for debug
//System.out.println(y + " " + x0 + " " + x1 + " " + x2 + " " + x3);
for(int x = 0; x <= TPI; x++){
xd = (x / xPrecision);
if(x1 == xd || x2 == xd || x3 == xd)
System.out.print("*");
else System.out.print(" ");
}
System.out.println();
}
}
public static double bringXValueWithinPrecision(double num){
// obviously num has 16 floating points
// we need to get num within our precision
return Math.round(num * xPrecision) / xPrecision;
}
}
"Draw" the graph in memory first, then assign digits to its vertical points, and print them in a separate pass.
01
9 2
8 3
7 4
6 5
5 6
4 7
3 8
2 9
1 0
0 1 2
2 1
3 0
4 9
5 8
6 7
7 6
8 5
9 4
0 3
12
See comments in the code for an explanation of how this works:
static final double xPrecision = 10.0; // (1/xPrecision) is the precision on x-values
static final double yPrecision = 10.0; // (1/yPrecision) is the precision on y-values
static final int PI = (int) (3.1415 * xPrecision);
static final int TPI = 2 * PI; // twice PI
static final int HPI = PI / 2; // half PI
public static void main(String[] args) {
// This part is the same as OP's code, except that instead of printing '*'
// it stores the corresponding row number in the array of rows
double xd;
int[] row = new int[100];
Arrays.fill(row, -1);
int r = 0;
int maxc = 0; // Mark the rightmost column of all iterations
for(int start = (int) (1 * yPrecision), y = start; y >= -start; y--){
double x0 = Math.asin(y / yPrecision),
x1 = bringXValueWithinPrecision(x0),
x2 = bringXValueWithinPrecision(x0 + TPI / xPrecision),
x3 = bringXValueWithinPrecision(PI/xPrecision - x0);
int c = 0;
for(int x = 0; x <= TPI; x++, c++){
xd = (x / xPrecision);
// This is where the asterisk used to go
if(x1 == xd || x2 == xd || x3 == xd)
row[c] = r;
}
maxc = Math.max(c, maxc);
r++;
}
// Walk the assigned rows, and give each one a consecutive digit
int[] digit = new int[100];
int current = 0;
for (int i = 0 ; i != 100 ; i++) {
if (row[i] != -1) {
digit[i] = (current++) % 10;
}
}
// Now walk the rows again, this time printing the pre-assigned digits
for (int i = 0 ; i != r ; i++) {
for (int c = 0 ; c != maxc ; c++) {
if (row[c] == i) {
System.out.print(digit[c]);
} else {
System.out.print(' ');
}
}
System.out.println();
}
}
public static double bringXValueWithinPrecision(double num){
// obviously num has 16 floating points
// we need to get num within our precision
return Math.round(num * xPrecision) / xPrecision;
}
The first part of the code fills row[i] array, which contains row for the asterisk in column i. First few numbers from row[] array would look like this:
10 9 8 7 6 5 4 - 3 2 - 1 - - - 0 0 - - - 1 - 2 3 - 4 5 6 7 8 9 10
- denotes cells with -1, which represents a missing value. The array says that the left-most asterisk is on row 10, the next asterisk is on row 9, then 8, 7, 6, and so on. Asterisks 11 and 12 are on row zero, which is at the top.
The second loop walks rows, skips -1s, and assign consecutive digits to all non-negative positions.
The third loop walks the entire field again going row-by-row, printing values from pre-assigned digit[] array when the current row matches the value in the row[] array.
Demo.
If you replace:
System.out.print("*");
with
System.out.print(""+(x%10));
it seems to nearly work.
56
1 0
9 2
8 3
6 5
5 6
4 7
3 8
2 9
1 0
0 1 2
2 1
3 0
4 9
5 8
6 7
7 6
9 4
0 3
2 1
67
Perhaps some further adjustments might get it perfect.
Doing it in a completely different way produces a different picture but achieves your effect.
Essentially,
for each y
for each x
calculate fx = sin(x)
if fx == y print * else print space
It's very inefficient as it calculates sin(x) x*y times when, if you filled a matrix, you could calculate sin(x) just x times.
static final double xPrecision = 10.0; // (1/xPrecision) is the precision on x-values
static final double yPrecision = 10.0; // (1/yPrecision) is the precision on y-values
private void sine() {
for (double y = 1; y >= -1; y -= 1.0 / yPrecision) {
int n = 0;
for (double x = 0; x < 2.0 * Math.PI; x += 1.0 / xPrecision, n++) {
double fx = Math.sin(x);
boolean star = Math.round(fx*xPrecision) == Math.round(y*yPrecision);
System.out.print((star ? ""+(n%10) : " "));
}
System.out.println();
}
}
public void test(String[] args) {
sine();
}
Gives you:
345678
12 901
90 2
8 34
67 5
5 6
4 7
3 8
2 9
1 0
0 1
2 2
3 1
4 0
56 9
7 8
8 67
9 5
01 34
23 12
4567890
Since this is Java, how about let's actually use some objects as objects rather than just as places to define a couple of functions.
Treat your wavy graph as if it is a composition of several different "branches" of the inverse sine function. (Mathematically, that's how we explain the way your version of the program uses Math.asin to produce multiple coordinates for stars.)
Branch 0 is the initial rising part of the curve,
Branch 1 is the falling part of the curve after Branch 0,
Branch 2 is the rising part of the curve after Branch 1, and so forth.
The branches cross the middle line of the output at x values 0,
PI, 2*PI, 3*PI, and so forth.
Depending on how far you want the graph to extend to the right, it is easy to determine how many branches you need.
For example, to plot from 0 to 8*PI you need nine branches
(Branch 0, Branch 8, and the seven branches between those two).
You can implement each branch using an object of some class,
let's call it ArcSineBranch.
It has a constructor, ArcSineBranch(int), that takes the branch number as a parameter.
Create some sort of ordered list (which could just be an ArcSineBranch[] array) and put these branch objects in it,
making sure the branch numbers go in sequence from 0 up to the largest number needed.
You'll also want to implement some way to tell the first ArcSineBranch where its leftmost end is--in the example in the question, the leftmost end of first branch is at y == 0, whereas for all other rising branches it is at y == -start and for all falling branches it is at y == start.
Now you call a mutator function of the first ArcSineBranch that tells it its leftmost symbol is 0. Treat this as an integer (rather than a string) for now to make the arithmetic easier.
You then query the first ArcSineBranch for the rightmost symbol it will write, which it can compute from the leftmost symbol and the number of lines it will write symbols on.
You also query it for the x coordinate of that rightmost symbol.
(The object computes the x-coordinate of the symbol for any y-coordinate by either adding or subtracting a rounded multiple of Math.asin(y / yPrecision) from a multiple of PI.)
Now for each ArcSineBranch in the list, you pass to it the rightmost symbol and x coordinate written by the previous branch.
This ArcSineBranch uses that information to determine the leftmost symbol it writes and the y coordinate of that symbol.
(I am being careful here about the y coordinate in case you choose a value of xPrecision that causes the rightmost x coordinate of one branch to be the same as the leftmost x coordinate of the next; we should only write one symbol at that place in the output, so we want the later branch to skip its leftmost x coordinate and write its leftmost symbol in the next place, one line up or down. But if the x coordinates are different we want the later branch to write a symbol on the same line.)
Now that the later ArcSineBranch "knows" the leftmost symbol it will print and thata symbol's y coordinate, you can query it for its rightmost symbol and x coordinate, and pass those to the next ArcSineBranch, and so forth.
Once you have traversed all the ArcSineBranch objects in this way,
so that each object knows what symbols need to be written for its branch and where to write them, you can loop for (y = start; y >= -start; y--);
within that loop you loop over the list of ArcSineBranch objects;
for each object you query whether it requires a symbol to be written at
y-coordinate y.
If the object requires a symbol to be written,
you query which symbol to write at which x-coordinate,
then space the output to the right until you reach that x-coordinate and write that symbol there.
But of course, first check that this would not plot a symbol beyond the
right-hand edge of the desired graph.
(This check really only applies to the last ArcSineBranch, so you can optimize the code a bit by looping over the other branches first and then dealing with the last ArcSineBranch separately.)
I've already described this algorithm in more detail than I initially wanted to. There should be enough information here to code this into Java in a relatively straightforward way, though there are still some localized details to be worked out.
Note that the design in this answer is intended to use the same mathematical ideas as the code in the question uses to decide where to plot the points.
Specifically, ArcSineBranch(0) produces the x1 values from the original code, ArcSineBranch(1) produces the x3 values, and ArcSineBranch(2) produces the x2 values.
The implementation of this design should plot a digit at the location of each star plotted by the original code, and should plot no other digits.
Care about a different approach?
3030
28 28
26 26
22 22
18 18
12 12
06 06
00 00 00
06 06
12 12
18 18
22 22
26 26
28 28
3030
Solution:
import static java.lang.Math.sin;
import static java.lang.Math.PI;
import static java.lang.Math.abs;
public class Sine {
static final Integer points = 30; // points on x and y axis
public static void main(String[] args) {
// contains graph points
Boolean[][] graph = new Boolean[points + 1][points + 1];
for (Double x = 0.0; x <= points; x++) {
// x axis pi value
Double pi = (x / points) * 2 * PI;
// sin(x) plot for x
Integer sinx = (int) Math.round((sin(pi) * points / 2) + points / 2);
graph[sinx][x.intValue()] = true;
}
for (Integer i = 0; i <= points; i++) {
for (Integer j = 0; j <= points; j++) {
// space characters on x axis
Integer pt = (int) Math.floor(Math.log10(points) + 1);
String space = String.format("%" + pt + "s", " ");
// padding for p
String p = String.format("%0" + (pt) + "d", abs(i - points / 2) * 2);
System.out.print(graph[i][j] != null ? p : space);
}
System.out.println();
}
}
}
Approach:
points contains the number of characters on x and y axis.
graph contains true or null for each x and y characters.
1st for loop:
Since the value of x in sine graph is from 0 to 2π, we need to convert x accordingly. So pi contains the value of the same range but according to x.
sinx is the Integer value according to x.
No need to explain graph[sinx][x.intValue()] = true;.
2nd for loops:
1st for loop
Execute LOOPLABEL.
Break to next line at the end.
2nd for loop(LOOPLABEL)
pt holds the number for padding on y axis.
space is the space characters to be printed on y axis.
p is the converted range between 0 to points.
Printing graph[i][j]
DEMO
By using the fact that each row has one point (on each slope), you can calculate which digit to display at each point without using extra memory or loops. Here's my example. Note that I only checked that this example only works if xPrecision and yPrecision are integers. You'll have to modify it if you want to use doubles.
class sine {
static final double xPrecision = 10.0; // (1/xPrecision) is the precision on x-values
static final double yPrecision = 10.0; // (1/yPrecision) is the precision on y-values
static final int PI = (int) Math.round(Math.PI * xPrecision);
static final int TPI = 2 * PI; // twice PI
static final int HPI = PI / 2; // half PI
static final int cycles = 2; // prints from x=0 to 2*cycles*pi
public static void main(String[] args) {
double xd;
int cycleoffset, cycleoffset2, topbottomoffset = 1;
for (int start = (int) (1 * yPrecision), y = start; y >= -start; y--) {
double x0 = Math.asin(y / yPrecision), x1 = bringXValueWithinPrecision(x0),
x2 = bringXValueWithinPrecision(x0 + TPI / xPrecision),
x3 = bringXValueWithinPrecision(PI / xPrecision - x0), tmp;
if (y == start) {
if (x1 == x3) // when there is only one point at the top/bottom
topbottomoffset = 0;
else if (x1 > x3) // swap x1 and x3
{
tmp = x1;
x1 = x3;
x3 = tmp;
}
} else if (y == -start) {
// I don't think this is needed, but just for safety make sure there is only one point on the bottom if there was only one point at the top
if (topbottomoffset == 0)
x2 = x3;
else if (x2 < x3) // swap x2 and x3
{
tmp = x2;
x2 = x3;
x3 = tmp;
}
}
cycleoffset = (int) (4 * yPrecision + 2 * topbottomoffset);
cycleoffset2 = -cycleoffset;
int start1 = topbottomoffset + 2 * (int) yPrecision, start2 = 2 * topbottomoffset + 4 * (int) yPrecision;
for (int x = 0, lim = cycles * TPI; x <= lim; x++) {
xd = ((x % TPI) / xPrecision);
if (x % TPI == 0)
cycleoffset2 += cycleoffset;
// x = 0 to pi/2
if (x1 == xd)
System.out.print((cycleoffset2 + y) % 10);
// x = 3pi/2 to 2pi
else if (x2 == xd)
System.out.print((cycleoffset2 + start2 + y) % 10);
// x = pi/2 to 3pi/2
else if (x3 == xd)
System.out.print((cycleoffset2 + start1 - y) % 10);
else
System.out.print(" ");
}
System.out.println();
}
}
public static double bringXValueWithinPrecision(double num) {
// obviously num has 16 floating points
// we need to get num within our precision
return Math.round(num * xPrecision) / xPrecision;
}
}
EDIT
The digits for the different ranges are calculated as follows
0 < x < π/2 : This one is simplest since it is the first range. Since the middle row is y=0 and that is where the sine wave starts, we can just use y to find the digit.
π/2 < x < 3π/2 : The digits here count up as we go down, but y decreases as we go down. So we have to use a -y term. On the top row, y=yPrecision, and the last digit from the previous range was yPrecision. So we use 2*yPrecision - y, because that includes the -y, and is equal to yPrecision at the first term (where y=yPrecision).
3π/2 < x < 2π : The digits here count down as we go down, so we need a +y term, but the tricky part is figuring where to start. Since the sine wave by this point has gone from 0 to yPrecision to 0 to -yPrecision, the bottom point (x=3π/2) should start at 3*yPrecision. Since y=-yPrecision at the bottom point, we use 4*yPrecision + y, since that includes a +y and is equal to 3*yPrecision at the first term (where y=-yPrecision).
The topbottomoffset term : Depending on the values used for xPrecision and yPrecision, there can be one or two points plotted on the top and bottom rows. If there are two points, we need to add one to digits in the π/2 to 3π/2 range, and two to the digits in the 3π/2 to 2π range.
The cycleoffset term : If multiple cycles of the sine wave are plotted, additional cycles need to start from the last digit used in the previous cycle. Each cycle goes from 0 to yPrecision to 0 to -yPrecision to 0, which is equal to 4*yPrecision. So each new cycle needs to start at 4*yPrecision*[the number of previous cycles]. If there are two points on the top and bottom rows, those need to be factored in as well.
Swapping values: When there are two points on the top row, then x1>x3. This happens because when y=yPrecision, we're taking Math.asin(1), which happens to be exactly pi/2=1.5707963267948966 in Java's double system. On lower xPrecision (<100.0), the rounding done by bringXValueWithinPrecision brings x1 up to 1.58 while x3 down to nearly 1.56. Hence, they need to be swapped in order to get the correct numerical order.
Here's my solution, which basically uses the half of the sine in 4 for loops:
from half to 0
from 0 to half
from half to the end
from the end to the half
And in each loop replace only the first asterisk.
class sine {
static final double xPrecision = 14.0; // (1/xPrecision) is the precision on x-values
static final double yPrecision = 14.0; // (1/yPrecision) is the precision on y-values
static final int PI = (int)(3.1415 * xPrecision);
static final int TPI = 2 * PI; // twice PI
static final int HPI = PI / 2; // half PI
public static void main(String[] args) {
double xd;
String str = "";
for (int start = (int)(1 * yPrecision), y = start; y >= -start; y--) {
double x0 = Math.asin(y / yPrecision),
x1 = bringXValueWithinPrecision(x0),
x2 = bringXValueWithinPrecision(x0 + TPI / xPrecision),
x3 = bringXValueWithinPrecision(PI / xPrecision - x0);
// for debug
//System.out.println(y + " " + x0 + " " + x1 + " " + x2 + " " + x3);
for (int x = 0; x <= TPI; x++) {
xd = (x / xPrecision);
if (x1 == xd || x2 == xd || x3 == xd)
str += "*";
else str += " ";
}
str += "\n";
}
String[] rows = str.split("\n");
int half = (int)(1 * yPrecision);
// we use this half in for loops, from half to 0, from 0 to half, from half to the end and from the end to the half, and replace only the first asterisk.
int val = 0;
for (int i = half; i >= 0; i--) {
if (val == 10) val = 0;
rows[i] = rows[i].replaceFirst("\\*", Integer.toString(val++));
}
for (int i = 0; i <= half; i++) {
if (val == 10) val = 0;
rows[i] = rows[i].replaceFirst("\\*", Integer.toString(val++));
}
for (int i = half + 1; i < rows.length; i++) {
if (val == 10) val = 0;
rows[i] = rows[i].replaceFirst("\\*", Integer.toString(val++));
}
for (int i = rows.length - 1; i >= half; i--) {
if (val == 10) val = 0;
rows[i] = rows[i].replaceFirst("\\*", Integer.toString(val++));
}
System.out.println(String.join("\n", rows));
}
public static double bringXValueWithinPrecision(double num) {
// obviously num has 16 floating points
// we need to get num within our precision
return Math.round(num * xPrecision) / xPrecision;
}
}
Result:
01
9 2
8 3
7 4
6 5
5 6
4 7
3 8
2 9
1 0
0 1 2
2 1
3 0
4 9
5 8
6 7
7 6
8 5
9 4
0 3
12
Add a counter in your loop and reset it when 9 is reached:
for(int x = 0, counter = 0; x <= TPI; x++, counter++){
xd = (x / xPrecision);
if(x1 == xd || x2 == xd || x3 == xd) {
System.out.print("" + counter);
if (counter == 9) {
counter = 0;
}
} else {
System.out.print(" ");
}
}

Find out the Number of ways in which two queens intersects (won't be stable) on n*n chessboard?

I can do this using combinations.
Queens won't be stable (under attack) if they are in the same :
Vertical
Horizontal
Diagonal.
So
Its possible by : n * P(n,2) ways
Its possible by : n * P(n,2) ways
Its possible by : 2 * ( P(n,2) + P(n-1,2) + ... + P(2,2)) + 2 * (P(n-1,2) + ... + P(2,2))
What would be an appropriate algo for the above ?
class Main
{
public static void main (String[] args) throws java.lang.Exception
{
int n = 8;
int arr[][] = new int[n][n];
long x = 0;
for (int i=0;i<n;i++){
for (int j=0;j<n;j++){
x += Math.min(n-1-i, n-1-j) + Math.min(i, j) + Math.min(n-1-i,j) + Math.min(i,n-1-j);
x+= 2*n -2;
}
}
System.out.println(x);
}
}
How about the above logic?
Well, for n * n board there are
All: n * n * (n * n - 1) / 2
Stable: n * (n - 1) * (n - 2) * (3 * n - 1) / 6
Unstable: n * (5 * n - 1) * (n - 1) / 3
positions. (See https://oeis.org/A036464 for details). Some examples for small ns:
n all unstable stable
-----------------------------
1 0 = 0 + 0
2 6 = 6 + 0
3 36 = 28 + 8
4 120 = 76 + 44
5 300 = 160 + 140
6 630 = 290 + 340
7 1176 = 476 + 700
8 2016 = 728 + 1288
9 3240 = 1056 + 2184
10 4950 = 1470 + 3480
The implementation (Java) is evident
private static long unstableCount(long n) {
return n * (5 * n - 1) * (n - 1) / 3;
}
It may be interesting to note, that
All = O(n**4)
Stable = O(n**4)
Unstable = O(n**3) // just cube
so for a large board almost all postions are stable.
If queens are distinguishable (e.g. you have white and red queens) all you have to do is to multiply the numbers and formulas above by 2 (swapping queens brings a new position now).
private static long unstableDistinguishableCount(long n) {
return n * (5 * n - 1) * (n - 1) / 3 * 2;
}
Edit: Naive sampling implementation (we loop over all possible queens' positions) could be
private static long unstableCountNaive(int n) {
long result = 0;
for (int file1 = 0; file1 < n; ++file1)
for (int rank1 = 0; rank1 < n; ++rank1)
for (int file2 = file1; file2 < n; ++file2)
for (int rank2 = file1 == file2 ? rank1 + 1 : 0; rank2 < n; ++rank2)
if ((file1 == file2) || // Same file
(rank1 == rank2) || // Same rank
(file1 + rank1 == file2 + rank2) || // Same top-left bottom-right diagonal
(file1 - rank1 == file2 - rank2)) // Same bottom-left top-right diagonal
result += 1;
return result;
}
Edit 2: if I got your idea right, you can just count diagonal attacks and then use symmetry:
private static long unstableCountBetter(int n) {
long result = 0;
// Attacked by top-left bottom-right diagonal
for (int rank = 0; rank < n; ++rank)
for (int file = 0; file < n; ++file)
result +=
(rank + file >= n ? 2 * n - 2 - (rank + file) : rank + file);
result =
// symmetry: we have TWO diagonals
result * 2 +
// At each postion (n * n of them) we have n - 1 checks on the same rank
n * n * (n - 1) +
// At each postion (n * n of them) we have n - 1 checks on the same file
n * n * (n - 1);
// /2 if queens are indistiguished (728 for 8x8 board)
return result / 2;
}
The question is a bit incomplete but looking at the comments, I think I have got all the information to answer the question.
Since you wrote that there is 56 ways for 2 queens to intersect on a 3*3 board, you treat both queens as different, ie. ordered. eg. These 2 boards are different:
..q ..Q
.Q. .q.
... ...
So, the answer to your question is simple formula for n*n board:
(n*n) * (n*n - 1) - n*(n-1)*(n-2)*(3*n-1)/3

Printing pattern from list in Java

What I have done here is taken the contents of the table below and stored them in a list called tableElems
0 1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16 17
18 19 20 21 22 23 24 25 26
27 28 29 30 31 32 33 34 35
List<WebElement> tableElems = chrome.findElements(By.tagName("td"));
From this table I want to print in a pattern starting at the 4th element (#3 in the table) and I want to print 3 elements, then skip the next 6, print the next 3 and then skip the next 6, etc. etc.
So my expected output would be 3 4 5 12 13 14 21 22 23 30 31 32
My initial attempt ended with
for (int i = 3; i<tableElems.size(); i++) {
if(i % 3 == 0) { System.out.println(tableElems.get(i).getText()); }
else if(i % 4 == 0) { System.out.println(tableElems.get(i).getText()); }
else if(i % 5 == 0) { System.out.println(tableElems.get(i).getText()); }
}
Obviously this is wrong, because my % 3 will print the 9th element, % 4 will print the 16th element, etc.
I am having trouble wrapping my head around this, so any advice to point me in the right direction is appreciated!
try this:
for (int i = 3; i<tableElems.size(); i++) {
if (((i / 3) % 3) == 1) { System.out.println(tableElems.get(i).getText()); }
}
Think about this as dividing into groups of nine, and further dividing each group of 9 into groups of 3. on the second group of 3 (i.e. 3-5, 12-14) it will display.
int offset = 4;
int width = 3;
advice:
for each row in table check offset + width is under the row width, and then start from offset + 0, offset + 1 upto offset + width
and continue this loop for all the row of table
You mentioned that tableElems is a list, so I assume it's akin to a single-dimension array, rather than what appears to be a multi-dimensional table like you've laid out(I assume for visual purposes).
You're right by starting the for loop at i = 3. The easiest way, IMO, to do this is to just bump the loop ahead several spaces in the array after you've printed three elements. Here's my solution using C# and an array; you should be able to convert it to Java pretty easily.
int counter = 0;
for (int i = 3; i < array.Length; i++)
{
if (counter < 3)
{
Console.WriteLine(array[i]);
counter++;
}
else
{
i += 5; // we are incrementing by one on the next pass, so this can be 5
counter = 0;
}
}
If you want to stick to %, then this should work
int rowSize = 9;
for (int i = 0; i < tableElems.size(); i++) {
int column = i % rowSize;
if (column >=3 && column <= 5) {
System.out.println(tableElems.get(i).getText());
}
}
Update: Java code
for (int i = 3; i<tableElems.size(); i += 9) {
System.out.println(tableElems.get(i).getText());
System.out.println(tableElems.get(i+1).getText());
System.out.println(tableElems.get(i+2).getText());
System.out.println(tableElems.get(i+3).getText());
}
If you are creating a larger pattern:
int starting = 3;
int nextStartDistance = 9;
int waveCount = 3;
for (int i = starting; i<tableElems.size(); i += nextStartDistance) {
for (int b = 0; b <= waveCount; b ++) {
System.out.println(tableElems.get(i).getText());
}
}
This code is written in JavaScript, but the algorithm considered:
var list =[
0,1,2,3,4,5,6,7,8,
9,10,11,12,13,14,15,16,17,
18,19,20,21,22,23,24,25,26,
27,28,29,30,31,32,33,34,35];
for (var index = 3; index <= list.length; index +=9 ) {
var a = list[index];
var b = list[index+1];
var c = list[index+2];
var d = list[index+3];
console.log(a,b,c,d);
}
Result will be what you expected:
// 3 4 5 6
// 12 13 14 15
// 21 22 23 24
// 30 31 32 33
// user:~$
for (int i = 3; i < tableElems.size(); i += 9) {
for (int j = i; j < i + 3 && j < tableElems.size(); j++) {
System.out.println(tableElems.get(j).getText());
}
}
i think this would be very close to your code:
for (int i = 3; i < tableElems.size(); i++) {
if (i % 3 == 0) {
System.out.println(tableElems.get(i).getText());
} else if ((i % 3) == 1) {
System.out.println(tableElems.get(i).getText());
} else if ((i % 3) == 2) {
System.out.println(tableElems.get(i).getText());
i = i + 6;
}
}
i just adapted your modulo and skip 6 elements every time i hit the last one to print out
furthermore its quite effective because all unneeded elements are just skipped instead of iterated and checked
Assuming you only care about the values out of your table and the html structure is standard html tags as shown on your questions, then you can use css selector to select appropriate values.
chrome.findElements(By.cssSelector("td:nth-child(4),td:nth-child(5), td:nth-child(6)"))
Please note that css nth-child selector is 1 based.

2d array representation

The question is not tied to a specific programming language, but rather to minimalistic code and abstraction.
I have this array of 3 rows and 3 columns - imagine a board in which you'd play Tic-Tac-Toe (or naughts and crosses).
When a key(on the Phone) is pressed a value of 0 or 1 is added to the array(1 for X and 0 for O) in the position corresponding to the key pressed(key 9 being board[2][2]).
In building the GUI, I need to map the array coordinates to pixels, such that if:
[0][0] - 10,10
[0][1] - 10,50
[0][2] - 10,90
...
[2][2] - 90,90
the drawing will take place while traversing the array in a nested loop, but I got stuck on how to write in fewest lines of code as possible the mapping between 0 = 10, 1 = 50 and 2 = 90.
One way to go would be to use a switch for each case. Another would be using an if.
Any other ideas to write this in fewer possible lines?
Thanks!
for ( y = 0; y < 3; ++y )
{
for ( x = 0; x < 3; ++x )
{
pos_x = x * 40 + 10;
pos_y = y * 40 + 10;
// Draw...
}
}
for(var i = 0; i < 3; i++) {
for(var j = 0; j < 3; j++) {
int xPos = i * 40 + 10;
int yPos = j * 40 + 10;
//set accordingly
}
}
Use your index value as multiplicator i.e. 90 = 2 * 40 + 10, 50 = 1 * 40 + 10

Categories