For my Mastermind Game I am using 6 numbers instead of 6 colours. Also instead of showing black and white pegs, just 2 sentences are outputted. One reads:
"The number of correct digits in the right position is __ "(black pegs/bothRight)
"The number of correct digits in the wrong position is __ "(white pegs/numberRight)
For the 4 digit guesses that are submitted, I am using an array called guessArr, which accepts 4 values from 4 input boxes.
guess0 = Integer.parseInt(firstInput.getText());
guess1 = Integer.parseInt(secondInput.getText());
guess2 = Integer.parseInt(thirdInput.getText());
guess3 = Integer.parseInt(fourthInput.getText());
//New array to arrange guesses
int[] guessArr = new int[] {guess0,guess1,guess2,guess3};
For the answer generated by the computer,
//Create a 4 digit code made of random numbers between 1 and 6
answerArr[0]=(int)(Math.random()*6+1);
answerArr[1]=(int)(Math.random()*6+1);
answerArr[2]=(int)(Math.random()*6+1);
answerArr[3]=(int)(Math.random()*6+1);
Finding the amount of black pegs is easy:
//Calculate number of correct digits in correct position
for (int i = 0; i < 4; ++i)
{
if (answerArr[i] == guessArr[i])
{
used[i] = true;
bothRight++;
}
}
EDIT
I've Solved It!
// Calculate number of correct numbers in wrong position
//Declare variables for what digits are in the answer
Integer digit1 = 0, digit2 = 0, digit3 = 0, digit4 = 0, digit5 = 0 , digit6 = 0;
//Find what the answer digits are
for (int k = 0; k < answerArr.length; ++k){
if (answerArr [k] == 1)
{
digit1++;
}
if (answerArr [k] == 2)
{
digit2++;
}
if (answerArr [k] == 3)
{
digit3++;
}
if (answerArr [k] == 4)
{
digit4++;
}
if (answerArr [k] == 5)
{
digit5++;
}
if (answerArr [k] == 6)
{
digit6++;
}
}
//Declare variables for what digits are in the answer
Integer gDigit1 = 0, gDigit2 = 0, gDigit3 = 0, gDigit4 = 0, gDigit5 = 0 , gDigit6 = 0;
//Find the guess numbers submitted
for (int p = 0; p < guessArr.length; ++p){
if (guessArr [p] == 1)
{
gDigit1++;
}
else if (guessArr [p] == 2)
{
gDigit2++;
}
else if (guessArr [p] == 3)
{
gDigit3++;
}
else if (guessArr [p] == 4)
{
gDigit4++;
}
else if (guessArr [p] == 5)
{
gDigit5++;
}
else if (guessArr [p] == 6)
{
gDigit6++;
if (gDigit6 == 0)
{
gDigit6++;
}
}
//Find the value of correct numbers submitted in the guess
Integer correctNumbers = Math.min (digit1, gDigit1) + Math.min (digit2, gDigit2) + Math.min (digit3, gDigit3) +
Math.min (digit4, gDigit4) + Math.min (digit5, gDigit5) + Math.min (digit6, gDigit6);
//Calculate value of numberRight
numberRight = (correctNumbers - bothRight);
}
Any help would be greatly appreciated. :D Thanks.
First, I'll say up front, I'm not going to give you any code since this is either a learning exercise, so you can learn the language, or else this is a class problem.
So, lets think about this logically... One way you can you can solve this is by counting the number of a type of colors.
As an example, suppose the player guessed 2 blues, and 2 greens, and the answer has 1 blue, 1 red, and two greens.
The player guessed 3 of the right colors, so you would give them 3 white pegs UNLESS they got some in the right spot. Now, suppose that they got one of those blues in the right spot, that means they have 1 black peg, which replaces a white peg. So, the grand total is 2 white pegs, and 1 black peg.
So, to find the number of "Correct Colors" you should check each color (good chance for a loop?) and compare the number of each color that the player guessed, to the number of each color that the solution has.
Put another way, you don't want to compare the guess to the answer. You want to compare the count for each color on the guess, to the count of each color on the solution.
Then, you get "White pegs" by this pesudo-code:
int whitePegs=correctColors-blackPegs;
Edit 1: Comparing answers one color at a time
If you're going to hold the count for each color, then you're going to want to use two arrays, one for the guess, and one for the solution. Each element in the array will hold the count for the color, like this:
r=red, o=orange, y=yellow, etc.
R O Y G B
Guess: [0][2][1][1][0] (Total is 4, for 4 pegs
Actual: [1][1][2][0][0] (Total is 4) for 4 pegs
Matches:[0][1][1][0][0] (Total is 2) This is "correctColors" from above
Related
I am doing a question on leetcode, 66. Plus One.
You are given a large integer represented as integer array digits, where each digits[i] is the ith digit of the integer. The digits are ordered from most significant to least significant in left-to-right order. The large integer does not contain any leading 0's.
Increment the large integer by one and return the resulting array of digits.
Example 1
Input: digits = [1,2,3]
Output: [1,2,4]
Explanation: The array represents the integer 123.
Incrementing by one gives 123 + 1 = 124.
Thus, the result should be [1,2,4].
My solution is:
class Solution {
public int[] plusOne(int[] digits) {
int num = 0;
for (int a : digits) {
num = 10*num + a;
}
int n=num+1;
String str=String.valueOf(n);
int arr[]=new int[str.length()];
for(int i=0;i<str.length();i++){
arr[i]=str.charAt(i)-'0';
}
return arr;
}
}
I am getting many test cases failed, one being:
Input:
[9,8,7,6,5,4,3,2,1,0]
Output:
[1,2,8,6,6,0,8,6,1,9]
Expected:
[9,8,7,6,5,4,3,2,1,1]
Can anyone help me with it?
Think before you leap. And consider the edges.
Why would they do the seemingly idiotic move of storing an number, digit by digit, in an int array? Makes no sense, right?
Except... computers aren't magic. int can't represent any number. A computer's storage is not infinite. Specifically, an int covers 32 bits (4 bytes), and thus can only represent at most 2^32 different numbers. int 'uses' its alloted space of 2^32 by dividing it evenly amongst positive and negative numbers, but negative numbers get one more (because the '0' is in the positive space). In other words, all numbers from -2^31 to +2^31-1, inclusive.
9876543210 is larger than that.
You're trying to turn that array of digits into an int and that is a dead end. Once you do that, you get wrong answers and there is no fixing this. your algorithm is wrong. You can figure this stuff out, and you should always do that with leetcode-style problems, by first carefully reading the assignment. The assignment covers the limits. It says how large these arrays can be, and I'm sure it says that they can be quite large; large enough that the number inside it is larger than 2^31-1. Probably larger than 2^63-1 (which a long can reach).
Then you know the algorithm you need to write can't involve 'turn it into an int first'. That's usually the point (many problems are trivial if small, but become interesting once you make things large).
The algorithm they want you to write must not involve any conversion whatsoever. Increment the array in place. This isn't hard (just think about it: without converting anything, how do you turn [1, 2, 3] into [1, 2, 4]? That should be simple. Then think about how to deal with [1, 9, 9]. Finally, think about how to deal with [9, 9, 9]. Then you've covered all the cases and you have your answer.
In continuation to the detailed explanation of rzwitserloot, in case you are interested in code for the problem.
class Solution {
public int[] plusOne(int[] digits) {
int size = digits.length;
int i=0;
for(i = size-1 ; i >= 0 ; i--){
if (digits[i] != 9) {
digits[i] += 1;
break;
} else {
digits[i] = 0;
}
}
if(i == -1) {
int[] newDigits = new int[size+1];
newDigits[0] = 1;
return newDigits;
}
return digits;
}
}
This is a pretty trivial task, but in some test cases the value is too high to represent even as long, so the best candidate is BigInteger.
public int[] plusOne(int[] digits) {
BigInteger val = BigInteger.ZERO;
for (int i = 0; i < digits.length; i++)
val = val.multiply(BigInteger.TEN).add(BigInteger.valueOf(digits[i]));
val = val.add(BigInteger.ONE);
String str = val.toString();
digits = str.length() == digits.length ? digits : new int[str.length()];
for (int i = 0; i < digits.length; i++)
digits[i] = str.charAt(i) - '0';
return digits;
}
P.S. Sure, you can do this without BigInteger.
public int[] plusOne(int[] digits) {
boolean carry = true;
for (int i = digits.length - 1; carry && i >= 0; i--) {
carry = digits[i] == 9;
digits[i] = carry ? 0 : digits[i] + 1;
}
if (carry) {
int[] tmp = new int[digits.length + 1];
tmp[0] = 1;
System.arraycopy(digits, 0, tmp, 1, digits.length);
digits = tmp;
}
return digits;
}
Think about a mileage counter in a car. How does it work?
Whenever a 9 turns around, it turns the number left to it too.
So for incrementing by one, you'd start from the right, increment by one and if you incremented it to a 10, set it to a 0 instead and continue with the next digit to the left. If you reached the leftmost digit and still didnt finish, add a 1 to the left and set everything else to 0.
Example:
8
9 <- incremented rightmost
10 <- 9 turned to a 10, leftmost digit reached, add a 1 to the left and set everything else to 0
...
18
19 <- incremented rightmost
20 <- 9 turned to a 10, set to 0 instead, increment the next one to the left (1 -> 2), finished
...
108
109 <- incremented rightmost
110 <- 9 turned to a 10, set to 0 instead, increment the next one to the left (1 -> 2), finished
...
998
999 <- incremented rightmost
1000 <- 9 turned to a 10, set to 0 instead, increment the next one to the left, turned to a 10 too, set to 0 instead, ...
import java.util.stream.Collectors;
import java.util.stream.IntStream;
class Scratch {
public static void main(String[] args) {
int[] digits = new int[0];
for (int i = 0; i < 100; i++) {
digits = plusOne(digits);
System.out.println(IntStream.of(digits).mapToObj(Integer::toString).collect(Collectors.joining()));
}
}
public static int[] plusOne(int[] digits) {
boolean finished = false;
for (int i = digits.length - 1; !finished && i >= 0; i--) {
if (++digits[i] % 10 == 0) {
digits[i] = 0;
} else {
finished = true;
}
}
if (!finished) {
// not finished after exiting the loop: every digit was turned from a 9 to a 10 -> we need one digit more
// initialize a new array with a length of 1 more digit, set the leftmost (index 0) to 1 (everything else is 0 by default)
digits = new int[digits.length + 1];
digits[0] = 1;
}
return digits;
}
}
plus one in leetcode solve on dart language
class Solution {
List<int> plusOne(List<int> digits) {
for(int i=digits.length - 1; i>=0; i--){
if(digits[i] < 9){
++digits[i];
return digits;
}
digits[i]=0;
}
List<int> ans = List.filled(digits.length+1, 0);
ans[0]=1;
return ans;
}
}
Here is my solution:
Runtime: 0 ms, faster than 100.00% of Java online submissions for Plus One.
Memory Usage: 40.8 MB, less than 92.31% of Java online submissions for Plus One. for Plus One.
public int[] plusOne(int[] digits) {
for(int i=digits.length-1;i>=0;i--) {
if(digits[i]<9) {
digits[i]=digits[i]+1;
return digits;
}else {
digits[i]=0;
if(i==0) {
digits= new int[digits.length+1];
digits[0]=1;
}
}
}
return digits;
}
My solution:
Runtime: 0 ms, Memory Usage: 2.1 MB,
play.golang link: https://go.dev/play/p/Vm28BdaIi2x
// function to add one digit based on diff scenarios
func plusOne(digits []int) []int {
i := len(digits) - 1
// while the index is valid and the value at [i] ==
// 9 set it as 0 and move index to previous value
for i >= 0 && digits[i] == 9 {
digits[i] = 0
i--
}
if i < 0 {
//leveraging golang's simplicity with append internal method for array
return append([]int{1}, digits...)
} else {
digits[i]++
}
return digits
}
The Question was:
You are given a binary matrix (i.e. each element of matrix is either 0 or 1) of size n × n. You want to re-arrange 1's in such a way that they form a rectangular region. Note that the rectangular region should be made of only 1's, and all the 1's of the entire matrix should be in this rectangular region.
For achieving rectangular region, you can swap any two elements of the matrix. Please find out the minimum number of swaps needed. If it is not possible to re-arrange 1's in the desired way, please print -1.
Input
First line of the input contains a single integer T denoting number of test cases.
Description of T test cases follows.
First line of each test case will contain a single integer n denoting dimension of matrix.
Each of next n lines will contain n space separated integers denoting the ith row of the matrix.
Output
For each test case, print a single line containing a single integer denoting minimum number of swaps needed or -1 depending on the situation.
Example
Input:
2
2
0 1
1 0
2
1 1
1 0
Output:
1
-1
Explanation
Example case 1. You can swap 1 of second row first column with 0 of first row first column.
After the swap, matrix will look as follows.
1 1
0 0
Here all the 1's form a rectangular region of dimension 1 × 2. In this case, 1 swap will be needed.
Note that you can also swap 1 at first row second column with 0 at second row second column too.
Matrix after this swap will be following.
0 0
1 1
So you need 1 swap in this case too.
So overall, you need 1 swap.
Example case 2. There is no way to create a rectangular region containing 3 1's in a matrix of dimension 2 × 2, hence answer is -1.
My Algorithm [Edit]
First i am Taking Number of Cases from user
Then the order of matrix [will be of nxn order].
So logic is that if matrix is 1x1 then it will simply print 0
else while taking input from user [that will be only 1 or 0] i am counting 1's because the logic i develop that when in a matrix of odd order the 1's will be even then it cannot be arranged in rectangular form.and for even order of matrix if 1's are odd , not arrange able .
Next i am traversing each index if i find one then i move to next element else i try to find 1 in the same colomn if dont find than i am breaking loop showing -1 that it is not arrange able in rectangular form
Than after arranging a row i check the next row whether it is already arranged or not if it is than i break everything and moves to next case
n rectangular form
My Solution
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Main {
static long startTime;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int numberOfOnes = 0;
int T = scanner.nextInt();
for (int t = 1; t <= T; t++) {
int n = scanner.nextInt();
int loopCounter, swapCounter = 0;
boolean rowContainsZero = false;
int array[][] = new int[n][n];
boolean reject = true;
//Worst and the most simpler conditions
if (n == 1) {
System.out.print("0");
exitingSystem();
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
array[i][j] = scanner.nextInt();
if (array[i][j] == 1) {
numberOfOnes++;
}
}
}
if (n % 2 == 0 && numberOfOnes % 2 != 0) {
System.out.println("-1");
if (t == T) {
exitingSystem();
}
continue;
} else if (n % 2 != 0 && numberOfOnes % 2 == 0) {
System.out.println("-1");
if (t == T) {
exitingSystem();
}
continue;
}
// System.out.println("Here i am");
//From here swaping processes will take the place
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (array[i][j] == 1) {
continue;
} else if (array[i][j] == 0) {
loopCounter = i;
reject = true;
while (loopCounter < n) {
if (array[loopCounter][j] == 1) {
int temp = array[loopCounter][j];
array[loopCounter][j] = array[i][j];
array[i][j] = temp;
reject = false;
swapCounter += 1;
break;
}
loopCounter++;
}
if (rowContainsZero) {
System.out.println("" + swapCounter);
break;
}
if (reject == true) {
System.out.println("-1");
break;
} else {
for (int m = i + 1; m < n; m++) {
for (int k = 0; k < n; k++) {
if (array[m][k] == 0) {
rowContainsZero = true;
} else {
rowContainsZero = false;
break;
}
}
}
}
} else {
System.out.println("0's and 1's were Expected :(");
exitingSystem();
}
}
if (reject == true) {
break;
}
}
}
}
public static void exitingSystem() {
System.exit(0);
}
}
BUT THE CODECHEF COMPUTER SAYING WRONG ANSWER + They allowed to take input from keyboard too
I think your algorithm isn't fully correct.
I think the following is a counter-example for your step 4 / odd order (n=3) and even number of ones (numberOfOnes=4):
1 1 0
1 1 0
0 0 0
This should give 0.
Similar for n=4 and numberOfOnes=3:
1 1 1 0
0 0 0 0
0 0 0 0
0 0 0 0
This should give 0 as well.
I haven't yet deeply analyzed your steps 5 and 6.
Here are some more examples:
1 1 1 0
1 1 0 0
1 1 1 0
1 1 0 0
This should give -1, as from 10 ones you can only form rectangles of the form 2*5 or 1*10, which both don't fit into the 4*4 frame.
1 1 1 0
1 1 0 0
1 1 1 0
1 0 0 0
This should give 1, as by moving the lower-left 1 two palces up and right, you get a 3*3 rectangle.
This is not the way you are trying to solve problem. Suppose you have
0 0 1
0 1 1
0 0 1
This is a perfect example of solveable matrix but you can't simply use random swap and then acquire result. You need to use A* search algorithm with manhatten distance.
Make a priority queue
Define manhatten distance.
Create a function which creates succesors of each board. Like if i have above board then it will give you a collection of boards back:
0 0 1
0 1 1 ==> colection
0 0 1
0 1 1
0 0 1
0 0 1
0 0 1
0 0 1
0 1 1
0 1 0
0 1 1
0 0 1
0 0 1
0 1 1
0 1 0
Description of A:*
an initial lis to store visited boar so that you don't visit them again.
i will call MinPriority queue a pq
`insert the initial_board in pq
while(!pq.isEmpty() && !foundGoal(pq.min)) //You find goal when your
manhatten distance is 0.
board = pq.delMin(); //you have to override the distance method in
priority queue so it will return you that board whoms manhatten
distance is smallest.
for(boards b :board.getSuccesors(); // give you collection of boards.
if(notvisited(b,vistiedList)) // so that you don't come in same state again and
again.
pq.insert(b);
visitedList.add(b);`
In first year i had to solve 8-puzzle and you can solve this way however you can also use hamming distance but that's not efficient and here is 8-puzzle code(with A* implementation).
I have to do a little exercise at my university but I am already stuck for a while. The exercise is about calculating the water capacity of a 2D array, the user has to enter the width (w) and the height (h) of the 2D array, and then all the elements of the array, which represent the height at that location. Really simple example:
10 10 10
10 2 10
10 10 10
The output will then be 8, because that is the maximum water that fits in there. Another example is:
6 4
1 5 1 5 4 3
5 1 5 1 2 4
1 5 1 4 1 5
3 1 3 6 4 1
Output will be 14.
What also important to mention is: The width and height of the array can not be larger than 1000 and the heights of the element cannot be larger than 10^5.
Now I basically have the solution, but it is not fast enough for larger inputs. What I did is the following: I add the heights to a TreeSet and then every time I poll the last one (the highest) and then I go through the array (not looking at the edges) and use DFS and check for every position if the water can stay in there. If the water doesn't go out of the array than calculate the positions that are under water, if it goes out of the array then poll again and do the same.
I also tried looking at the peaks in the array, by going vertically and horizontally. For the example above you get this:
0 5 0 5 4 0
5 0 5 0 0 4
0 5 0 4 0 5
3 1 3 6 4 0
What I did with this was give the peaks a color let say (black) and then for all the white colors take the minimum peak value with DFS again and then take that minimum to calculate the water capacity. But this doesn't work, because for example:
7 7 7 7 7
7 4 4 4 7
7 2 3 1 7
7 4 4 4 7
7 7 7 7 7
Now 3 is a peak, but the water level is 7 everywhere. So this won't work.
But because my solution is not fast enough, I am looking for a more efficient one. This is the part of the code where the magic happens:
while (p.size() != 0 || numberOfNodesVisited!= (w-2)*(h-2)) {
max = p.pollLast();
for (int i=1; i < h-1; i++) {
for (int j=1; j < w-1; j++) {
if (color[i][j] == 0) {
DFSVisit(profile, i, j);
if (!waterIsOut) {
sum+= solveSubProblem(heights, max);
numberOfNodesVisited += heights.size();
for(int x = 0; x < color.length; x++) {
color2[x] = color[x].clone();
}
} else {
for(int x = 0; x < color2.length; x++) {
color[x] = color2[x].clone();
}
waterIsOut = false;
}
heights.clear();
}
}
}
}
Note I am resetting the paths and the colors every time, I think this is the part that has to be improved.
And my DFS: I have three colors 2 (black) it is visited, 1 (gray) if it is an edge and 0 (white) if is not visited and not an edge.
public void DFSVisit(int[][] profile, int i, int j) {
color[i][j] = 2; // black
heights.add(profile[i][j]);
if (!waterIsOut && heights.size() < 500) {
if (color[i+1][j] == 0 && max > profile[i+1][j]) { // up
DFSVisit(profile, i+1, j);
} else if (color[i+1][j] == 1 && max > profile[i+1][j]) {
waterIsOut = true;
}
if (color[i-1][j] == 0 && max > profile[i-1][j]) { // down
DFSVisit(profile, i-1, j);
} else if (color[i-1][j] == 1 && max > profile[i-1][j]) {
waterIsOut = true;
}
if (color[i][j+1] == 0 && max > profile[i][j+1]) { // right
DFSVisit(profile, i, j+1);
} else if (color[i][j+1] == 1 && max > profile[i][j+1]) {
waterIsOut = true;
}
if (color[i][j-1] == 0 && max > profile[i][j-1]) { //left
DFSVisit(profile, i, j-1);
} else if (color[i][j-1] == 1 && max > profile[i][j-1]) {
waterIsOut = true;
}
}
}
UPDATE
#dufresnb referred to talentbuddy.co where the same exercise is given at https://www.talentbuddy.co/challenge/526efd7f4af0110af3836603. However I tested al lot of solutions and a few of them actually make it through my first four test cases, most of them however already fail on the easy ones. Talent buddy did a bad job on making test cases: in fact they only have two. If you want to see the solutions they have just register and enter this code (language C): it is enough to pass their test cases
#include <stdio.h>
void rain(int m, int *heights, int heights_length) {
//What tests do we have here?
if (m==6)
printf("5");
else if (m==3)
printf("4");
//Looks like we need some more tests.
}
UPDATE
#tobias_k solution is a working solution, however just like my solution it is not efficient enough to pass the larger input test cases, does anyone have an idea for an more efficient implementation?
Any ideas and help will be much appreciated.
Here's my take on the problem. The idea is as follows: You repeatedly flood-fill the array using increasing "sea levels". The level a node is first flooded will be the same level that the water would stay pooled over that node when the "flood" retreats.
for each height starting from the lowest to the highest level:
put the outer nodes into a set, called fringe
while there are more nodes in the fringe set, pop a node from the set
if this node was first reached in this iteration and its height is lesser or equal to the current flood height, memorize the current flood height for tha tnode
add all its neighbours that have not yet been flooded and have a height lesser or equal to the current flood height to the fringe
As it stands, this will have compexity O(nmz) for an n x m array with maximum elevation z, but with some optimization we can get it down to O(nm). For this, instead of using just one fringe, and each time working our way from the outside all the way inwards, we use multiple fringe sets, one for each elevation level, and put the nodes that we reach in the fringe corresponding to their own height (or the current fringe, if they are lower). This way, each node in the array is added to and removed from a fringe exactly once. And that's as fast as it possibly gets.
Here's some code. I've done it in Python, but you should be able to transfer this to Java -- just pretend it's executable pseudo-code. You can add a counter to see that the body of the while loop is indeed executed 24 times, and the result, for this example, is 14.
# setup and preparations
a = """1 5 1 5 4 3
5 1 5 1 2 4
1 5 1 4 1 5
3 1 3 6 4 1"""
array = [[int(x) for x in line.strip().split()]
for line in a.strip().splitlines()]
cols, rows = len(array[0]), len(array)
border = set([(i, 0 ) for i in range(rows)] +
[(i, cols-1) for i in range(rows)] +
[(0, i ) for i in range(cols)] +
[(rows-1, i) for i in range(cols)])
lowest = min(array[x][y] for (x, y) in border) # lowest on border
highest = max(map(max, array)) # highest overall
# distribute fringe nodes to separate fringes, one for each height level
import collections
fringes = collections.defaultdict(set) # maps points to sets
for (x, y) in border:
fringes[array[x][y]].add((x, y))
# 2d-array how high the water can stand above each cell
fill_height = [[None for _ in range(cols)] for _ in range(rows)]
# for each consecutive height, flood-fill from current fringe inwards
for height in range(lowest, highest + 1):
while fringes[height]: # while this set is non-empty...
# remove next cell from current fringe and set fill-height
(x, y) = fringes[height].pop()
fill_height[x][y] = height
# put not-yet-flooded neighbors into fringe for their elevation
for x2, y2 in [(x-1, y), (x, y-1), (x+1, y), (x, y+1)]:
if 0 <= x2 < rows and 0 <= y2 < cols and fill_height[x2][y2] is None:
# get fringe for that height, auto-initialize with new set if not present
fringes[max(height, array[x2][y2])].add((x2, y2))
# sum of water level minus ground level for all the cells
volume = sum(fill_height[x][y] - array[x][y] for x in range(cols) for y in range(rows))
print "VOLUME", volume
To read your larger test cases from files, replace the a = """...""" at the top with this:
with open("test") as f:
a = f.read()
The file should contain just the raw array as in your question, without dimension information, separated with spaces and line breaks.
talentbuddy.co has this problem as one of their coding tasks. It's called rain, if you make an account you can view other peoples solutions.
#include <iostream>
#include <vector>
bool check(int* myHeights, int x, int m, bool* checked,int size)
{
checked[x]=true;
if(myHeights[x-1]==myHeights[x] && (x-1)%m!=0 && !checked[x-1])
{
if(!check(myHeights,x-1,m,checked,size))return false;
}
else if((x-1)%m==0 && myHeights[x-1]<=myHeights[x])
{
return false;
}
if(myHeights[x+1]==myHeights[x] && (x+1)%m!=m-1 && !checked[x+1])
{
if(!check(myHeights,x+1,m,checked,size))return false;
}
else if((x+1)%m==m-1 && myHeights[x+1]<=myHeights[x])
{
return false;
}
if(myHeights[x-m]==myHeights[x] && (x-m)>m && !checked[x-m])
{
if(!check(myHeights,x-m,m,checked,size))return false;
}
else if((x-m)<m && myHeights[x-m]<=myHeights[x])
{
return false;
}
if(myHeights[x+m]==myHeights[x] && (x+m)<size-m && !checked[x+m])
{
if(!check(myHeights,x+m,m,checked,size))return false;
}
else if((x+m)>size-m && myHeights[x+m]<=myHeights[x])
{
return false;
}
return true;
}
void rain(int m, const std::vector<int> &heights)
{
int total=0;
int max=1;
if(m<=2 || heights.size()/m<=2)
{
std::cout << total << std::endl;
return;
}
else
{
int myHeights[heights.size()];
for(int x=0;x<heights.size();++x)
{
myHeights[x]=heights[x];
}
bool done=false;
while(!done)
{
done=true;
for(int x=m+1;x<heights.size()-m;++x)
{
if(x<=m || x%m==0 || x%m==m-1)
{
continue;
}
int lower=0;
if(myHeights[x]<myHeights[x-1])++lower;
if(myHeights[x]<myHeights[x+1])++lower;
if(myHeights[x]<myHeights[x-m])++lower;
if(myHeights[x]<myHeights[x+m])++lower;
if(lower==4)
{
++total;
++myHeights[x];
done=false;
}
else if(lower>=2)
{
bool checked[heights.size()];
for(int y=0;y<heights.size();++y)
{
checked[y]=false;
}
if(check(myHeights,x,m,checked,heights.size()))
{
++total;
++myHeights[x];
done=false;
}
}
}
}
}
std::cout << total << std::endl;
return;
}
I have some code that is supposed to find the smallest of the 8 neighboring cells in a 2D array. When this code runs, the smallest is then moved to, and the code run again in a loop. However when it is run the code ends up giving a stack overflow error as it keeps jumping between two points. This seems to be a logical paradox as if Y < X then X !< Y. So it think it is my code at fault, rather than my logic. Here's my code:
private Point findLowestWeight(Point current) {
float lowest = Float.MAX_VALUE;
Point ret = new Point(-1, -1);
LinkedList<Point> pointList = new LinkedList<Point>();
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
if (!(i == 0 && j == 0)) {
if ((current.x + i >= 0 && current.x + i <= imageX - 2)
&& (current.y + j >= 0 && current.y + j <= imageY - 2)) {
pointList.add(new Point(current.x + i, current.y + j));
}
}
}
}
for (Point p : pointList){
if (map[p.x][p.y] < lowest){
lowest = map[p.x][p.y];
ret = p;
}
}
return ret;
}
You need a stopping case.
find the smallest of the 8 neighboring cells in a 2D array. When this code runs, the smallest is then moved to, and the code run again in a loop
is a fine way to start but says nothing about stopping.
Do you care about the value of the current cell? If so you need to check 9 not 8. If you simply want to move down hill then you need to check where you've been or any flat multi-cell valley will put you into an infinite loop. Consider only moving if moving down.
If you truly don't care where you are then even a single cell valley will put you into an infinite loop as you bounce in and out of it. In which case you'd need some other stopping condition. Consider stopping after imageX * imageY iterations.
Do you move even if the smallest neighbour is greater than the value in the center?
Example:
2 2 2 2
2 0 1 2
2 2 2 2
You start with center cell 0. The smallest neighbour is 1. If you move to 1, the smallest neighbour is 0. You can continue endless.
Probably you should not move, if the smallest neighbour is greater than the current cell.
Text File:
2 3
5 5
6 6
3 4
3 4
4 5
5 6
3 3
4 5
For school, one part of a program we had to make was to get "The sum of the scores on the hole that is the highest for all the holes played." Basically, the program had to read from the text file above, and had to display which line had the highest sum. For example, line 1 has a sum of 5, line 2 has a sum of 10, etc. The output should be "12", since line 3 has the highest sum.
What I tried to do was to create two variables: currentSumScore and sumScores. currentSumScore was a test, and sumScores would contain the highest sum.
for (int roundNum = 1; roundNum <= 9; roundNum++)
{
player1Score = in.nextInt();
player2Score = in.nextInt();
currentSumScore = player1Score + player2Score;
if (currentSumScore >= player1Score + player2Score)
{
sumScores = currentSumScore;
}
else
{
sumScores = player1Score + player2Score;
}
}
What I tried doing here was to add the first two numbers of the first line and set that equal to currentSumScore. Then, I put in an if-else. If line 2 had a sum that was greater than line 1, ten sumScores would replace that. I tried this but it is only returning the sum of the last line.
currentSumScore = player1Score + player2Score;
if (currentSumScore >= player1Score + player2Score)
You make currentSumScore to be the sum of player1Score + player2Score, so when it checks the if condition, it will always be true. You need to compare the current sum with the greater value found until then.
currentSumScore = player1Score + player2Score;
if (currentSumScore >= sumScores )
{
//Actual sum is greater than previous
sumScores = currentSumScore;
}
else
{
//Do nothing, this line is not greater than one found before
//This else is not needed
}
And start with a sumScores of a small value so the first line will always be greater (0, -1...)
currentSumScore = player1Score + player2Score;
if (currentSumScore >= player1Score + player2Score)
You are setting currentSumScore = player1Score + player2Score
Then you are saying if it is > OR = to. It is always going to be equal to hence the line before it.
Start with currentSumScore = 0 before reading any of the scores and then check to see if player1Score + player2Score is >, not >=.
You must check against the last value you saved in
sumScores
if (currentSumScore > sumScores) {
sumScores = currentSumScore;
}
And no need to else part. Give this a try, it should work.