Reputation: 2200
I have been struggling with the LeetCode 'Bulls & Cows' challenge for the last day. I am a front-end developer in the process of learning Algorithms, and am having a hard time understanding a block of logic achieved in Java and porting it over to my JavaScript solution.
The working Java Solution:
public String getHint(String secret, String guess) {
int bulls = 0;
int cows = 0;
int[] numbers = new int[10];
for (int i = 0; i<secret.length(); i++) {
int s = Character.getNumericValue(secret.charAt(i));
int g = Character.getNumericValue(guess.charAt(i));
if (s == g) bulls++;
else {
if (numbers[s] < 0) cows++;
if (numbers[g] > 0) cows++;
numbers[s] ++;
numbers[g] --;
}
}
return bulls + "A" + cows + "B";
}
Specifically I am having a difficult time understanding the following block of functionality:
else {
if (numbers[s] < 0) cows++;
if (numbers[g] > 0) cows++;
numbers[s] ++;
numbers[g] --;
}
Here is my JS solution I have derived that is passing all (known) test cases except for secret = 1807
and guess = 7810
:
var getHint = function(secret, guess) {
var bulls = 0;
var cows = 0;
var nums = [];
var checkNums = function(num) {
if(nums.length) {
for (var l = 0; l < nums.length; l++) {
if(num === nums[l]) {
return false;
} else {
nums.push(num);
cows++;
return true;
}
} else {
// /nums/ is equal to 0
cows++;
nums.push(num);
}
}
};
if(guess) {
// iterate over the secret to compare it to the guess
for (var i = 0; i < secret.length; i++) {
// compare the related location to check for bulls
if(secret[i] === guess[i]) {
bulls++;
nums.push(guess[i]);
} else {
// We didnt find a bull, lets check the /guess/ for cows
for(var j = 0; j < guess.length; j++) {
// We have a match, what should we do with it?
if (secret[i] === guess[j]) {
checkNums(guess[j]);
}
}
}
}
}
return bulls + "A" + cows + "B";
};
The failed test case I get is:
Input:
"1807"
"7810"
Output:
"1A2B"
Expected:
"1A3B"
I would love to better understand how I can replicate the elegant Java solution better, as well as any ways I can make this JS solution more succinct (and working). The more I bang my head against this, the more for
loops and if
blocks I wind up writing and I just know I am moving in the wrong direction.
Here is a JSBin of my solution:
http://jsbin.com/jibusa/edit?js,console
Thank you for any help.
Upvotes: 1
Views: 3578
Reputation: 23945
Here is a virtual copy of the Java solution. The little adjustment to the JavaScript charCodeAt()
was to account for its discrepancy with the Java Character.getNumericValue
.
function getHint(secret, guess) {
var bulls = 0;
var cows = 0;
var numbers = new Array(10);
for (var i=0; i<10; i++){
numbers[i] = 0;
}
for (var i = 0; i<secret.length; i++) {
var s = secret.charCodeAt(i) - 48;
var g = guess.charCodeAt(i) - 48;
if (s == g) bulls++;
else {
if (numbers[s] < 0) cows++;
if (numbers[g] > 0) cows++;
numbers[s] ++;
numbers[g] --;
}
}
return bulls + "A" + cows + "B";
}
console.log(getHint("1807","7810"));
Upvotes: 1
Reputation: 65488
numbers[x]
represents the number of unmatched x
s in the prefixes of the secret and the guess scanned so far. Positive numbers indicate a surplus in the secret. Negative numbers indicate a surplus in the guess.
The code block
if (numbers[s] < 0) cows++;
if (numbers[g] > 0) cows++;
numbers[s] ++;
numbers[g] --;
translates to English as follows. If s
, the current letter in the secret, has a surplus in the guess, then it matches a previous letter in the guess, so increment the number of cows. If g
, the current letter in the guess, has a surplus in the secret, then it matches a previous letter in the secret, so increment the number of cows. numbers[s] ++
is very slick: it either erases a surplus letter in the guess or creates a surplus in the secret. Similarly, numbers[g] --
either erases a surplus letter in the secret or creates one in the guess.
Upvotes: 1
Reputation: 455
Why don't you do this?...
var getHint = function(secret, guess) {
var bulls = 0;
var cows = 0;
var nums = [];
var length = 10;
var s;
var g;
for (var i2=0; i2 < length; i2++) {nums[i2] = 0;}
for (var i=0; i < secret.length; i++) {
s = Number(String(secret).charAt(i));
g = Number(String(guess).charAt(i));
if(s == g)bulls++;
else{
if(nums[s] < 0)cows++;
if(nums[g] > 0) cows++;
nums[s]++;
nums[g]--;
}
}
return bulls + "A" + cows + "B";
};
console.log(getHint("1123", "0111"));
console.log(getHint("1807", "7810"));
Ouput:
"1A1B"
"1A3B"
Upvotes: 0