Trouble with a java histogram issue - java

This is the question:
Design and implement an application that creates a histogram that allows you to
visually inspect the frequency distribution of a set of values. The program should read in
an arbitrary number of integers that are in the range 1 to 100 inclusive; then produce a
chart similar to the one below that indicates how many input values fell in the range 1
to 10, 11 to 20, and so on. Print one asterisk for each value entered.
1 - 10 | *****
11 - 20 | **
21 - 30 | *******************
31 - 40 |
41 - 50 | ***
51 - 60 | ********
61 - 70 | **
71 - 80 | *****
81 - 90 | *******
91 - 100 | *********
Source Code:
import java.io.*;
import java.util.Scanner;
public class histogram
{
public static void main(java.lang.String[] args)
throws IOException
{
Scanner scan = new Scanner (System.in);
final int min = 1;
final int max = 10;
final int limit = 10;
int[] a = new int[max];
for (int b = 0; b < a.length; b++)
{
a[b] = 0;
}
System.out.println("Enter Number between 1 and 100: \n (Or press 0 to stop)");
int number = scan.nextInt();
while (number >= min && number <= (limit*max) && number != 0)
{
a[(number-1)/limit] = a[(number - 1 ) / limit] + 1;
System.out.print("Please enter a value:");
number = scan.nextInt();
}
System.out.println("\n__Histogram__");
for (int y = 0; y < a.length; y++)
{
System.out.print(" " + (y * limit + 1) + " - " + (y + 1) * limit + "\t");
return;
}
for (int z = 0; z < a[b]; z++)
{
System.out.print("*");
}
System.out.println(0);
}
}
In the last for statement, it says that b cannot be resolved to a variable. When I use java for help it sets b to 0 and the program doesn't run correctly. Any ideas?

Since b was an array index in the earlier loop, I think you will need to put the last loop inside the loop to increment through the array indexes as you did in the beginning.
Changed b to y and moved z for loop inside y for loop.
for (int y = 0; y < a.length; y++)
{
System.out.print(" " + (y * limit + 1) + " - " + (y + 1) * limit + "\t");
for (int z = 0; z < a[y]; z++)
{
System.out.print("*");
}
System.out.println();
}

Related

My logic doesn't work for computing a histogram

Write a program Example.java to compute data to construct a histogram of integer values read from a file. A histogram is a bar chart in which the length of each bar gives the number of items that fall into a certain range of values, usually called a bin. You won’t actually be drawing a bar chart, but instead will print out the size of each bin.
Your program should take four command line arguments:
The name of a file containing an array of integers
An integer b giving the number of bins to sort into.
A integer min giving the lowest number in the smallest bin.
An integer s giving the size (number of distinct integers) in each bin. You can assume (without checking) that b > 0 and s > 0.
Divide the range of values of interest into b bins of size s. Count the number of values from the file that fall into each bin. Also count the number of values that are completely below or above the range.
For example, given this test file data1:"05X/data1"
1 15
2 18 11 -101 51 92 53 45 55 52 53 54 55 56 5 -2
The output of java Example data1 10 -10 7 should be
x < -10: 1
-10 <= x < -3: 0
-3 <= x < 4: 1
4 <= x < 11: 1
11 <= x < 18: 1
18 <= x < 25: 1
25 <= x < 32: 0
32 <= x < 39: 0
39 <= x < 46: 1
46 <= x < 53: 2
53 <= x < 60: 6
x >= 60: 1
My code below is able to print out the first line of the output. The for loop to print out the range min <= x < max : bin keeps getting the exception
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 1 out of bounds for length 1 at Example.main(Example.java:49)
What syntax is wrong here? Please help
class Example {
public static void main (String argv[]) throws IOException {
if (argv.length != 4)
usage ();
int[] is = {0};
int b = 0;
int min = 0;
int s = 0;
try {
is = readIntArray(argv[0]);
b = Integer.parseInt (argv[1]);
min = Integer.parseInt (argv[2]);
s = Integer.parseInt(argv[3]);
} catch (NumberFormatException e) {
usage();
}
int max = b * s + min;
int [] count = {0};
for (int i = 0; i < is.length; i++)
if (is[i] < min){
count[0]++;
} else if (i >= max) {
count[b+1]++;
} else {
int n = min;
int index = 0;
while (i < n + s){
n += s;
index++;
count[i]++;
}
}
System.out.println("x < " + min + ": " + count[0]);
for (int i = 1; i <= b; i++){
int low = s * i + min;
int high = s * (i + 1) + min;
System.out.println(low + " <= x < " + high + ": " + count[i]);
}
System.out.println("x >= " + max + ": " + count[b + 1]);
}
Your count array has a length of 1: int [] count = {0}; but you're trying to access higher indices:
if (is[i] < min){
count[0]++;
} else if (i >= max) {
count[b+1]++; //here
} else {
int n = min;
int index = 0;
while (i < n + s){
n += s;
index++;
count[i]++; // and here
}
}
Since indices other that 0 don't exist in the array, they're out of bounds, so you're getting an exception.

How to change the increment in a loop to more than one?

For one of my programming projects, I was told to make one of these charts:
1 - 10 | *****
11 - 20 | **
21 - 30 | *******************
31 - 40 |
41 - 50 | ***
51 - 60 | ********
61 - 70 | **
71 - 80 | *****
81 - 90 | *******
91 - 100| *********
This is an array that when the user inputs numbers in a particular range it adds a * for each value entered in that range. I have already created a program that creates one of these charts. My next programming project tells me to only add an * for every five values entered in a particular range of numbers. If less than 5 values are entered then no *'s will be printed. I don't know how I should approach this problem.
Here is the code for the chart:
import java.util.Scanner;
public class SixFive
{
public static void main(String[] args)
{
int[] counts = new int[10];
Scanner scan = new Scanner(System.in);
System.out.println("Enter integers between 1-100");
while(scan.hasNextInt())
{
int num = scan.nextInt();
if (num < 1 || num > 100)
break;
counts[(num - 1) / 10]++;
}
scan.close();
for (int i = 0; i < 10; i++)
{
System.out.format("%2d -%3d ", i*10+1, i*10+10);
for (int j = 0; j < counts[i]; j++)
System.out.print("*");
System.out.println();
}
}
}
In your inner loop, replace the condition j < counts[i] by j < counts[i] / 5 like this:
for (int i = 0; i < 10; i++) {
System.out.format("%2d -%3d | ", i * 10 + 1, i * 10 + 10);
for (int j = 0; j < counts[i] / 5; j++)
System.out.print("*");
System.out.println();
}

Formatting This Magical Square

I am looking to format the output of this code so that the totals of the rows and columns show up next to/below said row/column. I am getting the numbers correct, but spaces and char counts seem to be too unpredictable to format it correctly for any size square. Here is the code i currently have.
public void printSquare()
{
for (int x = 0; x < square.length; x ++)
{
System.out.println();
for (int j = 0; j < square.length; j++)
{
System.out.print(" " + square[x][j]);
}
System.out.println(" | " + sumRow(x));
}
System.out.print(sumOtherDiag());
for (int x = 0; x < square.length; x ++)
{
System.out.print(" ^");
}
System.out.println(sumMainDiag());
for (int x = 0; x < square.length; x ++)
{
System.out.print(" " + sumCol(x));
}
}
And the output for this is..
8 1 6 | 15
3 5 7 | 15
4 9 2 | 15
15 ^ ^ ^15
15 15 15
Are there any strategies in order to more reliably format something like this?
Instead of
System.out.printf(" " + square[x][j]);
use
System.out.printf("%4d", square[x][j]); // 4 positions for right-aligned decimal
and so on for other similar statements.

Printing odd numbers in odd sequences

There's this problem from my programming class that I can't get right... The output must be all odd numbers, in odd amounts per line, until the amount of numbers per line meets the odd number that was entered as the input. Example:
input: 5
correct output:
1
3 5 7
9 11 13 15 17
If the number entered is even or negative, then the user should enter a different number. This is what I have so far:
public static void firstNum() {
Scanner kb = new Scanner(System.in);
int num = kb.nextInt();
if (num % 2 == 0 || num < 0)
firstNum();
if (num % 2 == 1)
for (int i = 0; i < num; i++) {
int odd = 1;
String a = "";
for (int j = 1; j <= num; j++) {
a = odd + " ";
odd += 2;
System.out.print(a);
}
System.out.println();
}
}
public static void main(String[] args) {
Scanner kb = new Scanner(System.in);
firstNum();
}
The output I'm getting for input(3) is
1 3 5
1 3 5
1 3 5
When it really should be
1
3 5 7
Can anyone help me?
Try this:
public static void firstNum() {
Scanner kb = new Scanner(System.in);
int num = kb.nextInt();
while (num % 2 == 0 || num < 0) {
num = kb.nextInt();
}
int odd = 1;
for (int i = 1; i <= num; i += 2) {
String a = "";
for (int j = 1; j <= i; j++) {
a = odd + " ";
odd += 2;
System.out.print(a);
}
System.out.println();
}
}
if (num % 2 == 1) {
int odd = 1;
}
for (int i = 0; i < num; i++) {
String a = "";
for (int j = 1; j <= odd; j++) {
a = odd + " ";
odd += 2;
System.out.print(a);
}
System.out.println();
}
You should assign odd before for loop.
In inner for loop compare j and odd together.
For questions like this, usually there is no need to use and conditional statements. Your school probably do not want you to use String as well. You can control everything within a pair of loops.
This is my solution:
int size = 7; // size is taken from user's input
int val = 1;
int row = (size / 2) + 1;
for (int x = 0; x <= row; x++) {
for (int y = 0; y < (x * 2) + 1; y++) {
System.out.print(val + " ");
val += 2;
}
System.out.println("");
}
I left out the part where you need to check whether input is odd.
How I derive my codes:
Observe a pattern in the desired output. It consists of rows and columns. You can easily form the printout by just using 2 loops.
Use the outer loop to control the number of rows. Inner loop to control number of columns to be printed in each row.
The input number is actually the size of the base of your triangle. We can use that to get number of rows.
That gives us: int row = (size/2)+1;
The tricky part is the number of columns to be printed per row.
1st row -> print 1 column
2nd row -> print 3 columns
3rd row -> print 5 columns
4th row -> print 7 columns and so on
We observe that the relation between row and column is actually:
column = (row * 2) + 1
Hence, we have: y<(x*2)+1 as a control for the inner loop.
Only odd number is to be printed, so we start at val 1 and increase val be 2 each time to ensure only odd numbers are printed.
(val += 2;)
Test Run:
1
3 5 7
9 11 13 15 17
19 21 23 25 27 29 31
33 35 37 39 41 43 45 47 49
You can use two nested loops (or streams) as follows: an outer loop through rows with an odd number of elements and an inner loop through the elements of these rows. The internal action is to sequentially print and increase one value.
a loop in a loop
int n = 9;
int val = 1;
// iterate over the rows with an odd
// number of elements: 1, 3, 5...
for (int i = 1; i <= n; i += 2) {
// iterate over the elements of the row
for (int j = 0; j < i; j++) {
// print the current value
System.out.print(val + " ");
// and increase it
val += 2;
}
// new line
System.out.println();
}
a stream in a stream
int n = 9;
AtomicInteger val = new AtomicInteger(1);
// iterate over the rows with an odd
// number of elements: 1, 3, 5...
IntStream.iterate(1, i -> i <= n, i -> i + 2)
// iterate over the elements of the row
.peek(i -> IntStream.range(0, i)
// print the current value and increase it
.forEach(j -> System.out.print(val.getAndAdd(2) + " ")))
// new line
.forEach(i -> System.out.println());
Output:
1
3 5 7
9 11 13 15 17
19 21 23 25 27 29 31
33 35 37 39 41 43 45 47 49
See also: How do I create a matrix with user-defined dimensions and populate it with increasing values?
Seems I am bit late to post, here is my solution:
public static void firstNum() {
Scanner scanner = new Scanner(System.in);
System.out.println("Enter the odd number: ");
int num = scanner.nextInt();
if (num % 2 == 0 || num < 0) {
firstNum();
}
if (num % 2 == 1) {
int disNum = 1;
for (int i = 1; i <= num; i += 2) {
for (int k = 1; k <= i; k++, disNum += 2) {
System.out.print(disNum + " ");
}
System.out.println();
}
}
}

Java Programming Code

I am trying to produce the following results:
120
200 202
280 284 288
360 366 372 378
440 448 456 464 472
520 530 540 550 560 570
600 612 624 636 648 660 672
680 694 708 722 736 750 764 778
760 776 792 808 824 840 856 872 888
As you can see, each row increases by 80 and difference between consecutive numbers in each row is i*2 (where i row number starting with 0)
I have written this code down which actually makes this result:
public class Triangle
{
public static void main(String [] args)
{
System.out.println(120);
System.out.print(i + " ");
}
System.out.println();
for (int i = 280 ; i <= 288; i = i + 4 ) {
System.out.print(i + " ");
}
System.out.println();
System.out.print(i + " ");
}
System.out.println();
for (int i = 440 ; i <= 472; i = i + 8 ) {
System.out.print(i + " ");
}
System.out.println();
for (int i = 520 ; i <= 570; i = i + 10 ) {
System.out.print(i + " ");
}
System.out.println();
for (int i = 600 ; i <= 672; i = i + 12 ) {
System.out.print(i + " ");
}
System.out.println();
for (int i = 680 ; i <= 778; i = i + 14 ) {
System.out.print(i + " ");
}
System.out.println();
for (int i = 760 ; i <= 888; i = i + 16 ) {
System.out.print(i + " ");
}
System.out.println();
}
}
However, this code is really long. You can see that I add 80 myself every time. Is there a way I could add another forever loop that does that instead? An adds the 2s as well?
Thanks
Not tested, only using my brain:
for(int i=0;i<input;i++){
int firstNumber = 120+80*i;
for(int j=0;j<=i;j++){
System.out.print(firstNumber+2*i*j); //optimalization firstNumber+(i*j<<1)
}
System.out.println();
}
EDIT input
input variable is count of rows
you can pass the variable as parameter from command line, for example:
public static void main(String[] args){
int input=5; //default value
try{
input=Integer.valueOf(args[0]); //trying to get integer from command line
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("Missing parameter");
}catch(Exception e){
System.out.println("First parameter is not an integer");
}
//input variable is now parameter or 5 by default
for(int i=0;i<=input;i++){
int firstNumber = 120+80*i;
for(int j=0;j<i;j++){
System.out.print(firstNumber+2*i*j);
}
System.out.println();
}
}
EDIT explanation
The first number is variable in first column, if you will count by i variable, you will see this sequence:
120, 200, 280, 360, 340, ...
Which is really the first column.
Then, you should solve next column, as you see, in each row, the difference is +2 in each, and in each column too +2, so 2*i*j solves this
Try to split your problem in separate parts like
print N lines
in each line print M values
Such loop can look more or less like
for (int line = 1 ; line <= N; line++){
for (int position = 1; position <= M; position++){
print(calculateFor(line, position));
}
printLineSeparator;
}
(I started indexing from 1 but you should get used to indexing from 0 so consider rewriting these loops to be in form for (int x = 0; ...) as homework)
Now our problem is calculating proper value based on line number and its position in line.
Lets start from figuring out formula for first value in each line.
We can calculate it easily since it is linear function f(line)=... where we know that
x | 1 | 2 | 3 |
----+-----+-----+-----+ .....
f(x)| 120 | 200 | 280 |
So after applying some math to
{120 = a*1 + b
{200 = a*2 + b
we can figure out that f(line) is 80 * line + 40.
Now we need to figure out formula for rest of elements in line.
This is quite easy since we know that it increases by 2, which means that it is something in form firstValue + 2*(positionInLine -1)
Now last problem is how to decide how many values should be printed in each line?
If you take a closer look you at your data you will see that each line contains same amount of values as line number. So we should continue printing values in line as long position<=line.
So our final solution can look like
for (int line = 1; line <= 9; line++) {
int firstValueInCurrentLine = 80 * line + 40;
for (int position = 1; position <= line; position++) {
System.out.print(firstValueInCurrentLine + 2 * (position -1) + " ");
}
System.out.println();
}
public class Triangle {
public static void main(String [] args) {
int base_int = 40;
for (int row = 1; row < 10; row++) {
for (int col = 0; col < row; col++) {
int result = base_int + (80 * row) + (2 * (row - 1) * col);
System.out.print(result);
System.out.print(" ");
}
System.out.println();
}
}
}
for (int i = 0, m = 120; i < 9; ++i, m += 80) {
for (int j = 0, s = i + i, n = m; j <= i; ++j, n += s)
System.out.print(n + " ");
System.out.println();
}

Categories

Resources