Below problem has a list of characters and number of columns as the input. Number of columns is not a constant and can vary with every input.
Output should have all the rows fully occupied except for the last one.
list: a b c d e f g
colums: 3
Wrong:
a b c
d e f
g
Wrong:
a d g
b e
c f
Correct:
a d f
b e g
c
I have tried below:
public static void printPatern(List<Character> list, int cols) {
for (int i = 0; i < cols; i++) {
for (int j = i; j < list.size(); j += cols) {
System.out.print(list.get(j));
}
System.out.println();
}
}
It gives output as (which is wrong):
a d g
b e
c f
I am trying to come with an algorithm to print the correct output. I want to know what are the different ways to solve this problem. Time and Space complexity doesn't matter. Also above method which I tried is wrong because it takes columns as the parameter but that's actually acting as the number of rows.
FYI: This is not a HOMEWORK problem.
Finally able to design the algorithm for this problem
Please refer below java code same
public class puzzle{
public static void main(String[] args){
String list[] = { "a", "b", "c","d","e","f","g","h","i","j" };
int column = 3;
int rows = list.length/column; //Calculate total full rows
int lastRowElement = list.length%column;//identify number of elements in last row
if(lastRowElement >0){
rows++;//add inclomplete row to total number of full filled rows
}
//Iterate over rows
for (int i = 0; i < rows; i++) {
int j=i;
int columnIndex = 1;
while(j < list.length && columnIndex <=column ){
System.out.print("\t"+list[j]);
if(columnIndex<=lastRowElement){
if(i==rows-1 && columnIndex==lastRowElement){
j=list.length; //for last row display nothing after column index reaches to number of elements in last row
}else{
j += rows; //for other rows if columnIndex is less than or equal to number of elements in last row then add j value by number of rows
}
}else {
if(lastRowElement==0){
j += rows;
}else{
j += rows-1; //for column greater than number of element in last row add j = row-1 as last row will not having the column for this column index.
}
}
columnIndex++;//Increase column Index by 1;
}
System.out.println();
}
}
}
This is probably homework; so I am not going to do it for you, but give you some hints to get going. There are two points here:
computing the correct number of rows
computing the "pattern" that you need when looping your list so that you print the expected result
For the first part, you can look into the modulo operation; and for the second part: start iterating your list "on paper" and observe how you are printing the correct result manually.
Obviously, that second part is the more complicated one. It might help if you realize that printing "column by column" is straight forward. So when we take your correct example and print the indexes instead of values, you get:
0 3 6
1 4 7
2 5
Do that repeatedly for different input; and you will soon discover the pattern of indexes that you need to print "row by row".
Related
I'm trying to implement a game where the viable moves are down-left and down-right.
The parameter for the function is for the size of the array, so if you pass 4 it will be a 4 by 4 array.
The starting position is the top row from any column. Every element in the array is a number in the range 1-100, taken from a file. I need to find the resulting value for the most profitable route from any starting column.
My current implementation will compare the right position and left position and move to whichever is higher. The problem is, for example, if the left position is lower in value than the right, but the left position will provide more profit in the long run since it can access higher value elements, my algorithm fails.
Here is a demo:
84 (53) 40 62
*42* 14 [41] 57
76 *47* 80 [95]
If we start at number 53. The numbers enclosed in * are the moves that my algorithm will take, but the numbers enclosed in [] are the moves my algorithm should take.
This is my code:
import java.util.ArrayList;
import java.util.Scanner;
public class bestPathGame{
private int[][] grid;
private int n;
public bestPathGame(int num){
Scanner input = new Scanner(System.in);
n = num;
grid = new int[n][n];
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
grid[i][j] = input.nextInt();
}
}
}
public static void main(String[] args){
bestPathGame obj = new bestPathGame(Integer.parseInt(args[0]));
obj.bestPath();
}
private boolean moveLeftBetter(int r,int c){
if(c <= 0){
return false;
} else if (c >= n -1 ){
return true;
}
return grid[r][c-1] > grid[r][c+1];
}
public void bestPath(){
ArrayList<Integer> allOptions = new ArrayList<>();
for(int k = 0; k < n; k++){
int row = 0;
int col = k;
int collection = grid[row][col];
while(row < n - 1){
row += 1;
if(moveLeftBetter(row,col)){
col-=1;
} else{
col+=1;
}
collection += grid[row][col];
}
allOptions.add(collection);
}
System.out.println(allOptions.stream().reduce((a,b)->Integer.max(a,b)).get());
}
}
Greedy algorithm vs Dynamic programming
There's an issue with the logic of your solution.
Basically, what you are implemented is a called a greedy algorithm. At each step of iteration, you are picking a result that optimal locally, assuming that this choice will lead to the optimal global result. I.e. your code is based on the assumption that by choosing a local maximum between the two columns, you will get the correct global maximum.
As a consequence, your code in the bestPath() method almost at each iteration will discard a branch of paths based on only one next value. This approach might lead to incorrect results, especially with large matrixes.
Greedy algorithms are rarely able to give an accurate output, usually their result is somewhat close but not precise. As an upper-hand, they run fast, typically in O(n) time.
For this problem, you need to use a dynamic programming (DP).
In short, DP is an enhanced brute-force approach which cashes the results and reuses them instead of recalculating the same values multiple times. And as well, as a regular brute-force DP algorithms are always checking all possible combinations.
There are two major approaches in dynamic programming: tabulation and memoization (take a look at this post for more information).
Tabulation
While implementing a tabulation first you need to create an array which then need to be prepopulated (completely or partially). Tabulation is also called the bottom-up approach because calculation start from the elementary edge cases. Every possible outcome is being computed based on the previously obtained values while iterating over this array. The final result will usually be stored in the last cell (in this case in the last row).
To implement the tabulation, we need to create the matrix of the same size, and copy all the values from the given matrix into it. Then row by row every cell will be populated with the maximum possible profit that could be obtained by reaching this cell from the first row.
I.e. every iteration will produce a solution for a 2D-array, that continuously increases by one row at each step. It'll start from the array that consists of only one first row (no changes are needed), then to get the profit for every cell in the second row it's values has to be combined with the best values from the first row (that will be a valid solution for 2D-array of size 2 * n), and so on. That way, solution gradually develops, and the last row will contain the maximum results for every cell.
That how the code will look like:
public static int getMaxProfitTabulation(int[][] matrix) {
int[][] tab = new int[matrix.length][matrix.length];
for (int row = 0; row < tab.length; row++) { // populating the tab to preserve the matrix intact
tab[row] = Arrays.copyOf(matrix[row], matrix[row].length);
}
for (int row = 1; row < tab.length; row++) {
for (int col = 0; col < tab[row].length; col++) {
if (col == 0) { // index on the left is invalid
tab[row][col] += tab[row - 1][col + 1];
} else if (col == matrix[row].length - 1) { // index on the right is invalid
tab[row][col] += tab[row - 1][col - 1];
} else {
tab[row][col] += Math.max(tab[row - 1][col - 1], tab[row - 1][col + 1]); // max between left and right
}
}
}
return getMax(tab);
}
Helper method responsible for extracting the maximum value from the last row (if you want to utilize streams for that, use IntStream.of(tab[tab.length - 1]).max().orElse(-1);).
public static int getMax(int[][] tab) {
int result = -1;
for (int col = 0; col < tab[tab.length - 1].length; col++) {
result = Math.max(tab[tab.length - 1][col], result);
}
return result;
}
Memoization
The second option is to use Memoization, also called the top-down approach.
As I said, DP is an improved brute-force algorithm and memoization is based on the recursive solution that generates all possible outcomes, that is enhanced by adding a HashMap that stores all previously calculated results for every cell (i.e. previously encountered unique combination of row and column).
Recursion starts with the first row and the base-case of recursion (condition that terminates the recursion and is represented by a simple edge-case for which output is known in advance) for this task is when the recursive call hits the last row row == matrix.length - 1.
Otherwise, HashMap will be checked whether it already contains a result. And if it not the case all possible combination will be evaluated and the best result will be placed into the HashMap in order to be reused, and only the then the method returns.
Note that tabulation is usually preferred over memoization, because recursion has significant limitations, especially in Java. But recursive solutions are sometimes easier to came up with, so it's completely OK to use it when you need to test the idea or to prove that an iterative solution is working correctly.
The implementation will look like that.
public static int getMaxProfitMemoization(int[][] matrix) {
int result = 0;
for (int i = 0; i < matrix[0].length; i++) {
result = Math.max(result, maxProfitHelper(matrix, 0, i, new HashMap<>()));
}
return result;
}
public static int maxProfitHelper(int[][] matrix, int row, int col,
Map<String, Integer> memo) {
if (row == matrix.length - 1) { // base case
return matrix[row][col];
}
String key = getKey(row, col);
if (memo.containsKey(key)) { // if cell was already encountered result will be reused
return memo.get(key);
}
int result = matrix[row][col]; // otherwise result needs to be calculated
if (col == matrix[row].length - 1) { // index on the right is invalid
result += maxProfitHelper(matrix, row + 1, col - 1, memo);
} else if (col == 0) { // index on the left is invalid
result += maxProfitHelper(matrix, row + 1, col + 1, memo);
} else {
result += Math.max(maxProfitHelper(matrix, row + 1, col - 1, memo),
maxProfitHelper(matrix, row + 1, col + 1, memo));
}
memo.put(key, result); // placing result in the map
return memo.get(key);
}
public static String getKey(int row, int col) {
return row + " " + col;
}
Method main() and a matrix-generator used for testing purposes.
public static void main(String[] args) {
int[][] matrix = generateMatrix(100, new Random());
System.out.println("Tabulation: " + getMaxProfitTabulation(matrix));
System.out.println("Memoization: " + getMaxProfitMemoization(matrix));
}
public static int[][] generateMatrix(int size, Random random) {
int[][] result = new int[size][size];
for (int row = 0; row < result.length; row++) {
for (int col = 0; col < result[row].length; col++) {
result[row][col] = random.nextInt(1, 101);
}
}
return result;
}
I have been asked in an interview about how to implement Inner Join using nested for loop in Java. I found on internet about Hash Join here https://rosettacode.org/wiki/Hash_join but couldn't find anything on internet explaining about simple nested loop implementation of inner join. I tried implementing the code but got stuck at few places as mentioned in the code comment.
/**
*
* #param R
* #param index1 Join column for table R.
* #param S
* #param index2 Join column for table S.
* #return
*/
public String[][] innerJoin(String[][] R, int index1, String[][] S, int index2) {
// How to define the result array. What should be it's size?? Is the below code correct.
String[][] result = new String[R.length + S.length][R[0].length + S[0].length];
// loop through both the tables to find out when the join column have common values.
// output those common values.
for (int i = 0; i < R.length; i++) {
for (int j = 0; j < S.length; j++) {
if (R[i][index1] == S[j][index2]) {
// How to combine both tables here ???
}
}
}
return result;
}
)
You have correctly identified 3 important issues in the question code:
how do you calculate the size of the result table?
how do you find matches?
when you find a match, how do you add it to your result table?
The easy way to calculate the result is to store matches somewhere else, and then count how many you have found before returning them. In this sense, it would be better to use ArrayList<String[]> instead of String[][], because you can append to ArrayLists but cannot change the size of arrays.
Finding matches with a double-loop is indeed very inneficient O(nm), but hey, if that is what they want, it can certainly be done. It would be a lot easier to sort on the indices first and then work on that (O(n log n + m log m + n log m), with O(n+m) extra memory); or build hashtables and use them (O(n + m + n) = O(n + m)).
Choosing what to return depends on what the columns represent, and if there are any duplicates. You could, for example, decide on the following format:
as 1st column, the contents of index1
all columns (except index1 one) from the 1st table
all the columns (except index2) from the second table.
Note that the choice of format is somewhat arbitrary; you could have left index1 in its place, and then just ommit it from the columns of table 2. In any case, with the previous answers, you would get:
public String[][] innerJoin(String[][] R, int index1, String[][] S, int index2) {
// temporary storage for matches
ArrayList<String[]> matches = new ArrayList<>();
// loop through both the tables to find out when the join column have common values.
// output those common values.
for (int i = 0; i < R.length; i++) {
for (int j = 0; j < S.length; j++) {
if (R[i][index1] == S[j][index2]) {
matches.add(combine(R[i], S[j], index1, index2));
}
}
}
// convert matches to expected output array
return matches.toArray(new String[matches.size()][]);
}
private String[] combine(String[] one, String[] two, int index1, int index2) {
String[] r = new String[one.length + two.length - 1];
int pos = 0;
r[pos ++] = one[index1];
for (int i=0; i<one.length; i++) if (i != index1) r[pos ++] = one[i];
for (int i=0; i<two.length; i++) if (i != index2) r[pos ++] = two[i];
return r;
}
I will try to give you some hints:
The length for the result array is not the sum of the length of R and S tables. Depending on the contents of the tables, it could be up to R.length * S.length.
The number of "columns" in the result array is indeed R[0].length + S[0].length (as long as the arrays are "real" tables and do not have variable number of "columns" per "row").
In your loop (in the if block), you should
In the current "output" line of the result array (starting with 0), set first R[0].length columns (0..rl - 1) to the contents of the R[i][0] ... R[i][rl - 1] columns
Then, set the rl ... R[0].length + S[0].length - 1 columns (rl ... rl + sl - 1) to the contents of the S[j][0] ... S[j][sl - 1] columns
Increment a counter for the current "output" line in the result array
In the end, it is just some array offset arithmetics ;-)
I'm trying to add all of the values for each column in a 2D array and these sums become values that overwrite the last row of the array
for example:
4 5 6 7 8
1 2 3 4 5
0 0 0 0 0 //this row will be replaced by the sum of each column
4 5 6 7 8
1 2 3 4 5
5 7 9 11 13
public static void fillTotals(int[][] scores)
{
int count = 0;
for (int r = 0; r < scores.length - 1; r++)
{
scores[r][0] += count;
scores[scores.length - 1][scores[0].length - 1] = count;
}
}
I thought I could keep the columns the same and add it down with the changing rows but it isn't rewriting the last row. Also I don't know how to change the values at the bottom
You need to iterate once over all rows and columns, actually iterate over all rows, for every column. If you assume that the number of columns is the same for every row, then you can use scores[0].length as a fixed value.
public static void fillTotals(int[][] scores) {
for (int c=0; c < scores[0].length; ++c) {
int sum = 0;
for (int r=0; r < scores.length - 1; ++r) {
sum += scores[r][c];
}
scores[scores.length - 1][c] = sum;
}
}
This assumes that the final row of the 2D array is not part of the sum and is available to be overwritten with the sum of all preceding values, for each column.
Well, the reason that nothing is being updated is that you never change count, so you just end up adding 0 to everything. I think what you want instead of:
scores[r][0] += count;
is:
count += scores[r][0];
That way count will contain the summation of every element in the first column.
To be clear, scores[r][0] += count; is the same as scores[r][0] = scores[r][0] + count;, whereas I think you probably want count = scores[r][0] + count;
That being said, Im still pretty sure this code isnt actually going to work (sorry), since you only ever actually sum values from the first column. However, for the sake of not just doing way may be a school assignment for you, Im just going to leave it there. If you're still stuck let me know, and I'll try to help!
Assume I had a 2D integer array, mxn.
I want to traverse this array like a sine wave.
In specific, traversal would start from the last row, and the first column, move onto the first row and the second column, move onto the last row and the third column.
I have attached an image to elaborate further.
t:
I only know how to traverse in order, but I was thinking of transposing the columns, changing the starting index of the column at every round, but I couldn't create a consisting loop to do so.
My attempt:
boolean startsAtbottom=true;
//cols become rows, startPoint alternates
for(int i = 0;i<n;i++)
{
if(startsAtbottom)
{
for(int j =m-1;j>-1;j--)
{
System.out.print(myArr[j][i]);
}
startsAtbottom=false;
}
else
{
for(int j =0;j<m;j++)
{
System.out.print(myArr[j][i]);
}
startsAtbottom=true;
}
}
The following code will do what you want. All you want is to change the way you traverse in consecutive iterations.
boolean traverseInOrder=true;
for(int i=0;i<columnCount;i++){
for(int j=0;j<rowCount;j++){
index=j;
if(!traverseInOrder){
index=rowCount-j-1;
}
//access the element
int element=array[i][index];
}
traverseInOrder= !traverseInOrder;
}
Your solution works, and there's nothing wrong with it. However you can get rid of the if by doing this:
for (int i = 0; i < n; i++) {
boolean goingUp = i % 2 == 0;
for (int j = 0; j < m; j++) {
int row = goingUp ? m - 1 - j : j;
System.out.println(myArr[row][i]);
}
}
Starting from your input you have that:
the outer loop index just increments from 0
the inner loop index increments for even columns and decrements for odd columns
you can determine if a number is even or odd by just checking if modulo is 0 (or by checking if (i & 0x01) == 0 but that's irrelevant)
Given this it's quite easy to model that pattern:
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
int value = data[i][i % 2 == 0 ? (cols - j - 1) : j]
}
}
The formula cols - j - 1 allows you to start from the end and go backward (see that with j = 0 you have cols - 1 and with j = cols - 1 you have cols - (cols - 1) - 1 == 0).
Mind that Java is nor column major nor row major, since a bidimensional array is just an array of arrays so according to your real layout you may need to swap indices.
I'm trying to print how many rows contain subarrays (a, b, c) which satisfy a + b = c
int [][] matrix = {
{0,**5,2,7**,0,0},
{6,0,2, 1,-5,5},
{8,5,**1,1,2**,-2},
{3,-1,-5,-3,-4,-2}
};
this is the matrix in question it has only two sums so my program should print 2 , but somehow i miss something , the program should only print the rows that contain a sum of numbers not matter how many they are on a row
int [][] matrix = {
{0,5,2,7,9,0},
{6,0,2, 1,-5,5},
{8,5,1,1,2,-2},
{3,-1,-5,-3,-4,-2}
};
for example here we have 3 sums, but my program should print 2 anyway
public static int rowSumsOfThree(int [][] matrix) {
int count = 0 ;
if (matrix.length != 0 ) {
for (int i = 0 ; i < matrix.length ; i++) {
for (int j = 0 ; j < matrix[0].length-2 ; j++)
if (matrix[i][j] + matrix[i][j+1] == matrix[i][j+2]) {
count++;
break;
}
}}
return count;
}
this is my code so far , i know it's maybe some stupid mistake i make , if you can provide some explanation it is greatly appreciated , thank you all
Maybe my english is bad , I need to create a method that sums the elements within an array as
int [] matrix = {{2,3,4,7,8,3,2},
{1,23,4,2,2,}};
given this matrix , i need to sum them like this , first two elements = the third , second and third element = the fourth and so on , if the algorithm checks than it should return on how many rows it checks , first matrix should be 2 , second matrix should be 1 ; i hope i explained better
EDIT : Use of break solved my problem ! It will count only one sum per row , even if there are more per row , therefor count will be equal also to the numbers of rows. thank you for the help
As ari said, your return statement should be:
return count;
not
return rowIndex;
It's a very simple bug, consider deleting your question.