I need help, I am trying to make use of Lattice Multiplication in java for use in a BigInt class I am having to write for a class.
Right now I have the code storing the digits needed for the adding part of the algorithm in a 2 dimensional array. From there though I am at a lose as to how to make a loop to go through the array and add the numbers in what would be a diagonal.
For instance here is the test numbers etc:
200
*311
= 62200
The array is holding:
6 0 0
2 0 0
2 0 0
6 is (2,2) in the array and the bottom right is (0,0)
I need to add in a diagonal, such as (1,0) + (0,1) = 0
The issue is how do I do this, since not only is it moving up and left in different ways, but it goes from 1 element to 2 elements to 3 elements, then back the other way, and of course this will get bigger the longer the number is.
This is the code that I have:
public int multiply(BigInt val){
int[] bigger;
int[] smaller;
int[] dStore;
int lengthMax = (val.getSize()+this.getSize()) - 1;
int first = 0;
int second = 0;
int[][] tempResult;
//Checks to see which is bigger and then adds that to bigger
if(val.getSize() >= this.getSize()){
bigger = val.getData();
smaller = this.getData();
dStore = new int[val.getSize()+this.getSize()];
}else{
bigger = this.getData();
smaller = val.getData();
dStore = new int[val.getSize()+this.getSize()];
}
tempResult = new int[smaller.length][bigger.length];
for(int i=0;i < smaller.length;i++){
for(int j = 0;j < bigger.length;j++){
tempResult[i][j] = smaller[i] * bigger[j];
}
}
** there is the return statement etc below
This might help as to explain lattice multi better: Lattice Multi Video
I would try a different approach. Look at the lattice in the video and imagine that you rotates the array a little bit to the left so that the diagonals becomes vertical. The array would then look like this:
2 3 5
8 3
2 4 0
Now, just summarize the columns and you would have the total.
You would of course have to split the numbers into arrays of digits first. The easiest way to do that (but not the most efficient) is to convert them into strings ...
Good luck!
To move diagonally, you'd increment both x and y:
// Loop though the diagonal of an array
x = 0;
y = 0;
while (x < ARR_X_SIZE && y < ARR_Y_SIZE) {
// Do something with arr[x][y]
x++;
y++;
}
This is the basic loop; you can change the x and y increments to determine the direction you need to go. The key to going through the whole array is the value of the coordinates going into the loop. Array:
1 2 3
4 5 6
7 8 9
If you set x = 1; y=0 at the beginning of the loop, you'll get 2 6. Set x = 0, y = 1 and you'll get 4 8.
I hope this helps you with your assignment. Good luck on the rest! That is definately an interesting algorithm to implement.
Related
So I have a really basic coding question, I just started learning this year, and I have an assignment for a code that is supposed to
flip a fair coin n times and count how many heads it gets. The program will do m experiments and then
print out the results as a (vertical) histogram. The program will first ask the user to input the number of
experiments to perform (m) and the number of coin flips in each experiment (n). n can be at most 79. The
output will be a histogram made up of spaces and asterisks (*), with n+1 columns (for the number of heads
which can go from 0 to n)
I have the code for the histogram all done, but the problem I have is how to store the number of heads as it's own variable. For example, if it flipped the coin 80 times and 40 of them were heads, I would want it to create an int for 40 flips, then add one to it. I just don't know how to go about initializing 80 variables without writing out int one = 0; int two = 0, int three = 0; until the end of time, then writing 80 if statements until it finds the right integer to add one to. Is there an easy way to do this or should there be a different approach I should be taking? Here is the code, please be gentle, literally only a month or so into an extremely basic java class
for(m=m; m>0; m--) { //runs m number of experiments of n coinflips, keeping track of total heads
n = o; // when N gets set to 0 through the while loop, o resets it back to it's original so it can loop again
while(n>0) {
n--;
if(random.nextBoolean()) {
heads++;
total++;
/** here is where I want the number of heads saved to a
variable, so that way later I can run a loop to put as many *'s as I need in the histogram later */
Just use an array for the 80 (or n) experiments:
I don't understand, this would just count how many heads/tails there are right? This doesn't save them (ie it flipped 5 heads 6 times, 4 heads 3 times, 3 heads twice, ect) unless I'm misunderstanding
If you are storing the number of head m times (where m is < 80), you can:
1) print the histogram as you generate the results (no array needed) OR
2) store the 80 results in an array
Example for 1 (no array):
for(int x=0; x<experiments; x++){
int heads = 0;
for(int y=0; y<flips; y++){
if(rnd.nextInt(2) == 0) //assume 0 is head
heads ++;
}
//print histogram
for(int y=0; y<heads; y++)
System.out.print("*");
System.out.println();
}
Example for 2 (with array):
int[] expr = new int[80]; //store results for 80 experiments
for(int x=0; x<expriments; x++)
for(int y=0; y<flips; y++)
if(rnd.nextInt(2) == 0)
expr[x] ++;
Use an array:
int n = 80;
// space for n integers, with indexes 0..n
int[] histogram = new int[n + 1];
for (int i = 0; i < experiments; i++) {
// flip coin n times, counting heads
int heads = ...;
histogram[heads] = histogram[heads] + 1;
}
for (int i = 0; i < histogram.length; i++) {
printStars(histogram[i]);
}
If you're unfamiliar with arrays, the Java Tutorial has a good explanation.
This question is translated into English by me from another forum, I found it interesting and then just write a Java solution. And found there's some heap size problem when dealing with large number like 10000000. And I would like to seek some really smart solution compared with my own.
Original Post is in Chinese. And I kind of revised it a little based on my understanding to make it clearer.
http://zhidao.baidu.com/question/1637660984282265740.html?sort=6&old=1#here
Below is the puzzle:
10000 rows of numbers;
1 row: 2,4,6,8...2K(2K<=10000000); (numbers no repeats for this row)
2 row: 3,3,6,6,9,9...3K(3K<=10000000); (starting from this row, each number repeats 2 times and a multiple which has something to do with row number (2XrowNumber-1) to be specificaly)
3 row: 5,5,10,10,15,15...5K(5K<=10000000);
and following 7K,9K,11K,13K....until
10000 row: 19999,19999,39998,39998....19999K,19999K (19999K<=10000000);
That's all the rows to be used in the following part. And now we will calculate the repeat times of numbers starting from row 1 and row 2:
Integer w1 is the repeat times of numbers in row 1 and row2. For example, consider row 1 numbers 2,4,6 and row 2 numbers 3,3,6,6. Then the repeat times up to this point would be 3 since 6 is already in row 1 and appears 2 times in row 2, and 3 appears 2 times in row 2;
Integer w2 is the repeat times of numbers in row 1 and row 2 and row 3.
Integer w3 is the repeat times of numbers in row 1 and row 2 and row 3 and row 4.
......
Integer w9999 is the repeat times of numbers of row 1,row 2,row 3 .....row 10000.
And now print out all integers, w1,w2....w9999;
I have come up with one Java solution, but I have heap size problem since 10000000 is too large and the memory is not enough. So I just use 10000 instead of 10000000, and 10 instead of 10000. Below is what I write in Java. I guess it should be right (if not, please point it out):
Set nums = new HashSet();
int max = 10000;
int row = 10;
for (int i=2;i<=max;i+=2){
nums.add(new Integer(i));
}
int nums_size = nums.size();
int w = 0;
for (int i=2;i<=(row);i++){
int tmp_count = 0;
int self_count = 0;
for (int j=(2*i-1);j<=max;j+=(2*i-1)){
nums.add(new Integer(j));
self_count++;
if (nums.size()==nums_size){
tmp_count++;
} else {
nums_size = nums.size();
}
}
w += tmp_count;
w += self_count;
System.out.println("w"+(i-1)+": "+w);
}
My question is
How to get a better solution in Java (if any)?
How to do it in C
since there would be no Set class in C as I remember. (importing 3rd
party library would not be preferred)?
Thanks.
Here is a simplified version of your code. Since it doesn’t use HashSet, creating a C version out of it should be no problem anymore.
int max = 10000;
int row = 10;
boolean[] seen=new boolean[max+1];
for(int i=2;i<=max;i+=2) seen[i]=true;
int w = 0;
for(int i=2;i<=(row);i++) {
int self_count = 0;
for(int j=(2*i-1);j<=max;j+=(2*i-1)) {
self_count++;
if(seen[j]) w++; else seen[j]=true;
}
w += self_count/2;
System.out.println("w"+(i-1)+": "+w);
}
Not an answer, but a hint: try using least common multiples.
For example, LCM(5,3)=15, and 15 is the first element in both rows 2 and 3. LCM(2,15)=30, and 30 is the first element in each of the first 3 rows.
You'll eventually get to a row r where the LCM of the first element of the first r rows is beyond 10,000,000, at which point no number shows up each of those rows.
Having an array such as int[] arr = new int[]{9, 6, 5, 2, 1, 2, 6, 3, 2, 7, 3, 8, 1, 5, 4, 7}; I want to print it like this:
* Output:
* 9
* 6 1
* 5 2 2
* 2 6 7 1
* 3 3 5
* 8 4
* 7
Without the * basically that's what I am trying to do. I intended to go over the array and just use System.out.println();until I reached then "end" which would be the 7 and then go to the next line but that didn't work.
I also tried printing 9 then 6 and 1 and so on but I couldn't make it to work either, I'm at a loss here and would appreciate guidance as to how can I think this through please.
EDIT
The intermediate step I have is making the array a "block" like this:
* Intermediate Step:
* 9 6 5 2
* 1 2 6 3
* 2 7 3 8
* 1 5 4 7
It should work for an array of any size.
I think this should work
You iterate 2 times. first you get the first row and all the diagonal rows below it, and then the last row and all the diagonal rows above it. You have to create a second array though to hold this info. I assumed that the array is same size for both X and Y. 7x7, 4x4 etc. tested with 4x4 data (your data)
String[][] array2 = new String[array.length*2][array.length];
for (int mb = 0; mb < array.length; mb++) {
String p1 = array[0][mb];
array2[mb][0] = p1;
int count = 0;
for (int i=1;i<=mb;i++) {
count++;
String p2 = array[i][mb-i];
array2[mb][count] = p2;
}
}
int counter = -1;
for (int mb = array.length -1; mb > 0; mb--) {
counter++;
String p1 = array[array.length -1][mb];
array2[mb+array.length -1][counter] = p1;
for (int i=0;i<counter;i++) {
String p2 = array[array.length -2 - i][array.length -counter + i];
array2[mb+array.length -1][i] = p2;
}
}
Well lets think you have two-dimensional array (you can change your one-dimension to two-dimensional easily)
PseudoCode :
whereToGo = RIGHT;
i = 0;
j = 0;
maxX = WIDTH;
maxY = HEIGHT;
minX = 0;
minY = 0;
while (somethingLeft){
addNumberToPyramid(array[i][j]);
if (whereToGo == RIGHT){
i++;
if (maxX == i) {
whereToGo = DOWN;
minY++;
}
} else if (whereToGo == DOWN){
//Same as if you go RIGHT, but increasing "j", at the end, you decrease maxY and then goLeft
} //... other two directions
}
This is how to parse input. Similar way for adding it to pyramid. I would prefer creating another 2D array, put that directly there as pyramid and then write method for printing this array correctly :
public class Pyramid{
//initialize minX, maxX etc.
int[][] array;
whereToGo = DOWN;
int i = 0, j = 0;
//initialize array size in constructor
public void addNumberToPyramid(int value){
if (whereToGo == DOWN){
array[i][j] == value;
j++;
if (j == maxY){
whereToGo = UPRIGHT;
maxY -= 2;
} else if (whereToGo == UPRIGHT){
} //... other else if directions
}
}
}
OK, first of all: You can't print a triangle like that for every length of an array. Say for example you had that array but missing the last entry; then your triangle would be missing one element at some point. In fact, you can print such a triangle if and only if the number of elements is the square of a natural number; in your example 16 = 4^2. Now, that 4 is also the length of your longest row.
OK, now how to do it. If you look at the intermediate step
9 6 5 2
1 2 6 3
2 7 3 8
1 5 4 7
and call that arr2, you want to print arr2[0][0] in the first row, arr2[1][0] and arr2[0][1] in the second row and so on until row 4 (which is of course the root of the length of the initial array). So you can write a nested loop that counts up like that.
Then you want to print arr2[1][3], arr2[2][2] and arr2[3][1] in the next row, then arr2[2][3] an arr2[3][2] and finally in the last row just arr2[3][3]. That is most easily done in a second nested loop.
I won't give you the exact code of course as this is obviously a learning task. But I will tell you that if you have a counter i for the outer loops and a counter j for the inner ones, the indexes in the intermediate array will depend on both i and j.
I need to flip a 1-D 64-element array of shorts (I can switch to ints if it's easier, but I assume the same processes will work for either) on it's head in Java. I represent it here as a square table for ease of understanding, since the actual problem is on a chessboard.
For example:
short[] example = new short[]
{
1, 2, 3,
4, 5, 6,
7, 8, 9
};
would become:
7 8 9
4 5 6
1 2 3
Please note that this is NOT the same as reversing the array (every answerer to similar questions I have found has made this mistake, hence my having to ask!). Reversing the array would give:
9 8 7
6 5 4
3 2 1
Apologies if I've missed any important info, any help is appreciated!
EDIT: The array is 1D and contains 64 elements, so short[64], and the reversed array is separate to the original. As far as what I've tried, I'm just struggling to wrap my head around it. I know how to reverse the array, but that's not what I'm after, and I had originally tried to reverse the index using:
byte index = (byte)(((byte)(position + 56)) - (byte)((byte)(position / 8) * 16));
Which is a code snippet I found on Chessbin, but this returns incorrect values and gives IndexOutOfBounds errors. In hindsight it's not clear to me if that code is meant to flip the index or reverse it. Since maths is not my strong suit, I tried to work around it with separate arrays.
My proposal would be like this:
public class Flipper {
public short[] flip(short[] array, int columns) {
short[] flipped = new short[array.length];
for(int i=0;i<array.length;i++){
int row = (i/columns); //use the fact that integer/integer is rounded down
int column = (i%columns);
flipped[i] = array[array.length-((columns*(row+1))-column)];
}
return flipped;
}
}
Which can be tested with:
public class FlipperTest {
private Flipper flipper = new Flipper();
#Test
public void test() {
short[] array = new short[]{1,2,3,4,5,6,7,8,9};
short[] actualResult = flipper.flip(array, 3);
assertThat(actualResult, equalTo(new short[]{7,8,9,4,5,6,1,2,3}));
}
}
Hope the code is self-explanatory
You have a physical 1D array representing a logical 2D array, and you want to swap rows. You can do this partly by mapping 2D array indices into a 1D array index.
Let height be the number of rows, and width be the number of columns.
for ( int i = 0; i < height/2; ++i ) {
int k = height - 1 - i;
for ( int j = 0; j < width; ++j ) {
short temp = array[i * width + j];
array[i * width + j] = array[k * width + j];
array[k * width + j] = temp;
}
}
I've written this for readability. You or the compiler may optimize some of the repeated computations.
You might be able to optimize further by using a 2D array, which would allow you to swap references to rows in O(height), rather than copying all the rows in O(height * width).
Im wondering how I could split a 1d array into a 2d array in java?
I know how to set up both of them and i know that I have to iterate over both of them using for loops im just not sure how I would go about it.
I have an array of students names and i want the first 5 to go on the top line and then the next 5 on the bottom line of the 2d array so as to create groups of 5 students.
so far I have:
public void main(String[] args)
{
for (int x=0; x<5;x++)
{
for (int y=0; y<5;y++)
{
board[x][y] = (letters)y;
System.out.print(board[x][y]);
System.out.print("");
}
}
}
How to I tell the it that i want this to be connected to the arrays
So, it sounds like your only problem is the calculation of the letters index. Try this:
for (int x = 0; x < 2; x++) {
for (int y = 0; y < 5; y++) {
board[x][y] = letters[x * 5 + y];
System.out.print(board[x][y]);
System.out.print("");
}
}
This will create 2 "rows" of 5 students each.
You can make the 2d array 5x(number of students / 5) or number of people per group by number of student / people per group /* number of groups */ so it is more dynamic.
You will only need one loop to achieve this. The loop goes through each of the names in the 1d array, get the names one by one and assign it to and appropriate index in the 2d array.
To figure out the index one of them could be just the counter of the loop mod(%) people per group this will keep the index between 0 to 4. To figure out the other index you could mod(%) the loop counter with (number of student / people per group)
so it will look like board[i%ppg][i%nog] ppg being people per group and nog being number of groups. You can easily calculate number of groups.
EDIT: 2d arrays are easy if you have a really simple way to visualize them. The trick I did when I was learning 2d arrays was to think of them as chess boards. Chess boards got vertical and horizontal indices represented by letters and number just like 2d arrays except in programming it is just numbers.
Take a closer look at this code, it's also computing the indexes even if your 1D array has a number of elements which is not divisible by 5.
String[] names = new String[104];
double size = names.length;
String[][] yetAnother = new String[(int) Math.ceil(size / 5)][5];
for (int i = 0; i < size; i++)
yetAnother[(int) Math.ceil(i / 5)][i % 5] = names[i];