A graphic representation of occurence of numbers and letters with asteriks - java

DISCLAIMER: THIS IS PART OF A HOMEWORK ASSIGNMENT
So i have created an array with the the count of each letter. It would look something like this:
Array charCount
charCount[0] = 10
charCount[1] = 6
charCount[2] = 4
I know that 0 = a, 1 = b etc.
Now I want to print these results to a graphic representation using asteriks. For example:
*
*
*
*
*
**
**
**
***
***
***
ABC
I found this rather difficult and don't really understand how to do this.
- I've made a function to check the max value of my array.
for (int i = 0; i < charCount.length; i++) {
if (letterCount[i] > maxInt) {
maxInt = charCount[i];
}
}
Then I've made a for loop to check if there are any matches.
My next part of code is:
for (int i = 0; i < letterCount.length; i++ ) {
for (int j = 0; j <= maxInt; j++) {
if (letterCount[i] == maxInt) {
System.out.println("*");
} if (letterCount[i] == maxInt - j ) {
System.out.println("*");
} if (letterCount[i] != maxInt ) {
System.out.println(" ");
}
}
But here it where I got stuck.
How do i print asteriks all the way down and next to each other? Should I work with spaces?
How do i know when to stop printing? Does my maxInt - j makes sense?
Can someone point my in the right direction?
I have to come up with a solution using for loops and arrays, So i cant use any fancy methods yet :)
Thank you :)

Imagine you wanna draw this like a bar graph to a grid, which has coordinates, similar to what you did in school with x and y coordinates.
To stay with your example, each y coordinate represents the index of your array, e.g. the specific letter, where the x - coordinate the amount.
Since those numbers may get quite large, it's, like you saw, not best practice to map +1 on the x-coordinate to +1 letter.
Therefore you need to determine the size of your diagram, let's say it shall be 10 letters wide:
y <- 10
^
a|**********
b|**********
c|**********
-------------> x
12345 ...10
Now it's important that the occurences of the letters relative to each other are represented correctly by those *-bars, that means the letter which occurs the most could be shown with a bar exactly as long as you draw the x-coordinate, in this case 10.
Lets use this as an example dataset
0 := 10
1 := 6
2 := 4
3 := 14
If the x-coordinate is 10 * long, the amount from entry 3 (highest in the array) is 14 and needs to be 10 * long. With this information you can calculate the factor by dividing 10(x-length) / 14(biggest amount) ~= 0.71 (the factor)
This factor you apply to all the numbers to get number of stars to draw.
Here as an example in java:
int xLength = 10;
int[] charCount = new int[5];
charCount[0] = 10;
charCount[1] = 4;
charCount[2] = 7;
charCount[3] = 14;
charCount[4] = 1;
// determine the biggest value:
int biggest = 0;
for(int n:charCount) {
if(n>biggest)
biggest = n;
}
System.out.println("Biggest no: " + biggest);
double factor = (double)xLength / (double)biggest;
System.out.println("Using factor: " + factor);
for(int i = 0; i < charCount.length; i++) {
System.out.print("no " + i + ":");
for(int j = 0; j < charCount[i] * factor; j++) {
System.out.print("*");
}
System.out.println();
}
This will output:
Biggest no: 14
Using factor: 0.7142857142857143
no 0:********
no 1:***
no 2:*****
no 3:**********
no 4:*
EDIT:
If you want to print the bars vertically (on the y-choordinate), or turn it any other way, store the bars in a grid, for example with a String[][] array, where arr[2][3] would be y-coordinate 2 and x-coordinate 3. Then you can calculate with the factor above and the maximum height of the chart whether or not a specific point / coordinate should be filled with a "*" or a " " (nothing):
// make a grid to draw the chart
// the height is the the number we defined as maximum height (xLength)
// and the width is one column for every char (charCount.length):
String[][] grid = new String[charCount.length][xLength];
// initialize the grid with spaces:
for(int x = 0; x < grid.length; x++) {
for(int y = 0; y < grid[x].length; y++) {
grid[x][y] = " ";
}
}
// We will go through the grid column by column:
for(int x = 0; x < grid.length; x++) {
// this will be called once for every char
// so just replace spaces in the grid in this column
// by "*" if it's a row (value of y) <= the amount
// of chars times the factor
for(int y = 0; y < grid[x].length; y++) {
if(y <= charCount[x] * factor) {
grid[x][y] = "*";
}
}
}
// print the grid row by row (think of it upside down, (0,0) is the upper left point
// so we start with the last (the no of elements in the array minus 1, counting from 0)
System.out.println("^");
for(int y = grid[0].length - 1; y >= 0; y--) {
System.out.print("|");
for(int x = 0; x < grid.length; x++) {
System.out.print(grid[x][y]);
}
// finish the line:
System.out.println();
}
// draw the bottom line:
System.out.println("------->");
System.out.println(" abcde");
Added this code just below the code from above, the output will be:
Biggest no: 14
Using factor: 0.7142857142857143
no 0:********
no 1:***
no 2:*****
no 3:**********
no 4:*
^
| *
| *
|* *
|* *
|* **
|* **
|* **
|****
|****
|*****
------->
abcde
If you want to put the amounts left to the y-bar, divide the row number by the factor.
If you want to use the absolute values without scaling up or down (which would fill the screen pretty fast for big numbers), just set the 'xLength' (height of the grid) to the biggest number in the input array.

Related

programming puzzle : how to count number of bacteria that are alive?

Recently, I had encountered an interesting programming puzzle which had some good twist and turn mentioned in the puzzle. Below the question which amazed me, I simply eager to know if any relevant solution probably in java is feasible for below scenario.
Problem statement:
There is a grid of dimension m*n, initially, a bacterium is present at the bottom left cell(m-1,0) of the grid with all the other cells empty. After every second, each bacteria in the grid divides itself and increases the bacteria count int the adjacent(horizontal,vertical and diagonal) cells by 1 and dies.
How many bacteria are present at the bottom right cell(m-1,n-1) after n-1 seconds?
I had taken references from
https://www.codechef.com/problems/BGH17
but failed to submit the solution
Below is the image for more insite of problem
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;
public class BacteriaProblem {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Number of Rows: ");
int m = sc.nextInt();
System.out.println("Number of Columns: ");
int n = sc.nextInt();
int[][] input = new int[m][n];
input[m - 1][0] = 1;
Stack<String> stack = new Stack<>();
stack.push(m - 1 + "~" + 0);
reproduce(stack, input, n - 1);
System.out.println("Value at Bottom Right corner after n-1 secs: " + input[m - 1][n - 1]);
}
private static void reproduce(Stack<String> stack, int[][] input, int times) {
//exit condition
if (times < 1) {
return;
}
//bacteria after splitting
List<String> children = new ArrayList<>();
//reproduce all existing bacteria
while (!stack.isEmpty()) {
String[] coordinates = stack.pop().split("~");
int x = Integer.parseInt(coordinates[0]);
int y = Integer.parseInt(coordinates[1]);
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
if (i == 0 && j == 0) continue;
split(input, x + i, y + j, children);
}
}
input[x][y]--;
}
//add all children to stack
for (String coord : children) {
stack.push(coord);
}
//reduce times by 1
reproduce(stack, input, times - 1);
}
private static void split(int[][] input, int x, int y, List<String> children) {
int m = input.length;
int n = input[0].length;
if (x >= 0 && x < m && y >= 0 && y < n) {
input[x][y]++;
children.add(x + "~" + y);
}
}
}
Well, I was asked this question in an Online Hackerrank test and couldn't solve it at that time.
I did later try to code it and here's the soln in C++,
long countBacteriasAtBottomRight(int m, int n){
long grid[m][n];
// Set all to 0, and only bottom left to 1
for (int i=0; i<m; i++){
for (int j=0; j<n; j++){
grid[i][j] = 0;
}
}
grid[m-1][0] = 1;
// Start the cycle, do it for (n-1) times
int time = n-1;
vector<long> toBeUpdated;
while (time--){
cout << "\n\nTime: " << time;
for (int i=0; i<m; i++){
for (int j=0; j<n; j++){
while (grid[i][j] > 0){
grid[i][j]--;
// upper left
if (i > 0 && j > 0){
toBeUpdated.push_back(i-1);
toBeUpdated.push_back(j-1);
}
// upper
if (i > 0){
toBeUpdated.push_back(i-1);
toBeUpdated.push_back(j);
}
// upper right
if (i > 0 && j < n-1){
toBeUpdated.push_back(i-1);
toBeUpdated.push_back(j+1);
}
// left
if (j > 0){
toBeUpdated.push_back(i);
toBeUpdated.push_back(j-1);
}
// bottom left
if (i < m-1 && j > 0){
toBeUpdated.push_back(i+1);
toBeUpdated.push_back(j-1);
}
// bottom
if (i < m-1){
toBeUpdated.push_back(i+1);
toBeUpdated.push_back(j);
}
// bottom right
if (i < m-1 && j < n-1){
toBeUpdated.push_back(i+1);
toBeUpdated.push_back(j+1);
}
// right
if (j < n-1){
toBeUpdated.push_back(i);
toBeUpdated.push_back(j+1);
}
};
}
}
// Update all other cells
for (int k=0; k<toBeUpdated.size(); k+=2){
grid[toBeUpdated[k]][toBeUpdated[k+1]]++;
}
for (int i=0; i<m; i++){
cout << endl;
for (int j=0; j<n; j++)
cout << grid[i][j] << " ";
}
// Clear the temp vector
toBeUpdated.clear();
};
return grid[m-1][n-1];
}
The starting situation only has a value in the left-most column 0. We need to know the situation in the right-most column n-1 after time n-1. This means that we only have to look at each column once: column x at time x. What happens to column x after time x is no longer important. So we go from left to right, adding up the cells from the previous column:
1
1 8
1 7 35
1 6 27 104
1 5 20 70 230
1 4 14 44 133 392
1 3 9 25 69 189 518
1 2 5 12 30 76 196 512
1 1 2 4 9 21 51 127 323 ...
You will also notice that the result for the last cell is only influenced by two cells in the previous column, and three in the one before that, so to calculate the end result for e.g. the case n=9, you only need to calculate the values in this triangle:
1
1 4 14
1 3 9 25 69
1 2 5 12 30 76 196
1 1 2 4 9 21 51 127 323
However high the grid is, we only ever have to go up n/2 (rounded up) rows. So the total number of sums we have to calculate is n2/4, or n×m if m < n/2.
Also note that we don't have to store all these values at once, because we go column by column from left to right. So we only need a one-dimensional array of size n/2, and the current values in it are transformed like this (e.g. going from column 4 to 5 in the example above):
[4, 5, 3, 1] (0) -> 0 + 5 - 0 = 5
[9, 5, 3, 1] (5) -> 9 + 3 - 5 = 7
[9,12, 3, 1] (7) -> 12 + 1 - 7 = 6
[9,12, 9, 1] (6) -> 9 + 0 - 6 = 3
[9,12, 9, 4] (3) -> 4 + 0 - 3 = 1
[9,12, 9, 4, 1] (1) (additional value is always 1)
where we iterate over the values from left to right, add up the value to the left and right of the current element, subtract a temporary variable which is initialized to 0, store the result in a temporary variable, and add it to the current element.
So the theoretical time complexity is O(n2) or O(n.m) and the space complexity is O(n) or O(m), whichever is smaller. In real terms, the number of steps is n2/4 and the required space is n/2.
I don't speak Java, but here's a simple JavaScript code snippet which should easily translate:
function bacteria(m, n) {
var sum = [1];
for (var col = 1; col < n; col++) {
var temp = 0;
var height = Math.min(col + 1, n - col, m);
if (height > sum.length) sum.push(0);
for (var row = 0; row < height; row++) {
var left = row > 0 ? sum[row - 1] : 0;
var right = row < sum.length - 1 ? sum[row + 1] : 0;
temp = left + right - temp;
sum[row] += temp;
}
}
return sum[0];
}
document.write(bacteria(9, 9));

finding the sum of the sreies, using java

the question is to find the sum of this series
series
i used this code to solve it , but im not quite sure the logic is correct.
the noofterms is how many terms are going to be added
and x is the number that will be assigned to the variable.
does the logic seem correct?
public static double sumOfSeries(double x, int noofterms){
double evennumbers=1;
double oddnumbers=1;
double result=1;
// since the power of x starts from 1 , we start i from 1 and increment by 2
for (int i=1; i<noofterms; i+=2 ){
// we reset starting numbers so we start from them everytime
evennumbers = 1;
oddnumbers = 1;
// everytime the number increases by 2 when it is smaller than i+1
// ex when its equal to 2 , j = 3 , j+1 = 4 so it increments by 2
// when its 4 , j = 5 , j+ 1 = 6 , it increments
for (int j=2; j<=i+1; j+=2){
// multiply by increments of 2
evennumbers= evennumbers * j;
}
// it starts from 1 and increments by 2 so it goes like 1,3,5
for (int z=1; z<=i; z+=2){
oddnumbers = oddnumbers * z;
}
result*=((Math.pow(x, (double)i)) / (double)i) + (oddnumbers/evennumbers);
}
return result;
}
You can do it better. Note that numerators and denominators form two sequences, so you can keep previous terms to efficiently make computations, this will look like this :
long even = 1;
long odd = 1;
double result = x;
for(long i = 1; i < noofterms; i++)
{
even *= 2 * i;
odd *= 2 * i - 1;
double oper = Math.pow(x, (double)(2 * i + 1)) / (double)(2 * i + 1);
result += (double)even / (double)odd * oper;
}
You can improve by using logarithms because even and odd will grow very fast and will lead to overflows :
double even = 0.0;
double odd = 0.0;
double result = x;
double logx = Math.log(x);
for(long i = 1; i < noofterms; i++)
{
even += Math.log((double)(2 * i));
odd += Math.log((double)(2 * i - 1));
double oper = logx * (2 * i + 1) - Math.log((double)(2 * i + 1));
result += Math.exp(even - odd + oper);
}
EDIT: only one sequence could also be computed : p *= (double)(2*i)/(2*i-1). Then the log trick is not useful.

pascal triangle starting and ending with 1

Pasted below is a program to print Pascal's triangle. The way to compute any given position's value is to add up the numbers to the position's right and left in the preceding row. For instance, to compute the middle number in the third row, you add 1 and 1. the sides of the triangle are always 1 because you only add the number to the upper left or the upper right (there being no second number on the other side).
int pascal[][]=new int[50][50]; int j;
for(int i=0;i<m;i++)
{
pascal[i][i]=1;
for(j=1;j<i;j++)
{
pascal[i][j]=pascal[i-1][j-1]+pascal[i-1][j];
}
for(int n=1;n<=m-i;n++)
{
System.out.print(" ");
}
for(int k=1;k<=i;k++)
{
System.out.print(pascal[i][k]);
System.out.print(" ");
}
System.out.println(" ");
}
Is there any way to accomplish this without using arrays?
I'm trying this combination without arrays:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
You can easily compute it using Combination.
You can compute combination as:
|n| = (n!) / ((n-k)!*k!)
|k|
So if you want to print the image above you would start as:
int size = 5;
for(int i = 0; i < size; i++){
for(int k = 0; k < (size - i)/2; k++)
System.out.print(" "); // print the intendation
for(int j = 0; j <= i; j++){
System.out.print(combination(i,j));
}
System.out.println("");
}

Dividing a 2D array into boxes

I am having trouble with dividing a 2D array into boxes, like in Sudoku. I have an array of squares in my board object, and I want to divide them into 2x3 or 3x3 boxes, The box objects have a 1D array to keep track of the squares.
k is the box number, in a 9x9 sudoku, the boxes will be numbered 0 through 8.
int l = 0;
for(int i=k*a; i<k*a+a;i++){
for(int j=k*b;j<k*b+b;j++){
narray[l]=brd.getSquare(i,j);
brd.getSquare(i,j).setBox(this);
l++;
}
This gets the first box right, but goes off after that. I've been thinking about this for hours now, and I can't seem to wrap my head around it. Does anyone have a neat trick for this?
So, I'll assume the boxes are numbered like this:
012
345
678
(and the boxes consist of 3x3 cells each)
If i and j are x and y coordinates, you'll need to translate the above to coordinates. Something like:
0 1 2 3 4 5 6 7 8
x 0 1 2 0 1 2 0 1 2
y 0 0 0 1 1 1 2 2 2
So x = k%3 and y = k/3.
In the actual grid x and y has to start from 0, 3 and 6 rather than 0, 1 and 2, so just multiply by 3.
So something like this should do it: (changes depending on which coordinate is x and which is y)
int size = 3;
int l = 0;
for(int i = 0; i < size; i++){
for(int j = 0; j < size; j++){
int x = i + k % size * size;
int y = j + k / size * size;
narray[l] = brd.getSquare(x, y);
brd.getSquare(x, y).setBox(this);
l++;
}
}
If you want to use a single number to index a 2D array, use the mod / divide functions.
row = index / row_size;
col = index % col_size;
Your index should be in the range 0 to (row_size*col_size -1)
So it sounds like you just want to get the box row and box column.
int boxsize = 3;
int h = 9; //height
inh w = 9; //width
for (int r =0;r<h;r++){
for (int c=0;c<w;c++){
int br = r/boxsize;
int bc = c/boxsize;
int index = br*h + c;
narray[index]=brd.getSquare(br,bc);
System.out.println("box row =" + br +" box column =" + bc);
}
}

Printing a sideways triangle in java

I'm trying to print a sideways triangle in java. If the user enters 5, the output should be:
*
***
*****
***
*
If the user enters 6, the output should be:
*
***
*****
*****
***
*
I've gotten it to work for the case when the user enters 5, 3, or 1 but my code seems to work for those three cases only. I was wondering if anyone could help me get my code working for more cases.
Here it is:
public void printArrow( int n )
{ int asterisks = 1;
for ( int i = 0; i <= n/2; i++ )
{
for ( int j = i; j < asterisks; j++ )
{
System.out.print( "*" );
}
asterisks += 3;
System.out.println();
}
asterisks = asterisks / 2 - 2;
for ( int i = 0; i < n/2; i++ )
{
for ( int k = i; k < asterisks; k++ )
{
System.out.print( "*" );
}
if ( i == 1 )
{
System.out.print( "*" );
}
asterisks -= 2;
System.out.println();
}
}
It's much easier to solve this using recursion:
static String triangle(int n, String s) {
return
n == 0 ? "" :
n == 1 ? s :
s
+
triangle(n - 2, "**" + s)
+
s
;
}
public static void main(String args[]) {
System.out.println(triangle(6, "*\n"));
}
The structure of the triangle is self-evident:
n == 0? No line!
n == 1? One line!
Otherwise? Two lines sandwiching n - 2 lines! (which are longer!)
Alright Will I'll bite
So the goal is to print out a triangle of stars. Well we are going to need a loop of some kind, probably with another internal loop. And we know that it's going to be symmetric as it's a triangle.
so I'd start with printing the fist half:
function triangle( input )
i <- 1
while i < input do
for j from 1 to i do
print "*"
end for
i <- i + 2
print "\n"
end while
After that we'd need to deal with the second half of the triangle which, because we have already walked i up to the input value means we can just walk it back down.
if i > input then i <- i - 2
while i > 0 do
for j from 1 to i do
print "*"
end for
i <- i - 2
print "\n"
end while
end function triangle
the little trick in it that almost caught me is the subtraction of two before the second while, if you don't do this you'll get the wrong answer. I'll leave figuring out why up to you. If there is confusing in the pseudocode notation please ask.
double middle = ((double) lines) / 2;
int asterisks = 1;
for (int i = 1; i <= lines; i ++){
for (int k = 0; k < asterisks; k ++) {
System.out.print("*");
}
if (i < middle) {
asterisks += 2;
} else if (i > middle){
asterisks -= 2;
}
System.out.println();
}
Explaining:
lines is the input number (3,4,5,6,7, etc)
get the middle row as a double. I.e. for odd numbers it will be x.5
the loop is for as many lines as the input is
on each line print as many asterisk as there are in the asterisks variable
on each iteration either increase the number of asterisk by 2, if the line is before the middle, or decrease it, if after. This means that if it is equal, nothing happens - i.e. the same row has the same number of asterisk. And it can't be equal for odd numbers.

Categories

Resources