Creating an array that works like a torus - java

I have create a program that takes a random array which is created by starting from 0 and adding Math.random() (double between 0 and 0.999) n times, and calculates the weighted average of each position within a certain radius. I currently have a program that does this but i was wondering how to create one using a torus. The basic principle is the last element is now equal to the first element and when the first element updates its position it takes into account the difference between the other elements including some of the last elements in the array.
Any help on the matter would be much appreciated. Its not help with the coding but with the principle behind it, I cant work out how this would be possible for multiple iterations.
heres the code so far that works for one iteration. After one the code is incorrect and calculates the wrong values.
import java.text.DecimalFormat;
import java.util.Scanner;
/**
* Created by jameshales on 12/03/2014.
*/
public class Torus {
public static void main(String[] args) {
DecimalFormat df = new DecimalFormat("#.###"); // this sets all decimals to a max of 3 decimal places.
System.out.println("how many numbers of agents on the real line?"); // This asks the question "how many numbers on the real line?" to the user.
Scanner input = new Scanner(System.in);
int n = 0;
n=Integer.parseInt(input.nextLine()); // the scanner reads the input and assigns it to the variable n
double[] agentPosition = new double[n]; // create an array with decimal places allowed called agentPosition
double[] newAgentPosition = new double[n]; // create an array with decimal places allowed called newAgentPosition
double[] originalAgentPosition = new double[n]; // create an array with decimal places allowed called originalAgentPosition
System.out.println("Please select your desired radius? select 1 normally"); // This asks the question "Please select your desired radius?
double r = 0;
r = input.nextDouble(); // the scanner reads the next input and assigns it to the variable r
int t = 0; // sets t to 0
double epsilon = 0.001; // this allows us to sets epsilon to 0.
// start the array from position 0 with its value set to 0
for (int i = 0; i <= n - 1; i++) { // starting from position 1 it creates a random number between 0 and 0.999 and adds it to the previous agentPosition to fill the array in a random increasing way.
if (i > 0)
agentPosition[i] = agentPosition[i - 1] + Math.random(); // this equation creates the random array
else agentPosition[i] =0.0;
}
System.arraycopy(agentPosition,0,originalAgentPosition,0,n);
// This takes the first randomly created array(agentPosition), copyies each element starting from 0 to n and calls it originalAgentPosition.
while(true) { // This is the start of the while loop, this will keep running until false
for (int i = 0; i <= n - 1; i++) {
// this will go through the array 1 position at a time in an increasing order from position 0 to n-1
double total1 = agentPosition[i]; // sets the initial value of total1 to 0
double total2 = 0; // sets the initial value of total2 to 0
int numposition = 1; // this starts at 1 so it includes the position in the array when dividing.(also stops dividing by 1)
for (int j = i - 1; j >= 0; j--) { // this will work from the initial value of the array to the one before the one selected.
if ((agentPosition[i] - agentPosition[j]) <= r) { // this calculates the absolute value of the difference between 2 positions on the array. (from i working downwards)
numposition++; // this sums the number of positions within the radius of the chosen position.
total1 += agentPosition[j]; // this sums up all the values within the radius below to the total1.
} else break; // stops the program once it has passed a position of a distance of 1
}
for (int k = i + 1; k <= n - 1 ; k++) { // this will go from the one after the position selected to the last position in the array to test if the distance is greater than 1, stops otherwise..
if (Math.abs(agentPosition[k] - agentPosition[i]) <= r) { // this calculates the absolute value of the difference between 2 positions on the array(i and positions greater).
numposition++; // this sums the number of positions within the radius of the chosen position.
total2 += agentPosition[k]; // this sums up all the values within the radius above to the total1.
} else break; // stops the program once it has passed a position of a distance of 1
}
for (int j = n - 2; j >= 1; j--) { // this will work from the initial value of the array to the one before the one selected.
if (((agentPosition[n-1] + agentPosition[i]) - agentPosition[j]) <= r) { // this calculates the absolute value of the difference between 2 positions on the array. (from i working downwards)
numposition++;
total1 += (agentPosition[j] - agentPosition[n - 1]); // this sums up all the values within the radius below to the total1.
} else break;// stops the program once it has passed a position of a distance of 1
}
for (int k = 1; k <= n - 2 ; k++) { // this will go from the one after the position selected to the last position in the array to test if the distance is greater than 1, stops otherwise..
if (Math.abs((agentPosition[i] - agentPosition[n - 1]) - agentPosition[k]) <= r) { // this calculates the absolute value of the difference between 2 positions on the array(i and positions greater).
numposition++; // this sums the number of positions within the radius of the chosen position.
total2 += (agentPosition[n - 1] + agentPosition[k]); // this sums up all the values within the radius above to the total1.
} else break;// stops the program once it has passed a position of a distance of 1
}
newAgentPosition[i] = (total1 + total2) / numposition; // this calculates the new weighted average. ( sum of assigned random variable/ sum of position)
}
for (int i = 0; i <= n - 1; i++){
if (newAgentPosition[i] > originalAgentPosition[n - 1]){
newAgentPosition[i] = newAgentPosition[i] - originalAgentPosition[n - 1];
}
if(newAgentPosition[i] < 0) { // This checks if the agentPosition is smaller than 0 and then adds the largest agent to make all the elements within the range.
newAgentPosition[i] = newAgentPosition[i] + originalAgentPosition[n - 1];
}
}
t++; // This sums up how many iterations it will take.
double largestDiff = 0.0; // This assigns largestDiff to 0
for (int i = 0; i <= n-1; i++) {
double diff = Math.abs(agentPosition[i] - newAgentPosition[i]); // This calculates the difference between the previous and current array at position i.
if(diff > largestDiff) // If the difference between the agents is bigger than 0, assign it to the variable largestDiff.
largestDiff = diff;
}
if(largestDiff <= epsilon){ // This checks if the difference is bigger than the set epsilon,
break; // This stops the program if the difference is smaller than epsilon
}
agentPosition = new double[n];
System.arraycopy(newAgentPosition, 0, agentPosition, 0, n); // This takes the newly generated array(newAgentPosition), copyies each element starting from 0 to n and assigns it back to agentPosition. (this stops the problem j and with taking the newly created elements.)
}
for (int i = 0 ; i <= n - 1; i++) { // starting from position 1 it creates a random number between 0 and 0.999 and adds it to the previous agentPosition to fill the array in a random increasing way.
System.out.println(i + ": " + df.format(originalAgentPosition[i]) + "\t->\t" + df.format(agentPosition[i]));
}
int sumdofclusters = 1; // This sets the sum of clusters to 1
System.out.println("The different clusters are:\n" + df.format(agentPosition[0])); // This prints out the first cluster only.
for (int i = 1; i <= n - 1 ; i++) {
if(Math.abs(agentPosition[i] - agentPosition[i - 1]) >= epsilon) { // This checks if the element after the element at hand is different by a set epsilon.(how to work out different clusters)
sumdofclusters++; // This sums the number of clusters.
System.out.println(df.format(agentPosition[i])); // This prints out the different clusters other than the first 1.
}
}
System.out.println("Number of clusters is:" + sumdofclusters); // This prints out the number of clusters.
System.out.println("Number of iterations:" + t); // This prints out the number of iterations.
}
}

You can create a circular list using an array with modulus division.
getElementAt(double[] arr, int index)
{
index = index % arr.length;
index = index + arr.length; // If index is negative, modulus division gives us negative result, so this makes it positive.
index = index % arr.length; // In case the previous step made index >= n
return arr[index]
}
If n is arr.length then
0 <= index < n will be like normal.
n <= index will wrap around the list (e.g. arr[n] == arr[0], arr[n+1] == arr[1], etc.)
index < 0 will wrap around the list in the other direction (e.g. arr[-1] == arr[n-1], arr[-2] == arr[n-2], etc.)

Related

Why is my arr.length not consistently printing out values and instead always printing out "0"?

From my research, my first error was populating the array in the switch case. I fixed it so it is populated outside. I did a few tests and arr.length will give me the output of 1000 as expected, but it should be 500 (if I put 500 as the upperbound, how would I make values between 1-1000?). Case 5 works for some reason which uses arr.length as well.
I want to have 500 integers between the value of 1-1000 print out various outcomes. There are no errors in the code. All cases except case 2 & 7 work.
import java.util.Scanner;
import java.util.Random;
class ArrayMenu {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("Pick an option 1-7, 0 to exit");
byte menu;
Random num = new Random();
int[] arr = new int[1000];
for (int i = 0; i <= 500; i++) {
arr[i] = num.nextInt(500);
}
do {
menu = scan.nextByte();
switch (menu) {
case 1:
for (int i = 0; i <= 500; i++) {
System.out.println(arr[i]);
}
break;
case 2:
int mean = 0;
for (int i = 0; i <= 500; i++) {
int sum = 0;
int z = arr[i];
sum = sum + z;
mean = sum / arr.length;
}
System.out.println("The mean is " + mean);
break;
case 3:
for (int i = 0; i <= 500; i++) {
int y = arr[i];
if (y % 2 != 0) System.out.println(arr[i]);
}
break;
case 4:
for (int i = 0; i <= 500; i++) {
int x = arr[i];
if (x % 2 == 0) System.out.println(arr[i]);
}
break;
case 5:
System.out.println("Median is " + arr[arr.length / 2]);
break;
case 6:
System.out.println("First is " + arr[0]);
break;
case 7:
System.out.println("Last is " + arr[arr.length - 1]);
System.out.println(arr.length);
break;
}
} while (menu != 0);
scan.close();
}
}
Bonus question: how would I randomly fill with negative values instead of only positive?
This is your code right now:
case 2:
int mean = 0;
for (int i = 0; i <= 500; i++) {
int sum = 0;
int z = arr[i];
sum = sum + z;
mean = sum / arr.length;
}
System.out.println("The mean is " + mean);
break;
However, there are a couple of mistakes here. First of all, the mean could be a decimal, so you should declare it as a double, not an int. Also, there's no need to assign it in the loop; you can just assign it once after the loop. You're also redeclaring sum every loop, which means the sum never gets incremented. Here's the fixed code:
case 2:
double mean;
int sum = 0;
for (int i = 0; i <= 500; i++) {
sum = sum + arr[i];
}
mean = (double) sum / arr.length;
System.out.println("The mean is " + mean);
break;
Also, for this line:
int[] arr = new int[1000];
You allocate an array of 1000 elements, but only fill from 0 to 500 inclusive (which is 501 elements). If you want arr.length to work properly, only allocate what you need:
int[] arr = new int[501];
If you don't want to manually allocate, then use ArrayLists instead.
If you want a negative number between -500 and 500, then generate one between 0 and 1000 then subtract 500:
rand.nextInt(1000) - 500
Note that case 5 also doesn't work. The mean is not defined as 'the middle in a random assortment', there is nothing special about the 500th element. It's defined as: "Once you've sorted it all, the middle element". You aren't sorting anything.
Without resorting to calling Arrays.sort (I don't know if your homework assignment allows you to do this), case 5 is in fact the one that's the most complicated to write.
Furthermore, you have an array of 1000 slots (so, array.length is 1000), and you wrote a bunch of code that assumes 1000 is in fact how large your array actually is - such as your 'print the last' code returning the [999] element. However, at the start, you only fill the first 500 with random numbers, the remaining 500 remain unfilled, which means they retain their initial value, which is 0.
Thus, we get to:
All cases except case 2 & 7 work.
No, they don't.
Programming is really, really hard. Before concluding that your stuff works just because it compiled and it ran, check that the outputs you see actually make sense.
for (int i = 0; i <= 500; i++) {
arr[i] = num.nextInt(500);
}```
The first use of '500' is how many times you want to loop. If you want to fill the whole array, use 1000 there. The second use of 500 decides from amongst how many numbers you want to pick random numbers. 500 means that you get any number, from as low as 0 to as large as 499 (which is a total span of 500 numbers).
You've used <= and that's the mistake; use <. An array of size 1000 has valid indices [0] all the way up to and including [999], but not [1000]. Think about it: if 0 is the first element, then 999 is the 1000th element, and [1000] would be the 1001st element, which isn't there. Thus:
for (int i = 0; i < 1000; i++) {
arr[i] = num.nextInt(500);
// or if you want uniform from -500 to 500 all inclusive:
arr[i] = num.nextInt(1001) - 500;
}
why 1001? Because that's how many different numbers you can generate: 500 negative numbers, 500 positive numbers.. and 0. 1001. (That goes some way into showing you why java is 0-based, the math tends to be less weird that way).

Maximum height of the staircase

Given an integer A representing the square blocks. The height of each square block is 1. The task is to create a staircase of max height using these blocks. The first stair would require only one block, the second stair would require two blocks and so on. Find and return the maximum height of the staircase.
Your submission failed for the following input: A : 92761
Your function returned the following : 65536
The expected returned value : 430
Approach:
We are interested in the number of steps and we know that each step Si uses exactly Bi number of bricks. We can represent this problem as an equation:
n * (n + 1) / 2 = T (For Natural number series starting from 1, 2, 3, 4, 5 …)
n * (n + 1) = 2 * T
n-1 will represent our final solution because our series in problem starts from 2, 3, 4, 5…
Now, we just have to solve this equation and for that we can exploit binary search to find the solution to this equation. Lower and Higher bounds of binary search are 1 and T.
CODE
public int solve(int A) {
int l=1,h=A,T=2*A;
while(l<=h)
{
int mid=l+(h-l)/2;
if((mid*(mid+1))==T)
return mid;
if((mid*(mid+1))>T && (mid!=0 && (mid*(mid-1))<=T) )
return mid-1;
if((mid*(mid+1))>T)
h=mid-1;
else
l=mid+1;
}
return 0;
}
To expand on the comment by Matt Timmermans:
You know that for n steps, you need (n * (n + 1))/2 blocks. You want know, if given B blocks, how many steps you can create.
So you have:
(n * (n + 1))/2 = B
(n^2 + n)/2 = B
n^2 + n = 2B
n^2 + n - 2B = 0
That looks suspiciously like something for which you'd use the quadratic formula.
In this case, a=1, b=1, and c=(-2B). Plugging the numbers into the formula:
n = ((-b) + sqrt(b^2 - 4*a*c))/(2*a)
= (-1 + sqrt(1 - 4*1*(-2B)))/(2*a)
= (-1 + sqrt(1 + 8B))/2
= (sqrt(1 + 8B) - 1)/2
So if you have 5050 blocks, you get:
n = (sqrt(1 + 40400) - 1)/2
= (sqrt(40401) - 1)/2
= (201 - 1)/2
= 100
Try it with the quadratic formula calculator. Use 1 for the value of a and b, and replace c with negative two times the number of blocks you're given. So in the example above, c would be -10100.
In your program, since you can't have a partial step, you'd want to truncate the result.
Why are you using all these formulas? A simple while() loop should do the trick, eventually, it's just a simple Gaussian Sum ..
public static int calculateStairs(int blocks) {
int lastHeight = 0;
int sum = 0;
int currentHeight = 0; //number of bricks / level
while (sum <= blocks) {
lastHeight = currentHeight;
currentHeight++;
sum += currentHeight;
}
return lastHeight;
}
So this should do the job as it also returns the expected value. Correct me if im wrong.
public int solve(int blocks) {
int current; //Create Variables
for (int x = 0; x < Integer.MAX_VALUE; x++) { //Increment until return
current = 0; //Set current to 0
//Implementation of the Gauss sum
for (int i = 1; i <= x; i++) { //Sum up [1,*current height*]
current += i;
} //Now we have the amount of blocks required for the current height
//Now we check if the amount of blocks is bigger than
// the wanted amount, and if so we return the last one
if (current > blocks) {
return x - 1;
}
}
return current;
}

For loop troubling for printing multiple values

So the question is:
Write a program that reads a sequence of input values and displays a bar chart of the values using asterisks. You may assume that all values are positive. First figure out the maximum value. That value’s bar should be drawn with 40 asterisks. Shorter bars should use proportionally fewer asterisks.
eg.
***********************
*********
****************************************
****
*******************
This is my code below:
int count = 0;
//Finds largest Value
int largestValue = numbersArray[0];
for (int i = 1; i < numbersArray.length; i++) {
if (numbersArray[i] > largestValue) {
largestValue = numbersArray[i];
count++;
}
}
//Prints number of asterisks
final int MAX = 40;
String asterisks = "****************************************";
for (int i = 0; i < count + 2; i++) {
System.out.print(numbersArray[i]);
if (numbersArray[i] == largestValue) {
System.out.print(asterisks);
} //if (numbersArray[i] != largestValue) {
else {
for (int j = 0; j < (40 * numbersArray[i] / largestValue); j++) {
System.out.print("*");
}
}
System.out.println();
}
This code doesn't seem to run properly.
If I enter values in the order: 5 8 6 4 7, it will just print the stars for 5 and 8, and not the rest. Basically it prints stars for values till the largest number.
I can't find what's wrong with my code. Any help would be greatly appreciated!
Thanks for reading <3
First of all, you don't need to count variable - it does nothing helpful to you and you for some reason limit yourself (you increment everytime you find a larger element so you only increment once since there's nothing larger than 8).
What you should be doing is finding the largest value, as you did, and then running over the entire array and displaying each element proportional to that value, as you did (but without the special case for the actual largest value - that is atrocious).
Also, you should note that division of two integers would result in an integer, which is not what you want, so you'll have to cast one of them to float or double.
//finds largest Value
int largestValue = numbersArray[0];
for (int i = 1; i < numbersArray.length; i++) {
if (numbersArray[i] > largestValue) {
largestValue = numbersArray[i];
}
}
//Prints number of asterisks
final int MAX = 40;
for (int i = 0; i < numbersArray.length; i++) {
int portion = (int)(MAX * (numbersArray[i] / (float)largestValue));
for (int j = 0; j < portion; j++) {
System.out.print("*");
}
System.out.println();
}
So you'll find the largest value is 8.
Then for 5, you'll do 5/8 which is 0.625 and times MAX (40) that would be 25, so you'll print 25 *.
Then for 8 - 8/8 = 1.0 * MAX = 40 so you'll print the whole 40 *.
For 6 - 6/8 = 0.75 * MAX = 30 so you'll print 30 * and so on.
Note that if you want to fine-tune it, you could use Math.round instead of simply casting the portion to int (which simply truncates the floating point).

Java Biasing Random Numbers in a Triangular Array

This question is an extension of Java- Math.random(): Selecting an element of a 13 by 13 triangular array. I am selecting two numbers at random (0-12 inclusive) and I wanted the values to be equal.
But now, since this is a multiplication game, I want a way to bias the results so certain combinations come up more frequently (like if the Player does worse for 12x8, I want it to come up more frequently). Eventually, I would like to bias towards any of the 91 combinations, but once I get this down, that should not be hard.
My Thoughts: Add some int n to the triangular number and Random.nextInt(91 + n) to bias the results toward a combination.
private int[] triLessThan(int x, int[] bias) { // I'm thinking a 91 element array, 0 for no bias, positive for bias towards
int i = 0;
int last = 0;
while (true) {
int sum = 0;
for (int a = 0; a < i * (i + 2)/2; a++){
sum += bias[a]
}
int triangle = i * (i + 1) / 2;
if (triangle + sum > x){
int[] toReturn = {last,i};
return toReturn;
}
last = triangle;
i++;
}
}
At the random number roll:
int sum = sumOfArray(bias); // bias is the array;
int roll = random.nextInt(91 + sum);
int[] triNum = triLessThan(roll);
int num1 = triNum[1];
int num2 = roll - triNum[0]; //now split into parts and make bias[] add chances to one number.
where sumOfArray just finds the sum (that formula is easy). Will this work?
Edit: Using Floris's idea:
At random number roll:
int[] bias = {1,1,1,...,1,1,1} // 91 elements
int roll = random.nextInt(sumOfBias());
int num1 = roll;
int num2 = 0;
while (roll > 0){
roll -= bias[num2];
num2++;
}
num1 = (int) (Math.sqrt(8 * num2 + 1) - 1)/2;
num2 -= num1 * (num1 + 1) / 2;
You already know how to convert a number between 0 and 91 and turn it into a roll (from the answer to your previous question). I would suggest that you create an array of N elements, where N >> 91. Fill the first 91 elements with 0...90, and set a counter A to 91. Now choose a number between 0 and A, pick the corresponding element from the array, and convert to a multiplication problem. If the answer is wrong, append the number of the problem to the end of the array, and increment A by one.
This will create an array in which the frequencies of sampling will represent the number of times a problem was solved incorrectly - but it doesn't ever lower the frequency again if the problem is solved correctly the next time it is asked.
An alternative and better solution, and one that is a little closer to yours (but distinct) creates an array of 91 frequencies - each initially set to 1 - and keeps track of the sum (initially 91). But now, when you choose a random number (between 0 and sum) you traverse the array until the cumulative sum is greater then your random number - the number of the bin is the roll you choose, and you convert that with the formula derived earlier. If the answer is wrong you increment the bin and update the sum; if it is right, you decrement the sum but never to a value less than one, and update the sum. Repeat.
This should give you exactly what you are asking: given an array of 91 numbers ("bins"), randomly select a bin in such a way that the probability of that bin is proportional to the value in it. Return the index of the bin (which can be turned into the combination of numbers using the method you had before). This function is called with the bin (frequency) array as the first parameter, and the cumulative sum as the second. You look up where the cumulative sum of the first n elements first exceeds a random number scaled by the sum of the frequencies:
private int chooseBin(float[] freq, float fsum) {
// given an array of frequencies (probabilities) freq
// and the sum of this array, fsum
// choose a random number between 0 and 90
// such that if this function is called many times
// the frequency with which each value is observed converges
// on the frequencies in freq
float x, cs=0; // x stores random value, cs is cumulative sum
int ii=-1; // variable that increments until random value is found
x = Math.rand();
while(cs < x*fsum && ii<90) {
// increment cumulative sum until it's bigger than fraction x of sum
ii++;
cs += freq[ii];
}
return ii;
}
I confirmed that it gives me a histogram (blue bars) that looks exactly like the probability distribution that I fed it (red line):
(note - this was plotted with matlab so X goes from 1 to 91, not from 0 to 90).
Here is another idea (this is not really answering the question, but it's potentially even more interesting):
You can skew your probability of choosing a particular problem by sampling something other than a uniform distribution. For example, the square of a uniformly sampled random variate will favor smaller numbers. This gives us an interesting possibility:
First, shuffle your 91 numbers into a random order
Next, pick a number from a non-uniform distribution (one that favors smaller numbers). Since the numbers were randomly shuffled, they are in fact equally likely to be chosen. But now here's the trick: if the problem (represented by the number picked) is solved correctly, you move the problem number "to the top of the stack", where it is least likely to be chosen again. If the player gets it wrong, it is moved to the bottom of the stack, where it is most likely to be chosen again. Over time, difficult problems move to the bottom of the stack.
You can create random distributions with different degrees of skew using a variation of
roll = (int)(91*(asin(Math.rand()*a)/asin(a)))
As you make a closer to 1, the function tends to favor lower numbers with almost zero probability of higher numbers:
I believe the following code sections do what I described:
private int[] chooseProblem(float bias, int[] currentShuffle) {
// if bias == 0, we choose from uniform distribution
// for 0 < bias <= 1, we choose from increasingly biased distribution
// for bias > 1, we choose from uniform distribution
// array currentShuffle contains the numbers 0..90, initially in shuffled order
// when a problem is solved correctly it is moved to the top of the pile
// when it is wrong, it is moved to the bottom.
// return value contains number1, number2, and the current position of the problem in the list
int problem, problemIndex;
if(bias < 0 || bias > 1) bias = 0;
if(bias == 0) {
problem = random.nextInt(91);
problemIndex = problem;
}
else {
float x = asin(Math.random()*bias)/asin(bias);
problemIndex = Math.floor(91*x);
problem = currentShuffle[problemIndex];
}
// now convert "problem number" into two numbers:
int first, last;
first = (int)((Math.sqrt(8*problem + 1)-1)/2);
last = problem - first * (first+1) / 2;
// and return the result:
return {first, last, problemIndex};
}
private void shuffleProblems(int[] currentShuffle, int upDown) {
// when upDown==0, return a randomly shuffled array
// when upDown < 0, (wrong answer) move element[-upDown] to zero
// when upDown > 0, (correct answer) move element[upDown] to last position
// note - if problem 0 is answered incorrectly, don't call this routine!
int ii, temp, swap;
if(upDown == 0) {
// first an ordered list:
for(ii=0;ii<91;ii++) {
currentShuffle[ii]=ii;
}
// now shuffle it:
for(ii=0;ii<91;ii++) {
temp = currentShuffle[ii];
swap = ii + random.nextInt(91-ii);
currentShuffle[ii]=currentShuffle[swap];
currentShuffle[swap]=temp;
}
return;
}
if(upDown < 0) {
temp = currentShuffle[-upDown];
for(ii = -upDown; ii>0; ii--) {
currentShuffle[ii]=currentShuffle[ii-1];
}
currentShuffle[0] = temp;
}
else {
temp = currentShuffle[upDown];
for(ii = upDown; ii<90; ii++) {
currentShuffle[ii]=currentShuffle[ii+1];
}
currentShuffle[90] = temp;
}
return;
}
// main problem posing loop:
int[] currentShuffle = new int[91];
int[] newProblem;
int keepGoing = 1;
// initial shuffle:
shuffleProblems( currentShuffle, 0); // initial shuffle
while(keepGoing) {
newProblem = chooseProblem(bias, currentShuffle);
// pose the problem, get the answer
if(wrong) {
if(newProblem > 0) shuffleProblems( currentShuffle, -newProblem[2]);
}
else shuffleProblems( currentShuffle, newProblem[2]);
// decide if you keep going...
}

pascal triangle proper formatting java

so I'm currently working on an assignment that I just can't seem to finish. Well I have everything finished but would like the extra credit. I've been looking around the web and can't really seem to find exactly what I'm looking for.
public class PascalTester
{
public static void main(String[] args)
{
Scanner kb = new Scanner(System.in);
System.out.println("Welcome to the Pascal's Triangle program!");
System.out.println("Please enter the size of the triangle you want");
int size = kb.nextInt();
int[][] myArray = new int[size][size];
myArray = fillArray(myArray);
//myArray = calculateArray(myArray);
printArray(myArray); //prints the array
}
private static int[][] fillArray(int[][] array)
{
array[0][1] = 1;
for (int i = 1; i < array.length; i++)
{
for (int j = 1; j < array[i].length; j++)
{
array[i][j] = array[i-1][j-1] + array[i-1][j];
}
}
return array;
}
private static void printArray(int[][] array)
{
for (int i = 0; i < array.length; i++)
{
for (int j = 0; j < array[i].length; j++)
{
if(array[i][j] != 0)
System.out.print(array[i][j] + " ");
}
System.out.println();
}
}
}
The only issue that I'm having now is to properly format the output to look like an actual triangle. Any suggestions would be very helpful at this point in time. Thanks in advance
One approach to this, is, assuming you have all numbers formatted to the same width, is to treat the problem as that of centering the lines.
Java Coding left as exercise to reader but essentially:
for lineText : triange lines
leadingSpacesCount = (80/2) - lineText.length();
print " " x leadingSpacesCount + lineText
Try to use the technique at http://www.kodejava.org/examples/16.html to make an array with array.length - i - 1 spaces (need to add the number spaces between numbers.. and 2 number of 2 digit numbers if any..).
Print this array at the start of the outer for loop.
The challenge here is that you want to start printing at the top of the triangle, but you don't know where to center each row until you get to the last (and widest) row of the triangle. The trick is to not print anything until you know how wide the last row is. One way to do this is to generate all the rows as String (or StringBuilder) objects and compute the maximum width. Then, from the top, center each line by first printing an appropriate number of spaces. The correct number of spaces will be
(maxLineLength - currentLine.length()) / 2
Alternatively, you can simply assume a maximum line length and center all lines in that width. If the longer lines exceed the maximum width, then the triangle will be distorted below a certain row. (Just be sure to not try printing a negative number of spaces!)
If anyone is looking for the actual code to do this take a look at my implementation in Java, it's similar to what Craig Taylor mentioned (numbers formatted to the same width) plus it uses an algorithm to compute the elements without memory (or factorials).
The code has comments explaining each step (calculation and printing):
/**
* This method will print the first # levels of the Pascal's triangle. It
* uses the method described in:
*
* https://en.wikipedia.org/wiki/Pascal%27s_triangle#Calculating_a_row_or_diagonal_by_itself
*
* It basically computes the Combinations of the current row and col
* multiplied by the previous one (which will always be 1 at the beginning
* of each pascal triangle row). It will print each tree element to the output
* stream, aligning the numbers with spaces to form a perfect triangle.
*
* #param num
* # of levels to print
*/
public static void printPascalTriangle(int num) {
// Create a pad (# of spaces) to display between numbers to keep things
// in order. This should be bigger than the # of digits of the highest
// expected number and it should be an odd number (to have the same
// number of spaces to the left and to the right between numbers)
int pad = 7;
// Calculate the # of spaces to the left of each number plus itself
// (this is the width of the steps of the triangle)
int stepsWidth = pad / 2 + 1;
// Now calculate the maximum # of spaces from the left side of the
// screen to the first triangle's level (we will have num-1 steps in the
// triangle)
int spaces = (num - 1) * stepsWidth;
for (int n = 0; n < num; n++) {
// Print the left spaces of the current level, deduct the size of a
// number in each row
if (spaces > 0) {
System.out.printf("%" + spaces + "s", "");
spaces -= stepsWidth;
}
// This will represent the previous combination C(n k-1)
int prevCombination = 1;
for (int k = 1; k <= n + 1; k++) {
System.out.print(prevCombination);
// Calculate how many digits this number has and deduct that to
// the pad between numbers to keep everything aligned
int digits = (int) Math.log10(prevCombination);
if (digits < pad) {
System.out.printf("%" + (pad - digits) + "s", "");
}
// Formula from Wikipedia (we can remove that "+1" if we start
// the row loop at n=1)
prevCombination = prevCombination * (n + 1 - k) / k;
}
// Row separator
System.out.println();
}
}
Hope it helps someone!

Categories