2D array of characters formatting - java

So i am writing a program where i have to read from a file that contains coordinate points and then display the plot. For instance, i have this as the first line, 20 10. What my program should do, is plot this using a 2D array of characters. An 'X' is to be used for the points.
This is how i calculated the slope and the formula for regression line.
float xMean = xSum / count;
float yMean = ySum / count;
float n = count;
float slope = (xySum - n* xMean * yMean) / (xSqSum - n * xMean * xMean);
I used below method to print '-' char if there is no 'X' char and if there is then an '*' char.
for (int i = 0; i < graph.length; i++) {
int yPred = Math.round(yMean + slope * (i - xMean)); // calculate regression value
graph[21-1-yPred][i + 1] = graph[21-1-yPred][i + 1 ] == 'X' ? '*' : '-';
}
Correct output that i am aiming for
However i am getting this output:
What i am trying to achieve is that my program would print "-"s as the regression line segments, and "*"s where a line segment and a point are located at the same spot
However i am getting less dashes in my program as compared to the correct output. Also the asterisk is not in the middle where it is supposed to be.
This is the text file which i am using. I was able to get the validation done with my program. ** x-coordinates in the range [0, 40] and y-coordinates in the range [1, 20].**

Alright so let's knock out this problem! First, after spending 15 minutes or so putting lines to your screen shot text file, here's the image I drew up (depicting the original of course):
Now, you mentioned having a line or entry of an 'X' you are to draw up. This is also a text file and you're reading it in from file, so here's what said file (let's call it 'coords.txt' for the sake of this example).
20 10
With 20 and 10 being the coordinates read, based off the line-overlay image I made, I think that (20 10) would correlate to x-axis=21, y-axis=10 (The off by one is likely to be a simple indexing off by one error - read more here I basically just treated the graph like a graph ).
This is one way to read that point/data in from file and prepare it to be plotted:
read 20 10 from file by
Scanner s = new Scanner(new File("coords.txt"));
int x = 0;
int y = 0;
if (s.hasNext())
x = s.nextInt();
if (s.hasNext())
y = s.nextInt();
s.close();
That code is easy enough, in that it makes a Scanner object to read the contents of our file. Then, declaring an x and y integer in order to store our coord values. Note: s.hasNext() is valuable logic in general to check to make sure there's something in the text file to read before trying to read it - you could also adapt s.hasNextInt() in order to only look ahead for an integer token next up to read from file.
However, I notice you have several X-marks-the-spot on your result graph. By going back to the image I drew up to visually see the coordinates you would likely have in your non-mentioned explicitly 'coords.txt' file, let's say in this example you would have a file with the following lines:
20 10
0 1
40 20
13 17
10 20
Now these numbers are based off that original image I drew lines over, however I respected the off-by-one error so that's why they don't directly correlate to coordinates on that image, because for the sake of correcting that off-by-one error.
Now with several coords, how to go about reading that input in a more efficient manner? Here's one way to go about it:
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class App {
public static final int SIZE = 100;
public static void main(String[] args) throws IOException {
Scanner s = new Scanner(new File("C:\\Users\\Nick\\Desktop\\coords.txt"));
int x = 0;
int y = 0;
int[] xCoords = new int[SIZE];
int[] yCoords = new int[SIZE];
int index = 0;
while (s.hasNextLine()) {
if (s.hasNextInt()) {
x = s.nextInt();
} else {
System.out.println("had a next line, but no integers to read");
break;
}
if (s.hasNextInt()) {
y = s.nextInt();
} else {
System.out.println("had a next line, but no integers to read");
break;
}
xCoords[index] = x;
yCoords[index] = y;
index++;
}
s.close();
}
}
This code assumes several things, including;
we don't think we're going to read more than 100 coordinates to plot. (If you do know this number, simply edit the SIZE value to the pre-determined value. If you don't know the value, then look into growing/expanding an array or java.util.List and a tutorial on the java list interface).
the xCoords and yCoords integer arrays are matching/mirror in that they should both be filled at a given index in order to represent a plot-able coordinate (X-marks-the-spot).
likewise to the previous point, in the while loop, each line is thought to contain two integer values to read that resemble a coordinate.
the integer index value increases after each loop to help ready the next point to read in and also let us know how many points were read in while the while loop was looping.
Running the above code for reading the 'coords.txt' file, and adding a few simple System.out.println()'s after the while loop but before the s.close(); helps show what was read in.
Here's the second version of the input reading, along with the output to show what happened:
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class App {
public static final int SIZE = 100;
public static void main(String[] args) throws IOException {
Scanner s = new Scanner(new File("C:\\Users\\Nick\\Desktop\\coords.txt"));
int x = 0;
int y = 0;
int[] xCoords = new int[SIZE];
int[] yCoords = new int[SIZE];
int index = 0;
while (s.hasNextLine()) {
if (s.hasNextInt()) {
x = s.nextInt();
} else {
System.out.println("had a next line, but no integers to read");
break;
}
if (s.hasNextInt()) {
y = s.nextInt();
} else {
System.out.println("had a next line, but no integers to read");
break;
}
xCoords[index] = x;
yCoords[index] = y;
index++;
}
System.out.println("Output from what was read in from file:");
for (int i = 0; i < index; ++i) {
System.out.print(xCoords[i] + ", ");
System.out.println(yCoords[i]);
}
s.close();
}
}
And the respective output:
had a next line, but no integers to read
Output from what was read in from file:
20, 10
0, 1
40, 20
13, 17
10, 20
The first two lines are just comments that can be removed. It's good to see we can read in our data effectively!
Moving onto the bread-and-butter part of the problem, the full output. In order to output the example image, we need to effectively print out a 2D array of characters (at least that's the idea I'll use to explain here).
We know (based on looking at the line-marked graph) that we need to have dimensions of 21 x 42 for complete replica output. This is because of the axis markings themselves. So, let's start off by declaring a 2D array like:
char[][] graph = new char[21][42];
That's great! We have an invisible graph! Let's get those crummy null characters out and put some good old spaces in! After all, this is the root cause of printing everything out all funky, you can't expect the char value of '\0' to behave the same as ' '.
for (int i = 0; i < graph.length; ++i)
for (int j = 0; j < graph[0].length; ++j)
graph[i][j] = ' ';
Now let's start marking it up with the bare axis. First the y-axis:
for (int i = 0; i < graph.length; ++i) {
graph[i][0] = '/';
}
graph[20][0] = '+';
Note: we can cheat with the + symbol since it comes at the very end. The for-loop could use and if statement and mark the last index with the + but lets try to be intuitive too.
Then, for the x-axis:
for (int i = 1; i < graph[0].length; ++i) {
graph[20][i] = '-';
}
Since we know where the very end is, we simply use the hard-coded value of 20 and loop over the index to input the x-axis symbols/char -.
Let's take a look at this newly created graph with the following code:
for (int i = 0; i < graph.length; ++i) {
for (int j = 0; j < graph[0].length; ++j) {
System.out.print(graph[i][j]);
}
System.out.println();
}
Which should produce the following output:
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
+-----------------------------------------
Let's plot the X-marks-the-spot now, based on what you used with the coordinates from the earlier code.
This can be done by looping over the mirror integer arrays (xCoords and yCoords) and using those coords to plot onto the 2D char[][] graph.
for (int i = 0; i < index; ++i) {
graph[21 - 1 - yCoords[i]][xCoords[i] + 1] = 'X';
}
Breaking down the information here (above), the [21 - 1 - yCoords[i]] is meant to translate the y-coordinate to the respective spot represented in the 2D array by using a offset from the top value of the graph portrayed backwards (hence using 21 to start from the top) and also another minus one offset because of the axis itself (e.g. the '/' and '-' and '+' characters respectively). For the xCoords, a simply plus one is used for the axis itself offset.
Here is that output:
/ X X
/
/
/ X
/
/
/
/
/
/
/ X
/
/
/
/
/
/
/
/
/X
+-----------------------------------------
Looks very like an early stage of those pictures of what the output is suppose to be!
All in all, this is what my final code looked like:
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class App {
public static final int SIZE = 100;
public static void main(String[] args) throws IOException {
Scanner s = new Scanner(new File("C:\\Users\\Nick\\Desktop\\coords.txt"));
int x = 0;
int y = 0;
int[] xCoords = new int[SIZE];
int[] yCoords = new int[SIZE];
int index = 0;
while (s.hasNextLine()) {
if (s.hasNextInt()) {
x = s.nextInt();
} else {
System.out.println("had a next line, but no integers to read");
break;
}
if (s.hasNextInt()) {
y = s.nextInt();
} else {
System.out.println("had a next line, but no integers to read");
break;
}
xCoords[index] = x;
yCoords[index] = y;
index++;
}
System.out.println("Output from what was read in from file:");
for (int i = 0; i < index; ++i) {
System.out.print(xCoords[i] + ", ");
System.out.println(yCoords[i]);
}
s.close();
char[][] graph = new char[21][42];
for (int i = 0; i < graph.length; ++i)
for (int j = 0; j < graph[0].length; ++j)
graph[i][j] = ' ';
for (int i = 0; i < graph.length; ++i)
graph[i][0] = '/';
graph[20][0] = '+';
for (int i = 1; i < graph[0].length; ++i)
graph[20][i] = '-';
for (int i = 0; i < index; ++i)
graph[21 - 1 - yCoords[i]][xCoords[i] + 1] = 'X';
for (int i = 0; i < graph.length; ++i) {
for (int j = 0; j < graph[0].length; ++j)
System.out.print(graph[i][j]);
System.out.println();
}
}
}
If you want to include more detail, e.g. multiple '-' for regression and '*' for point, I'd encourage using this information to learn and adapt to reading those coordinates for that additional information and applying it to this example. There's no supplied information on that however, so I won't venture off topic with alleged text files and coords for that, either edit it into the question or try it yourself and learn something. :) Cheers

Why not just array[x][y] = 'X'; ?
Also, what are you putting into the rest of the array? If you don't put anything there, it defaults to 0 which displays as nothing on the terminal. I'm guessing you wanted to fill the unused entries with spaces and newlines

Related

Creating a User-Input Asterisk Triangle using Java

I want to...
create an asterisk triangle, using Java, that matches the length of whatever number (Between 1-50) the user enters.
Details
The first line would always start with an asterisk.
The next line would increment by one asterisk until it matches the
user's input.
The following lines would then decrement until it is back to one
asterisk.
For instance, if the user was to enter 3, then the output would have one asterisk on the first line, two asterisks on the second line, three asterisks on the third line, and then revert back to two asterisks on the following line before ending with an asterisk on the last line.
What I've tried so far
I am required to use nested for loops. So far, I tried to test it out using this practice example I made below. I was only able to create on output of the numbers. I also have some concepts of outputting asterisk triangles. How can I apply the concept of this code to follow along the user's input number?
import java.util.Scanner;
public class Program
{
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
int count, index = 0, value, number;
System.out.println("This program creates a pattern of numbers " );
System.out.println("Based on a number you enter." );
System.out.println("Please enter a positive integer. " );
count = keyboard.nextInt();
value = count;
for (index = 1; index <= count; index++)
{
for (number = value; number >= 1; number--)
{
System.out.println(number);
}
value--;
System.out.println();
}
}
}
Here's how i would proceed
write a method printAsterisks that takes an int N as parameter and writes a line of N asterisks. You wil need a for loop to do so.
call printAsterisks in a for loop that counts from 1 to COUNT
call printAsterisks in a second loop that counts down from COUNT-1 to 1
That should do the trick.
Also, as a side note, you should close your scanner. The easy way to do so is enclose ot in a try-with-resource like so :
try (Scanner keyboard = new Scanner(System.in);) {
// your code here
}
Let us know the version of the program taht works (or the question you still have) :)
HTH
Here is what you want:
public class Asterisk {
private static final String ASTERISK = "*";
private static final String SPACE = "";
private static int LENGTH;
public static void main(String[] args) {
try{
readLength();
for (int i=1; i<=LENGTH; i++) {
if (i == LENGTH) {
for (int j=LENGTH; j>=1; j--) {
drawLine(j);
}
break;
}
drawLine(i);
}
}catch (Exception e) {
System.out.println("You must enter a number between 1 and 50.");
}
}
static void readLength(){
System.out.println("Enter asterisk's length (1-50)");
LENGTH = Integer.parseInt(System.console().readLine());
if (LENGTH<=0 || LENGTH>50)
throw new NumberFormatException();
}
static void drawLine(int asterisks){
StringBuilder line = new StringBuilder();
int spacesLeft = getLeftSpaceCount(asterisks);
int spacesRight = getRightSpaceCount(asterisks);
for (int i=0; i<spacesLeft; i++) {
line.append(SPACE);
}
for (int i=0; i<asterisks; i++) {
line.append(ASTERISK);
}
for (int i=0; i<spacesRight; i++) {
line.append(SPACE);
}
System.out.println(line.toString()+"\n");
}
static int getLeftSpaceCount(int asterisks){
int spaces = LENGTH - asterisks;
int mod = spaces%2;
return spaces/2 + mod;
}
static int getRightSpaceCount(int asterisks){
int spaces = LENGTH - asterisks;
return spaces/2;
}
}
I am required to use nested for loops
Yes, the main logic lies there...
for (int i=1; i<=LENGTH; i++) {
if (i == LENGTH) {
for (int j=LENGTH; j>=1; j--) {
drawLine(j);
}
break;
}
drawLine(i);
}
The triangle using 5 as input.
*
**
***
****
*****
****
***
**
*
Tip:
There is an easier way to get input from the user usingSystem.console().readLine().
In regards to the printing part, I wanted to clean up the answers a little:
int input = 3; //just an example, you can hook in user input I'm sure!
for (int i = 1; i < (input * 2); i++) {
int amount = i > input ? i / 2 : i;
for (int a = 0; a < amount; a++)
System.out.print("*");
}
System.out.println();
}
For our loop conditions, a little explanation:
i < (input * 2): since i starts at 1 we can consider a few cases. If we have an input of 1 we need 1 row. input 2, 3 rows. 4: 5 rows. In short the relation of length to row count is row count = (length * 2) - 1, so I additionally offset by 1 by starting at 1 instead of 0.
i > input ? i / 2 : i: this is called a ternary statement, it's basically an if statement where you can get the value in the form boolean/if ? value_if_true : value_if_false. So if the row count is bigger than your requested length (more than halfway), the length gets divided by 2.
Additionally everything in that loop could be one line:
System.out.println(new String(new char[i > input ? i / 2 : i]).replace('\0', '*'));
And yeah, technically with a IntStream we could make this whole thing a one-line, though at that point I would be breaking out newlines for clarity
Keep in mind, I wouldn't call this the "beginner's solution", but hopefully it can intrigue you into learning about some other helpful little things about programming, for instance why it was I replaced \0 in my one-line example.

How to print only the last element of an array?

I am trying to print the last element of my array. The code can be seen below:
double [] results = new double[21];
double t = 9600;
for(int y = 0; y < 21; y++) {
results[y] = t;
t *= 1.04;
System.out.println(results[results.length - 1]);
}
However, when I attempt to run this, I get this result:
0.0 (printed 20 times in a row)
...
21034.782173120842
I do not know why it is printing out 20 zero's, and then the answer I want (21034.78). I thought that by doing results[results.length - 1], only the last element of the array would be printed. I have a suspicion that this has to do with the loop, but I do not know why or how to fix it.
Any help or advice would be greatly appreciated. Thank you!
You need to put the System.out.println outside the for loop, or else you will always print 0.0 because the last index of the array isn't filled yet.
double [] results = new double[21];
double t = 9600;
for(int y = 0; y < 21; y++) {
results[y] = t;
t *= 1.04;
}
System.out.println(results[results.length - 1]);
Output: 21034.782173120842
put your System.out.println , out of loop.
for(int y = 0; y < 21; y++) {
** YOUR LOGIC **
}
System.out.println(results[results.length - 1]);
You need to move the print statement outside the loop..
double [] results = new double[21]; double t = 9600;
for(int y = 0; y < 21; y++) {
results[y] = t;
t *= 1.04;
}
System.out.println(results[results.length - 1]);
You need to make a slight alteration. Here is one thing that you can do:
double [] results = new double[21];
double t = 9600;
for(int y = 0; y < results.length; y++) {
results[y] = t;
t *= 1.04;
System.out.println(results[y]);
}
You can print the current index [y] each time through the loop. Or else you're always printing index 21 which isn't filled yet and will repeatedly print 0 until it is filled. The current iteration of the loop [y] will always be the last index that actually has a value in it, but the last index won't actually be filled with a value until your last iteration through the loop which explains your error here.

Java: taking char input from array results in infinite loop

This is the link the problem that I am trying to solve: https://dmoj.ca/problem/dmopc14c1p5
Here is the code that I have written for taking in input.
public static void main(String[] args)
{
Scanner kbd = new Scanner(System.in);
int y = kbd.nextInt(); //number of rows
int x = kbd.nextInt(); //number of columns
int initX = kbd.nextInt(); //initial starting position
int initY = kbd.nextInt();
int endX = kbd.nextInt(); //ending position (main office)
int endY = kbd.nextInt();
char [] [] maze = new char [y][x];
for (int i = 0; i < y; i++)
{
for (int j = 0; j < x; j++)
{
maze[i][j] = kbd.next().charAt(0);
}
}
//For checking
for (int i = 0; i < y; i++)
{
for (int j = 0; j < x; j++)
{
System.out.print(maze[i][j]);
}
System.out.println();
}
}
However, I don't know how to properly take in the char input in the for loop. I used the scanner.next().charAt(0) method I found with this link (How to take input for 'char' array in Java?), but it results in an infinite loop that does not end no matter how many characters I input.
What am I doing wrong?
Update:
This is the input that I will be receiving (There are no white spaces between characters):
OOXOO
OXOXO
OOOXX
XOXOX
OOOOO
How should I modify my code to make reading this input possible?
Your code works properly. Just remembers that you need to type atleast x*y (your variable name) times of char.
EDIT: I just saw your update. We need to think about it a little bit.
.charAt(0)
Only takes the first character of a string and return it. If you want to take "ooxoo" and turn it into ['o','o','x','o','o'], you can use the toCharArray method on strings. However if you do this, your for loop will loop longer than needed. If you know your sets of input, you can only loop through n numbers of strings and accept them and convert them into array. Let me know if you want me to go more in details.
The java.util.Scanner.next() method finds and returns the next
complete token from this scanner.
Every time you call kbd.next().charAt(0), you call next() and get a complete token. The tokens, by default, are separated by whitespace.
You also need to hit ENTER before System.in makes an data available.
So, enter your characters separated by spaces and end the input with a carriage return.

How do I print out an hourglass using asterisks?

For a homework assignment, I am trying to construct a program that prints an hourglass shape to the screen using asterisks and spaces. I have written the program below, but its output doesn't look anything like an hourglass. Can anyone help me understand why my program isn't producing the expected output?
public class hourglass {
public static void main(String[] args) {
int x = Integer.parseInt(args[0]);
int k = 2 * x - 1;
int c = k;
for (int j = x; j > 0; j--) {
for (int f = j; f <= k; f++) {
System.out.print("*");
}
for (int o = 1; o <= c; o++) {
if (k % 2 == 0) System.out.print(" ");
else System.out.print(" ");
}
System.out.print("\n");
}
}
}
EDIT: I redid the program now it just prints into infinity and beyond, I understand the logic that I need to take in a x number and then run a for loop, each and every time I go through it I -1 from the x.
Can anyone help me with this please? I'm simply trying to deepen my understanding in Java.
public class hourglass
{
public static void main(String[] args)
{
int valueIn = Integer.parseInt(args[0]);
int maxVALUE = 2*valueIn ;
for( int i = 0 ; (valueIn - 1) > i; i--)
{for( int j =1 ; j < maxVALUE; i++)
{
System.out.print("*");}
for (int o = 1; o < maxVALUE; o++) {
if (maxVALUE % 2 == 0) System.out.print(" ");
else System.out.print(" ");
}
System.out.print("\n");
}
}
}
EDIT 2*
If anyone sees this well, here I go.
I've constructed a code on my own for the past 8 hours and now I'm stuck, I don't know how I can "reverse" my for loop to make it print into the other direction here's my code, I don't know what to do and if anyone can give me any insight on how to do this I would be very pleased, I tried doing an if case if(i == 0) but that never happens and I even tried making that if case ==1; but then the loop ran forever.
Any pointers on how to finish my program?
public class mathrandom
{
public static void main ( String [] args)
{
int valueIn = Integer.parseInt(args[0]);
for ( int i = valueIn; 1 <= i; i--){
for ( int k = i ; k < 2*valueIn -1; k++)
{System.out.print(" ");}
{for ( int j = 1; j <= (i*2)-1; j++)
{
System.out. print("*");
}
System.out.println();
}
}
}}
If you don't think in code (and what novice does?), you can try starting by writing a prose(-ish) description of how your program will go about its task, and then writing code that matches up to the prose. For example, you might start with:
Given an input x representing the width of an hourglass shape, print the hourglass to the screen as a series of lines containing asterisks and spaces. The number of asterisks on each line will start at x, count down by two per line until a line containing fewer than two asterisks, then count back up by two per line until it reaches x again. An appropriate number of leading spaces will be printed on each line to center that line's run of asterisks relative to the other lines' (assuming spaces are displayed with the same width as asterisks).
You can even put that into your source code as a comment. In fact, it can help to break it up into several smaller comments, so that you can follow each logical thought with code that corresponds specifically to that thought. If you do that, then not only does it help you organize your code, but you end up with a nicely-documented program without any extra effort.
If you compare my prose to your program, you should see both similarities and differences. Your program performs some kind of count-down, at each step printing zero or more space characters, some asterisks, and then a newline to end the line. Those are basically the right things for it to do, but the details are wrong. Enough wrong and oddly enough wrong, in fact, that I'm inclined to suspect that the program is more cribbed from external sources than thoughtfully constructed de novo. I suggest from here out you devote your attention to writing the program yourself. In fact, consider starting by tossing out everything in main() except int x = Integer.parseInt(args[0]);.

Computing number of squares between two numbers, works only with small numbers, why?

The problem is to find the numbers of squares between two numbers.
The code below works small numbers but fails for huge numbers. How can I correct this?
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
public class NumOfSqrs {
public static void main(String[] args) {
try{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String input;
int line = 0;
int testCases;
int numOfSqrt = 0;
int j = 0;
while((input=br.readLine())!=null){
if(line == 0){
testCases = Integer.parseInt(input);
line = line +1;
}
else{
String[] splitter = input.toString().split(" ");
//Here splitter gives two numbers, we need to find no of sqrs b/w these numbers for eg say 3 and 9
for(int i = Integer.parseInt(splitter[0]); i<=Integer.parseInt(splitter[1]) ; i++){
String value = ""+Math.sqrt(i);
String[] isSqrt = value.toString().split("\\.");
//System.out.println(""+isSqrt[0] + "" + isSqrt[1]);
//Here lets say if 'i' is 4 (i.e 2.0) then isSqrt[0] = 2, isSqrt[1] = 0 and if isSqrt[1] != 1 then its obvious that its not a perfect square
if(isSqrt[1].length() == 1){
numOfSqrt++;
}
}
System.out.println(""+numOfSqrt);
}
numOfSqrt = 0;
}
}catch(IOException io){
io.printStackTrace();
}
}
}
Your technique for determining squares (converting to String and splitting on dot) is dodgy.
It's also unnecessary - you can use purely numeric approach in just one line:
int low, high; // fill from input
int numOfSqrt = (int) (Math.floor(Math.sqrt(high)) - Math.ceil(Math.sqrt(low)) + 1);
This is a simpler algorithm, and it works up to 100,000,000 relatively fast.
int low = 1, high = 100000000;
int max = 0;
int count = 0;
for (int j = low; j <= high; j++)
{
while (max * max < j)
max++;
if (max * max == j)
Console.WriteLine(max * max);
}
I will suggest to find the square root the first number given in the input ,let us take it as 10 and the square root will be like 3.(some thing) now take 4 and check whether 16 is in the range and like that for 5 check whether 25 is in the range and so on.

Categories