I'd would like to implement a check to see if a sudoku is valid in Java, and came across (http://leetcode.tgic.me/valid-sudoku/index.html).
I understand how it is validating rows and columns, but for the 3x3 grids validator:
34 for(x = 0; x < mx; x += 3){
35 for(y = 0; y < my; y += 3){
36
37 HashSet<Character> block = new HashSet<Character>();
38
39 for(int offset = 0; offset < 9; offset++){
40 int ox = offset % 3;
41 int oy = offset / 3;
42
43 char c = board[x + ox][y + oy];
44 if(c != '.'){
45 if(block.contains(c)) return false;
46
47 block.add(c);
48 }
49 }
50 }
51 }
What is offset and how does it help to check every cell in the 3x3 grid? I brute forced it and tried x=0, y=0, offset=0 and offset=1 first, but offset=1 gives int ox = 1%3 = 1; and int oy = 1/3, so the board[0 + 1][0+(1/3)] = board[1][1/3], and what does cell [1/3] represent and so on?
when you divide n by m, both are int's (either literals or variables) the result is also an int, so 1/3 -> 0
Hence when
offset == 0 => ox=0, oy=0
offset == 1 => ox=1, oy=0
offset == 2 => ox=2, oy=0
offset == 3 -> ox=0, oy=1
...
hence you will loop nicely of the 3 rows and 3 columns
Your HashSet approach looks quite good, but needs a little tweaking...
The assumption is: when the first block is duplication free and the same position in all blocks is duplication free too, then the sudoku is solved.
In you outer loop you should go trough the values of the first block only.
You should add the current value to the "first block check set" and check, that the all the blocks have a different number at the same position by an inner loop with its own "check set":
First iteration
1## 2## 3##
### ### ###
### ### ###
4## 5## 5##
### ### ###
### ### ###
7## 8## 9##
### ### ###
### ### ###
firstBlock: [1]
second iteration
#2# #3# #4#
### ### ###
### ### ###
#5# #6# #7#
### ### ###
### ### ###
#8# #9# #1#
### ### ###
### ### ###
firstBlock: [1,2]
The big trick is to avoid separate loops for x and y coordinates.
Since Java is an object oriented programming language I suggest to use objects to determine the coordinates. We could hold them in an Array (set a bookmark,I usually say "Collection" instead...) and iterate ofer it with a simple forech loop...
Also we have to deal with a fix number of objects we know in advance (there a 9 blocks with 9 positions in each...)
so I suggest using Java enums like this:
so you logic should look like this:
public class SudokuCheck {
enum SudokuPosition {
p11(0, 0), p12(0, 1), p13(0, 2),
p21(1, 0), p22(1, 1), p23(1, 2),
p31(2, 0), p32(2, 1), p33(2, 2);
private final int x;
private final int y;
SudokuPosition(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {return x;}
public int getY() {return y;}
}
boolean check(int[][] sudoku) {
Set<Integer> firstBlockUniqueNumbers = new HashSet<>();
for (SudokuPosition inBlock : SudokuPosition.values()) {
firstBlockUniqueNumbers.add(sudoku[inBlock.x][inBlock.y]);
Set<Integer> samePosInOtherBlocksUniqueNumbers = new HashSet<>();
for (SudokuPosition ofBlock : SudokuPosition.values()) {
int sameXinAll = inBlock.x + offset(ofBlock.x);
int sameYinAll = inBlock.y + offset(ofBlock.y);
samePosInOtherBlocksUniqueNumbers.add(sudoku[sameXinAll][sameYinAll]);
}
if (9 > samePosInOtherBlocksUniqueNumbers.size())
// numbers where not unique at current block position
// through all the blocks
return false;
}
return 9 == firstBlockUniqueNumbers.size();
}
private int offset(int xOrY) {
return xOrY * 3;
}
}
I hopefully demonstrated the usefulness of Java enums and how important good identifier names are.
I think this approach could be improved in 2 ways:
using the Java 8 Stream API may replace the forech loops
the names of the position elements somehow repeat their constructor values which may lead to nasty mistakes. The latter may be replaces by some clever calculation on the constant name which is available via name(), but for this demonstration it might be good enough as it is...
the most optimal answer I think will be :
public boolean isValidSudoku(char[][] board) {
if (board == null || board.length == 0) return false;
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
if (board[i][j] == '.') continue;
if (!isValid(board, i, j)) return false;
}
}
return true;
}
public boolean isValid(char[][] board, int row, int col) {
for (int i = 0; i < board.length; i++) {
if (i == row) continue;
if (board[i][col] == board[row][col]) return false;
}
for (int j = 0; j < board[0].length; j++) {
if (j == col) continue;
if (board[row][j] == board[row][col]) return false;
}
for (int i = (row / 3) * 3; i < (row / 3 + 1) * 3; i++) {
for (int j = (col / 3) * 3; j < (col / 3 + 1) * 3; j++) {
if (i == row && j == col) continue;
if (board[i][j] == board[row][col]) return false;
}
}
return true;
}
Related
I'm a beginner programmer and taking an intro to Java class. We were assigned to write a program that outputs the letter E made of asterisks with 5 down and 3 across as below:
***
*
***
*
***
The only requirement was to use nested-loops and if statements to get to our result. Below is my code. It works as intended, but I'm having trouble understanding why.
public class LetterE {
public static void main(String args[]) {
final int NUM_ACROSS = 3;
final int NUM_DOWN = 5;
int row;
int column;
for (row = 1; row <= NUM_DOWN; row++) {
if (row == 1 || row == 3 || row == NUM_DOWN)
for (column = 1; column <= NUM_ACROSS; column++) {
if (column == 1 || column == NUM_ACROSS)
System.out.print("*");
}
System.out.print("*");
System.out.print(" ");
System.out.println();
}
System.exit(0);
}
}
Basically my issue comes with the System.out.print statements. I don't understand the relationship between my loops and the print statements. For example, the first print statement is inside the curly brace and taking it out causes an incorrect output. On top of that, I don't understand what the other print statements outside of that first curly brace are for and why they can't be inside the curly brace.
Any guidance would be greatly appreciated. Trying my hardest to understand how this works, but I've been stuck on it for a while now.
Thank you very very much!
final int NUM_ACROSS = 3;
final int NUM_DOWN = 5;
int row;
int column;
I assume you know what the above code does, so I won't elaborate on that.
for (row = 1; row <= NUM_DOWN; row++) {
This code mean you want to execute the code inside the curly braces continuously as long as row <= NUM_DOWN. But before doing that, we assign 1 to row (this statement is executed only once). Each iteration ( = a full execution of the code inside the curly braces) row++ will be executed.
So we start off with row == 1, then row == 2, row == 3 ... until row == 6, at which point row > NUM_DOWN, because NUM_DOWN == 5.
If we would put all the values we have gotten for row in a list, the list would be equal to {1,2,3,4,5,6}, which contains 6 values. However, because the for loop is exited when row == 6, there are only 6 - 1 == 5 iterations.
Moving on:
if (row == 1 || row == 3 || row == NUM_DOWN){
Basically it means: if row == 1 OR row == 3 OR row == 5, then execute the code inside the curly braces. Otherwise, skip it.
for (column = 1; column <= NUM_ACROSS; column++) {
Basically the same as the other for loop, but just with different variables.
if (column == 1 || column == NUM_ACROSS)
Also the same as the if statement above, but again, with different parameters.
System.out.print("*");
This will print the * character once to the console without a newline ( = enter, basically).
The print statements that will be executed after this one will append another character to the already written characters, so your output will first look like this after the first iteration:
*
Then it will look like this after the third (in the second, column is equal to 2, so column == 1 || column == NUM_ACROSS is false and thus the code inside is not executed):
**
Then the loop is exited, and the other print statement is executed.
***
A space is also appended, but it is not visible because... well, it is a space :P
The println function is essentialy the same as print but it also appends the escape sequence \n. This escape sequence, called a newline, is like hitting enter on your keyboard: it starts a new line.
The next iteration, the code within the first if statement is skipped entirely, so we jump straight to the second print function. Now our output looks like this:
***
*
If we repeat the process, we will get:
***
*
***
.
***
*
***
*
.
***
*
***
*
***
Onto "optimizing" the program, because there is actually quite a lot of redundant code here:
int row;
int column;
Just put it inside the for statements like this:
for (int row = 1; row <= NUM_DOWN; row++) {
It is shorter and a bit more readable ;)
if (row == 1 || row == 3 || row == NUM_DOWN){
This one is a bit odd, because on one hand, declaring NUM_DOWN makes it easier to change the height if you want to, but on the other hand, you have to edit the constants 1 and 3 manually then either way.
Let's go with the somewhat more adaptable way:
if (row == 1 || row == NUM_DOWN / 2 + 1 || row == NUM_DOWN) {
Integers are always rounded down, so 5 / 2 == 2. The letter may look a bit odd when NUM_DOWN is even, but whatever.
for (int column = 1; column <= NUM_ACROSS; column++)
if (column == 1 || column == NUM_ACROSS)
Well, this is just a strange section of code: we would be better of starting off with column = 2 (2 because we will print another asterisk below) and scrapping the if statement entirely (the loop will be executed for the values 2 and 3, so 2 elements total --> 2 asterisks).
System.out.print(" ");
Since we can't read it, we can as well remove it altogether
System.out.println("*");
Again, it is shorter and it pretty much does the same thing.
System.exit(0);
Hmmm... It is not really needed, because your program returns 0 by default anyways.
The final program looks like this:
public class LetterE {
public static void main(String args[]) {
final int NUM_ACROSS = 3;
final int NUM_DOWN = 5;
for (int row = 1; row <= NUM_DOWN; row++) {
if (row == 1 || row == NUM_DOWN / 2 + 1 || row == NUM_DOWN)
for (int column = 2; column <= NUM_ACROSS; column++)
System.out.print("*");
System.out.println("*");
}
}
}
Try below code. I replaced inner loop print to '#' just to give you idea how it works.. The inner loop is to print additional * required for 3 lines (top, middle, and bottom). Outer System.out is by default we need * in each line and System.out.println is to move to next line. I moved the inner for loop in {} to make it more readable.
public class LetterE {
public static void main(String args[]) {
final int NUM_ACROSS = 3;
final int NUM_DOWN = 5;
int row;
int column;
for (row = 1; row <= NUM_DOWN; row++) {
if (row == 1 || row == 3 || row == NUM_DOWN){
for (column = 1; column <= NUM_ACROSS; column++) {
if (column == 1 || column == NUM_ACROSS)
System.out.print("L");
}
}
System.out.print("*");
System.out.print(" ");
System.out.println();
}
System.exit(0);
}
}
public class LetterE {
public static void main(String[] args) {
int row;
int column;
for (row = 1; row <= 5; row++) { //final int NUM_DOWN = 5
if (row == 1 || row == 3 || row == 5) {
for (column = 1; column <= 3; column++) {//final int NUM_ACROSS = 3
if (column == 1 || column == 3)
System.out.print("*");
}
}
System.out.print("*");
System.out.print("\n");
}
System.exit(0);
}
}
Look at my code.
I have added another bracket for if loop for making it easier to you.
following code prints 1 * for 5 rows.
for (row = 1; row <= 5; row++) {
System.out.print("*");
System.out.print("\n");
}
output:
row1: 1 = *
row2: 1 = *
row3: 1 = *
row4: 1 = *
row5: 1 = *
Inside this for loop there is another for loop with if condition
if (row == 1 || row == 3 || row == 5) {
for (column = 1; column <= 3; column++) {//final int NUM_ACROSS = 3
if (column == 1 || column == 3)
System.out.print("*");
}
}
This loop prints another 2 * for row 1,3,5
So, total no of * for
row1: 1 + 2 = ***
row2: 1 = *
row3: 1 + 2 = ***
row4: 1 = *
row5: 1 + 2 = ***
Hope that it will help you to understand.
import processing.core.PApplet;
import static java.lang.System.out;
public class GoL2 extends PApplet {
int rectSideLength = 25; // rectSideLength = length of each side of the rectangles drawn that represent cells
int generation = 0;
int windowWidth = 1920;
int windowHeight = 950;
int[][] currentGeneration = new int[windowWidth][windowHeight]; // currentGeneration = 2D array to gold cell values of current generation
int[][] nextGeneration = new int[windowWidth][windowHeight]; // nextGeneration = 2D array to hold cell values of next generation
int sumOfNeighbors;
int temporarySumOfNeighbors;
int counter;
public static void main(String[] args) {
PApplet.main("GoL2");
}
public void settings() {
size(windowWidth, windowHeight);
}
int numRectWidth = width / rectSideLength; // numRectWidth = the number of rectangles wide that will fit in the x axis of window
int numRectHeight = height / rectSideLength; // numRectHeight = the number of rectangles that will fit in the y axis of window
// The previous statements are here because they need the size of the frame to
// be set in order to accurately set the variables, lest they end up equal to 100
/* public void setup() {
* background(255);
* frameRate(1);
* for (int y = 0; y < windowHeight; y++) { // For each row,
* for (int x = 0; x < windowWidth; x++) { // For each element in the current row,
* currentGeneration[x][y] = (int) random(0, 2); // Set element (cell) equal to either 0 or 1 (on or off)
* }
* }
* } */
public void setup() {
background(255);
frameRate(1);
for (int y = 0; y < windowHeight; y++) { // For each row,
for (int x = 0; x < windowWidth; x++) { // For each element in the current row,
currentGeneration[x][y] = 0; // Set element (cell) equal to either 0 or 1 (on or off)
}
}
currentGeneration[25][25] = 1;
currentGeneration[25][26] = 1;
currentGeneration[25][27] = 1;
currentGeneration[26][27] = 1;
currentGeneration[27][26] = 1;
}
public void draw() {
numRectWidth = width / rectSideLength;
numRectHeight = height / rectSideLength;
displayCurrentGeneration();
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
fill(255, 20, 147);
textSize(30);
text(generation, 20, 30);
textSize(10);
text("25,25", 625, 645);
text("24,27", 600, 695);
text(generation, 580, 695);
generation++;
generateNextGeneration();
}
public void displayCurrentGeneration() {
background(255);
for (int y = 0; y < 950; y++) { // For each row,
for (int x = 0; x < 1920; x++) { // For each element in the current row,
if (currentGeneration[x][y] == 0) { // If element equals zero, make rectangle white
fill(255);
stroke(0);
} else if (currentGeneration[x][y] == 1) { // If element equals one, make rectangle black
fill(0);
stroke(255);
} else {
out.println("Inappropriate value for currentGeneration[" + x + "][" + y + "]. Value: "
+ currentGeneration[x][y] + ", generation: " + generation);
}
rect(x * rectSideLength, y * rectSideLength, rectSideLength, rectSideLength); // Display rectangle (cell)
}
}
// out.println("Generation " + generation);
}
public void generateNextGeneration() {
out.println("Generating gen " + generation);
for (int y = 1; y < numRectHeight - 1; y++) { // For each row,
for (int x = 1; x < numRectWidth - 1; x++) { // For each element in the current row,
sumOfNeighbors = 0;
sumOfNeighbors = getSumOfNeighbors(x, y);
if (sumOfNeighbors != 2 && sumOfNeighbors != 3) { // Death
nextGeneration[x][y] = 0;
} else if (sumOfNeighbors == 3 && currentGeneration[x][y] == 0) { // Birth
nextGeneration[x][y] = 1;
} else if ((sumOfNeighbors == 2 || sumOfNeighbors == 3) && currentGeneration[x][y] == 1) { // Stasis
nextGeneration[x][y] = 1;
}
}
}
currentGeneration = nextGeneration.clone();
}
public int getSumOfNeighbors(int xAxis, int yAxis) {
temporarySumOfNeighbors = 0;
for (int i = -1; i < 2; i++) {
for (int j = -1; j < 2; j++) {
if (xAxis == 24 && yAxis == 27 && j != 0 && i != 0) {
out.println("X" + j + ", Y" + i + ":: " + currentGeneration[xAxis + j][yAxis + i]);
} else if (xAxis == 24 && yAxis == 27 && j == 0 && i != 0) {
out.println("X" + ", Y" + i + ":: " + currentGeneration[xAxis + j][yAxis + i]);
} else if (xAxis == 24 && yAxis == 27 && j != 0 && i == 0) {
out.println("X" + j + ", Y" + ":: " + currentGeneration[xAxis + j][yAxis + i]);
} else if (xAxis == 24 && yAxis == 27 && j == 0 && i == 0) {
out.println("X" + ", Y" + ":: " + currentGeneration[xAxis + j][yAxis + i]);
}
temporarySumOfNeighbors += currentGeneration[xAxis + j][yAxis + i];
}
}
temporarySumOfNeighbors -= currentGeneration[xAxis][yAxis];
if (temporarySumOfNeighbors > 8) {
out.println("temporarySumOfNeighbors > 8: " + temporarySumOfNeighbors);
}
if (xAxis == 24 && yAxis == 27) {
out.println("Generation: " + generation + "- " + xAxis + ", " + yAxis + ": " + temporarySumOfNeighbors);
}
return temporarySumOfNeighbors;
}
}
http://pastebin.com/GH51hXzJ
I am a beginner attempting to code the Game of Life, and I am unsure how to find the source of my issues. I set the game to just start with a simple glider in setup, and believe I may have found the effects of the issue.
I put markers on the cells to help track them. If you watch cell (24,27) you will see at least an example of the issue. In the console, I print out the neighborhood of that cell throughout the run of the program. It appears to somehow detect the neighborhood that (24,27) will have in generation 2 in generation 1, and vice versa (assuming that the first generation is generation 0). I am unsure how to explain it, but if you examine the console output and look at the neighborhoods, you see that it detects generation 2's neighborhood in generation 1 and vice versa. That's why when (24,27) has 3 neighbors in generation 1, it only comes to life in generation 3 while in generation 2, it only has 2 neighbors.
Please let me know if you have any questions, I find it difficult to explain my problem.
The issue is explained more here: http://imgur.com/gallery/iRc07/new
Thank you
This is the main source of your problem:
currentGeneration = nextGeneration.clone();
You might think that line will copy everything from nextGeneration into currentGeneration, and it does... but not in the way you're thinking it does.
The nextGeneration variable is a 2D array. In other words, it's an array of arrays. In other other words, the values contained by nextGeneration are arrays.
When you call the clone() function of an array, it copies the values of the old array into a new array. There's your problem: your values are arrays. So it's copying the arrays, not the values inside those second arrays.
Because of that, both nextGeneration and currentGeneration are pointing to the same arrays. So now when you calculate the next generation, you're changing the arrays of the current generation. This doesn't work, since the Game of Life calculation requires two separate arrays.
In other words, you're making a shallow copy of the arrays.
This might be easier to explain with a simpler program:
public class Test {
public static void main(String... args){
//create an array
int[][] array = {{1, 2, 3}, {4, 5, 6}};
//clone the array
int[][] arrayTwo = array.clone();
//change the original array
array[0][0] = 99;
//second array has also changed!
System.out.println(arrayTwo[0][0]);
}
}
Long story short: You should almost never use the clone() function.
You could fix your problem by making a deep copy of the array. There are libraries that handle this for you, or you could use serialization, or just write your own nested for loop.
But an even simpler (and I would argue more correct) solution would be: stop using class-level variables when you don't need them.
The clone() problem wouldn't be a problem, except you're using nextGeneration as a class-level variable. This means that it retains its value between calls to generateNextGeneration(). And since that value is pointing to the arrays inside currentGeneration, that's causing all of the problems.
You already handle this issue with your other variables: notice how you're resetting the sumOfNeighbors and temporarySumOfNeighbors before you use them. You could do the same thing with the nextGeneration variable.
But I would go a step further and get rid of all three of those class-level variables. Move their declarations to inside the functions that use them, that way you don't have to worry about them maintaining their values between function calls.
Two more notes while I'm at it:
You shouldn't really call Thread.sleep() from the draw() function (or any event function). Just set the frame rate and let Processing handle the timing for you.
You're using a ton of cells that you aren't drawing. Your array is 1920x950, but you're only drawing a small percentage of those cells. That's wasting a ton of CPU time on cells you never show. Like I said in your other question, you need to be more careful about distinguishing between pixel coordinates and array coordinates.
Anyway, this was a good question. I think you're getting closer. You just need to get rid of those extra cells and you'll be in pretty good shape. Good luck.
PS: I'm going to add a processing tag to your question. If you have any questions in the future, it's probably a good idea to make sure to include this tag. Otherwise I won't see it. :p
I'm having difficulty with a HackerRank Challenge. My code runs for most cases, but fails others.
The challenge is to find the Max Sum in a 2D array in the shape of an hour-glass that spans a 6 x 6 array. With constraints being integer values of -9 to +9.
Example:
0 2 4 5 1 2
0 2 3 3 2 0
1 4 0 8 6 4 With 8 6 4
0 2 1 4 7 1 7 = 8 + 6 + 4 + 7 + 6 + 2 + 7 = 40
5 0 3 6 2 7 6 2 7
6 3 2 2 0 1
When I run my code with negative integers, I have a return statement of 0.
Here is my code:
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
public class Solution {
public static int maxSumValue;
public static int y;
public static int maxSumHolder;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int arr[][] = new int[6][6];
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 6; j++) {
arr[i][j] = in.nextInt();
}
}
for (int x = 0; x < 4; x++) {
for (int y = 0; y < 4; y++){
maxSumHolder = arr[x][y] + arr[x][y + 1] + arr[x][y + 2]
+ arr[x + 1][y + 1] + arr[x + 2][y] + arr[x + 2][y + 1] + arr[x + 2][y + 2];
if (maxSumHolder > maxSumValue || maxSumHolder == maxSumValue){
maxSumValue = maxSumHolder;
}
}
}
System.out.println(maxSumValue);
}
}
Any suggestions, hints, and/or solutions are welcomed!
You said you were interested in alternative solutions. Here is one that makes heavy use of Java 8 streams, for your interest. It's a lot longer (and less efficient) than your solution but arguably encapsulates the logic rather than having it embedded in the array calculations.
class Position {
public static final int SIZE = 6;
private final int row;
private final int col;
private Position(int row, int col) {
this.row = row;
this.col = col;
}
public static Stream<Position> all() {
return IntStream.range(0, SIZE).boxed()
.flatMap(row -> IntStream.range(0, SIZE)
.mapToObj(col -> new Position(row, col)));
}
public static Stream<Position> allNonEdge() {
return all().filter(Position::notOnEdge);
}
private boolean notOnEdge() {
return row > 0 && col > 0 && row < SIZE - 1 || col < SIZE - 1;
}
public int shapeSum(int[][] array) {
return all().filter(this::isInShape)
.mapToInt(pos -> pos.getVal(array))
.sum();
}
private boolean isInShape(Position other) {
int rowdiff = Math.abs(this.row - other.row);
int coldiff = Math.abs(this.col - other.col);
return rowdiff == 0 && coldiff == 0 || rowdiff == 1 && coldiff <= 1;
}
public int getVal(int[][] array) {
return array[row][col];
}
public void setVal(int[][] array, int val) {
array[row][col] = val;
}
}
And here is some code showing how it can be used:
Random rand = new Random();
int[][] array = new int[Position.SIZE][Position.SIZE];
Position.all().forEach(pos -> pos.setVal(array, rand.nextInt(100)));
Position.allNonEdge()
.mapToInt(pos -> pos.shapeSum(array))
.max()
.ifPresent(System.out::println);
The problem seems to be occurring because if negative values are being added, then it'll never be greater than the original value of maxSumValue, which starts off as zero (Java will initialize it to zero by default since it was never initialized to anything). A simple fix here is to just take the absolute value of maxSumHolder when comparing it to maxSumValue so that negative values will be taken into account. This,
if (maxSumHolder > maxSumValue || maxSumHolder == maxSumValue)
should be changed to
if (Math.abs(maxSumHolder) > maxSumValue || Math.abs(maxSumHolder) == maxSumValue)
However, if you're objective is not to find the sum with the greatest magnitude and you do feel that a smaller positive sum holds greater weight that a huge negative sum, then my suggestion would be to initialize maxSumValue to the smallest possible number Java can hold. Change
public static int maxSumValue;
to
public static int maxSumValue = -Integer.MAX_VALUE;
I am stuck on the coin denomination problem.
I am trying to find the lowest number of coins used to make up $5.70 (or 570 cents). For example, if the coin array is {100,5,2,5,1} (100 x 10c coins, 5 x 20c, 2 x 50c, 5 x $1, and 1 x $2 coin), then the result should be {0,1,1,3,1}
At the moment the coin array will consist of the same denominations ( $2, $1, 50c, 20c, 10c)
public static int[] makeChange(int change, int[] coins) {
// while you have coins of that denomination left and the total
// remaining amount exceeds that denomination, take a coin of that
// denomination (i.e add it to your result array, subtract it from the
// number of available coins, and update the total remainder). –
for(int i= 0; i< coins.length; i++){
while (coins[i] > 0) {
if (coins[i] > 0 & change - 200 >= 0) {
coins[4] = coins[4]--;
change = change - 200;
} else
if (coins[i] > 0 & change - 100 >= 0) {
coins[3] = coins[3]--;
change = change - 100;
} else
if (coins[i] > 0 & change - 50 >= 0) {
coins[2] = coins[2]--;
change = change - 50;
} else
if (coins[i] > 0 & change - 20 >= 0) {
coins[1] = coins[1]--;
change = change - 20;
} else
if (coins[i] > 0 & change - 10 >= 0) {
coins[0] = coins[0]--;
change = change - 10;
}
}
}
return coins;
}
I am stuck on how to deduct the values from coins array and return it.
EDIT: New code
The brute force solution is to try up to the available number of coins of the highest denomination (stopping when you run out or the amount would become negative) and for each of these recurse on solving the remaining amount with a shorter list that excludes that denomination, and pick the minimum of these. If the base case is 1c the problem can always be solved, and the base case is return n otherwise it is n/d0 (d0 representing the lowest denomination), but care must be taken to return a large value when not evenly divisible so the optimization can pick a different branch. Memoization is possible, and parameterized by the remaining amount and the next denomination to try. So the memo table size would be is O(n*d), where n is the starting amount and d is the number of denominations.
So the problem can be solved in pseudo-polynomial time.
The wikipedia link is sparse on details on how to decide if a greedy algorithm such as yours will work. A better reference is linked in this CS StackExchange question. Essentially, if the coin system is canonical, a greedy algorithm will provide an optimal solution. So, is [1, 2, 5, 10, 20] canonical? (using 10s of cents for units, so that the sequence starts in 1)
According to this article, a 5-coin system is non-canonical if and only if it satisfies exactly one of the following conditions:
[1, c2, c3] is non-canonical (false for [1, 2, 5])
it cannot be written as [1, 2, c3, c3+1, 2*c3] (true for [1, 2, 5, 10, 20])
the greedyAnswerSize((k+1) * c4) > k+1 with k*c4 < c5 < (k+1) * c4; in this case, this would require a k*10 < 20 < (k+1)*10; there is no integer k in that range, so this is false for [1, 2, 5, 10, 20].
Therefore, since the greedy algorithm will not provide optimal answers (and even if it did, I doubt that it would work with limited coins), you should try dynamic programming or some enlightened backtracking:
import java.util.HashSet;
import java.util.PriorityQueue;
public class Main {
public static class Answer implements Comparable<Answer> {
public static final int coins[] = {1, 2, 5, 10, 20};
private int availableCoins[] = new int[coins.length];
private int totalAvailable;
private int totalRemaining;
private int coinsUsed;
public Answer(int availableCoins[], int totalRemaining) {
for (int i=0; i<coins.length; i++) {
this.availableCoins[i] = availableCoins[i];
totalAvailable += coins[i] * availableCoins[i];
}
this.totalRemaining = totalRemaining;
}
public boolean hasCoin(int coinIndex) {
return availableCoins[coinIndex] > 0;
}
public boolean isPossibleBest(Answer oldBest) {
boolean r = totalRemaining >= 0
&& totalAvailable >= totalRemaining
&& (oldBest == null || oldBest.coinsUsed > coinsUsed);
return r;
}
public boolean isAnswer() {
return totalRemaining == 0;
}
public Answer useCoin(int coinIndex) {
Answer a = new Answer(availableCoins, totalRemaining - coins[coinIndex]);
a.availableCoins[coinIndex]--;
a.totalAvailable = totalAvailable - coins[coinIndex];
a.coinsUsed = coinsUsed+1;
return a;
}
public int getCoinsUsed() {
return coinsUsed;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder("{");
for (int c : availableCoins) sb.append(c + ",");
sb.setCharAt(sb.length()-1, '}');
return sb.toString();
}
// try to be greedy first
#Override
public int compareTo(Answer a) {
int r = totalRemaining - a.totalRemaining;
return (r==0) ? coinsUsed - a.coinsUsed : r;
}
}
// returns an minimal set of coins to solve
public static int makeChange(int change, int[] availableCoins) {
PriorityQueue<Answer> queue = new PriorityQueue<Answer>();
queue.add(new Answer(availableCoins, change));
HashSet<String> known = new HashSet<String>();
Answer best = null;
int expansions = 0;
while ( ! queue.isEmpty()) {
Answer current = queue.remove();
expansions ++;
String s = current.toString();
if (current.isPossibleBest(best) && ! known.contains(s)) {
known.add(s);
if (current.isAnswer()) {
best = current;
} else {
for (int i=0; i<Answer.coins.length; i++) {
if (current.hasCoin(i)) {
queue.add(current.useCoin(i));
}
}
}
}
}
// debug
System.out.println("After " + expansions + " expansions");
return (best != null) ? best.getCoinsUsed() : -1;
}
public static void main(String[] args) {
for (int i=0; i<100; i++) {
System.out.println("Solving for " + i + ":"
+ makeChange(i, new int[]{100,5,2,5,1}));
}
}
}
You are in wrong direction. This program will not give you an optimal solution. To get optimal solution go with dynamic algorithms implemented and discussed here. Please visit these few links:
link 1
link 2
link 3
The question is not tied to a specific programming language, but rather to minimalistic code and abstraction.
I have this array of 3 rows and 3 columns - imagine a board in which you'd play Tic-Tac-Toe (or naughts and crosses).
When a key(on the Phone) is pressed a value of 0 or 1 is added to the array(1 for X and 0 for O) in the position corresponding to the key pressed(key 9 being board[2][2]).
In building the GUI, I need to map the array coordinates to pixels, such that if:
[0][0] - 10,10
[0][1] - 10,50
[0][2] - 10,90
...
[2][2] - 90,90
the drawing will take place while traversing the array in a nested loop, but I got stuck on how to write in fewest lines of code as possible the mapping between 0 = 10, 1 = 50 and 2 = 90.
One way to go would be to use a switch for each case. Another would be using an if.
Any other ideas to write this in fewer possible lines?
Thanks!
for ( y = 0; y < 3; ++y )
{
for ( x = 0; x < 3; ++x )
{
pos_x = x * 40 + 10;
pos_y = y * 40 + 10;
// Draw...
}
}
for(var i = 0; i < 3; i++) {
for(var j = 0; j < 3; j++) {
int xPos = i * 40 + 10;
int yPos = j * 40 + 10;
//set accordingly
}
}
Use your index value as multiplicator i.e. 90 = 2 * 40 + 10, 50 = 1 * 40 + 10