How do I create a bigger matrix from another? - java

I'm having a problem working with matrices. I have a matrix which will hold 3 columns of data and as a starting point 10 rows of data. Each row is an article in a "cash register software" and each column is in order: {article number, items in stock, article price}.
As I mentioned, the int[][]articles has to start with the size of [10][3], but have the ability to expand with the help of a method "checkFull". The user will be asked how many articles he/she wants to add and the value will be saved into the variable "noOfArticles". The checkFull() method has to check if the value of articles fits into the article[][] matrix or if it has to create another matrix with the right amount of slots, copy the values from articles[][] and return the new matrix.
The following code is my shot at the problem, does anyone got any ideas how to get this method working properly?
public static int[][] checkFull(int[][]articles, int noOfArticles) {
int index = 0;
int i = 0;
while (i < articles.length)
{
if (articles[i][0] == 0)
{
index = i;
break;
}
i++;
}
if ((articles.length - index) < noOfArticles)
{
newmat = new int[noOfArticles + articles.length][3];
for (i = 0; i < articles.length; i++)
{
for (int j = 0; j < articles[i].length; j++)
{
int[][]newmat[i][j] = articles[i][j];
}
}
return newmat;
}
else
{
return articles;
}
}

Related

How to find most profitable Path in 2-Dimensional Array

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;
}

How to loop through an array and get how many zeros there are

I have a 2D array and it's like a maze.
So I loop through the first row to see if there is a zero (This zero is the opening) and then I go down to see if there is another zero below that zero.
The problem is that after the first 2 rows I don't know how I can write code to check left,right or down of that zero and move there and continue until I cannot do so any longer.
import java.util.Scanner;
public class AssignmentTwo
{
//int[rows][columns]
int[][] gasCavern = {{1,1,1,1,1,0,1},
{1,0,0,1,1,0,1},
{1,1,1,0,0,0,1},
{1,1,0,0,1,1,1},
{1,0,1,0,1,0,1},
{1,0,1,0,0,0,1},
{0,0,0,1,1,1,0},
{1,1,1,0,0,0,1}};
int counter = 0;
boolean checked = false;
// forLoop that deals with the first 2 rows.
// First check 1st row for a zero.
// Then check down and increment counter which ultimately shows area.
for(int column = 0; column < gasCavern[0].length; column++)
{
//Checking for opening in 1st row
if(gasCavern[0][column]== 0)
{
counter++;
gasCavern[0][column] = 2;
if(gasCavern[1][column]==0)
{
counter++;
}
}
}
for(int i=1; i<gasCavern.length; i++)
{
for(int j=0; j < gasCavern.length; j++)
{
if(gasCavern[i][j])
{
//Looking left
if(gasCavern[i][j-1]==2)
{
gasCavern[i][j-1]=2;
counter++;
}
//Looking Right
if(gasCavern[i][j+1]==2)
{
gasCavern[i][j+1]=2;
counter++;
}
//Looking up
if(gasCavern[i+1][j]==2)
{
gasCavern[i+1][j]=2;
counter++;
}
//Looking down
if(gasCavern[i-1][j]==2)
{
gasCavern[i-1][j]==2
counter++;
}
}
}
}
public boolean checkedForZeros()
{
//If returning false,go through while loop again
}
}
This is the code I have so far. In case I wasn't clear this is what I want to happen:
http://imgur.com/YOr86xs
I think with a bit more thought you would have got it!
Think about it, all you have to do is check the adjacent elements in the row you are looking at, which are just the columns in each side. Therefore:
[column+1]
Would check the element to the right, and:
[column-1]
Would check the element to the left.
Just be sure you don't accidentally go out of bounds.
EDIT: Let us know how you get on, if you are still struggling, I will provide more code, but try first.
This should work:
for (int x = 0; x < gasCavern.length; x++) {
for (int y = 0; y < gasCavern[x].length; y++) {
int num = gasCavern[x][y];
if (num == 0) {
// if it is a zero
} else {
// if it's not a zero (a one)
}
}
}

Creating optimal shopping list based on given conditions

I am trying to create shopping lists from a collection of products, where the returned shopping list should be optimized for cost as well as to meet another condition.
For example, let's say that I want to create shopping lists based on the energy content of the products. When the user enters a total sum, the returned shopping list should try to max out the kcal content while keeping the total sum at or around the sum specified by the user.
I've gotten so far as to create the collection of products, and all products are stored as objects with fields holding nutritional values and price etc. The kcal-value is also stored as a member variable in each product's object.
At first I considered looping through all combinations of products, sort out those that are way out of the price interval, and then return the one with the highest kcal content. But as the numbers of products available increases this soon becomes a non-viable option I think.
I now wonder if there is any algorithm to solve this problem, if not, is there any way to easily implement this?
I did something similiar with Dynamic Programming Wikipedia article on Dynamic Programming
In the following costs and values should be arrays of the same length. The length of the possible items to choose from. The capacity is the maximum sum of all the costs of items you choose. It returns an array of booleans of the same length determining whether to take the item or not.
The idea is to create a table with the solutions to sub-problems that can then be used to solve a bigger problem. The sub-problems just solve the same problem but with a smaller list, initially with only one item. The table contains the best value you can get with the first i items for each weight up to the maximum. As you add one potential item to the list you add its value to the previous solution for that allowed weight minus the weight your adding and check if that is better than the previous solution without the last item. Once the last row is created you can tell which items to take by checking for where there are differences in the values in that last row.
public boolean[] solve(int[] values, int[] costs, int capacity) {
boolean take[] = new boolean[values.length];
int min_cost = Integer.MAX_VALUE;
for (int i = 0; i < values.length; i++) {
if (costs[i] < min_cost) {
min_cost = costs[i];
}
}
int table[][] = new int[values.length][capacity + 1 - min_cost];
for (int i = 0; i < values.length; i++) {
int v = values[i];
int w = costs[i];
for (int j = 0; j < capacity - min_cost + 1; j++) {
int prev_value = 0;
int new_value = 0;
if (i > 0) {
prev_value = table[i - 1][j];
if (w <= j + min_cost) {
if (w <= j) {
new_value = table[i - 1][j - w] + v;
} else {
new_value = v;
}
}
} else if (w <= j + min_cost) {
new_value = v;
}
table[i][j] = Math.max(prev_value, new_value);
}
}
int index = capacity - min_cost;
for (int i = values.length - 1; i > 0 && index >= 0; i--) {
if (table[i][index] != table[i - 1][index]) {
take[i] = true;
index -= costs[i];
if (index < 0) {
System.err.println("index = " + index);
}
} else {
take[i] = false;
}
}
take[0] = index >= 0 && table[0][index] != 0;
return take;
}

Rewrite code using a linked list instead an a 2D array in java

I need to rewrite this code that uses a 2D array using a singly linked list. I thought I could just step through the list in the same way that this code steps through the matrix but it doesn't work and stops when trying to read a 2x2 array. Here is the original code with the array version:
Input looks likes this, the order is listed above each matrix:
1
5
2
2 3
5 9
public class Determinant {
public static int calculate(LinkedList matrix, int order) {
int det = 0;
int z = 0;
int new_order= 0;
int rows = 0;
int a = 0;
if (matrix.size() == 1) {
a = (int)matrix.get(1);
return a;
} else {
for (int i = 0; i < order; i++){// minor matrix is one order less than matrix
LinkedList minor = new LinkedList();
while (rows < order) {
//build the minor matrix, ignoring the first row
for (int j = 1; j < order; j++) {
if (matrix.get(z)!= null) {
int y = z + order;
minor.add(matrix.get(y));
}z++;
}rows++;
}// determinant calculated with recursive call
new_order = order-1;
a = (int) matrix.get(i);
det += a*Math.pow(-1,i)*calculate(minor, new_order);
}
}return det;
}
I can at least get it to run when I take the recursive part out, but when I put it back it it gets stuck on the 2x2 matrix. I get this error: Exception in thread "main" java.lang.NullPointerException
at listdeterminant.Matrix.calculat

Comparing integers of rows and columns of a 2d array. Sudoku

Hey I'm having trouble getting my code to compare the integers of a given row or column and block to make sure there are no duplicates within those parameters. I don't know if it would be a good idea separating the three contraints in 3 different methods or just trying to attempt to do all at once.
public static rowCheck(int[][] nsudokuBoard) {
for (int i =0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
// (nsudokuBoard)
}
}
}
this is my code im starting. before you guys bash on me for not even being able to compile this im stuck on how to compare all the values of a row of the 2d array.
You can compare all the values of the 2d array as shown in the code below:
void validate(final int[][] nsudokuBoard) {
final int width = nsudokuBoard[0].length;
final int depth = nsudokuBoard.length;
for (int i = 0; i < width; i++) {
int j = i;
int reference = nsudokuBoard[i][j];
do {
if (j < width) {
int current = nsudokuBoard[i][j];
if (current == reference) {
// invalid entry found do something
}
}
if (j < depth) {
// note reversed indexes
int current = nsudokuBoard[j][i];
if (current == reference) {
// invalid entry found do something
}
}
++j;
} while ((j >= width) || (j >= depth));
}
}
I haven't tried to compile this code, but it should give you an idea of how to accomplish your task. I would suggest that rather than passing in int[][] sudokuBoard that you should define a class which encapsulates the concept of a SudokuSquare and pass in SudokuSquare[][] , that way your validate method can return a List<SudokuSquare> containing all the offending entries.
I'll show how you might do it for one row, and then you can figure out the rest. I'm assuming your values are 1 through 9 inclusive, and that you don't have any zeroes or any "unfilled entries."
boolean isRowValid(int[][] grid, int row) {
boolean[] seen = new boolean[9];
int row; // chosen somewhere else
for (int col = 0; col < 9; col++) {
if (seen[grid[row][col] - 1]) { // if we've seen this value before in this row
return false; // there is a duplicate, and this is a bad sudoku
}
seen[grid[row][col] - 1] = true; // mark us as having seen this element
}
return true; // we're all good
}
return true; // this row is fine
make a class Cell with fields row,col,block,value; then make a class Matrix with field cells = cell[], fill matrix.
make a class checker with main method Matrix matrix = init(int[][]) and check(matrix), where init(ยท) fills the matrix.
boolean ok = check(matrix) where check(Matrix) does if(!rowcheck())return false; if(!colcheck()) return false etc;
create some methods like getrows(), getrow(r) and for(Cell cell: matrix.values()) to filter out the ones you want.
a bit tedious but i have done it and it is solid as rock.
As a note, filtering over matrix may seem stupid but computers are fast and the problem is O(1) since it is 9x9.

Categories

Resources