Bulls and Cows game? - java

For those who aren't familiar, the game is a number guessing game, where a number is chosen (non repeating; e.g 1223 is NOT chosen) and the user makes a guess and obtains information whether the number AND digit is correct, number is correct but in a wrong digit, or the number is not contained. http://en.wikipedia.org/wiki/Bulls_and_cows
(e.g number chosen => 1234, guessing 3789 will give 1 cow)
Instead of the computer choosing the number and telling the properties and player guesses, I would like to do the reverse; I type in a number and the properties - the computer gives a list of possible numbers.
Anyways, my method is:
Add all numbers that do not repeat itself to the arraylist
Delete numbers that do not satisfy the conditions.
Here is how the cow cases are done :
//Case 5: property is 4 cows;
if (property.equals("040")) {
//delete if numbers don't appear EXACTLY 4 times
if (contains != 4) { numbers.remove(i); }
//removes if the digits of the number tried corresponds with the actual number (Cow!)
else if (n.charAt(0) == first.charAt(0)) { numbers.remove(i); }
else if (n.charAt(1) == second.charAt(0)) { numbers.remove(i); }
else if (n.charAt(2) == third.charAt(0)) { numbers.remove(i); }
else if (n.charAt(3) == fourth.charAt(0)) { numbers.remove(i); }
}
It has worked for cows. Upon trying to implement bulls, it seems like using this sort of approach won't be possible. How can I do a method for bulls!? Would I need to create four more arraylists and calculate for each case? Or is ArrayList not the way to go?
For example, 1234 with 1bull would mean the number to guess is 1XXX, X2XX, XX3X or XXX4 but
I can't use this approach as it will delete all number except the input.
Thanks.

You can try this algorithm for solving -
String userAnswer = // ... getUserAnswer();
if(userAnswer == null || userAnswer.equals("")
|| !userAnswer.matches("^-?\\d+$")
|| userAnswer.split("(?<=\\G.{1})").length < 4) {
// error
}
int[] secret = (int[])// ... getSecret(request);
int[] seq = {1,2,3,4};
for(int i = 0; i < userAnswer.split("(?<=\\G.{1})").length; i++) {
seq[i] = Integer.parseInt(s[i]);
}
int bullCount = 0;
int cowCount = 0;
for(int i = -1; ++i < secret.length;) {
if(secret[i] == seq[i]) {
bullCount++;
}
}
for(int i = -1; ++i < secret.length;) {
for(int j = -1; ++j < secret.length;) {
if(secret[i] == seq[j] && i != j) {
cowCount++;
}
}
}
String snswer = bullCount + "b" + cowCount + "c";
if(Arrays.equals(secret, seq))
// win!
else
// fail!

It's wrong as if the code is 1634 and the user enters 6113, the program returns 4 cows when there is in fact 3.

Try this:
private static String findNumberOfCowsAndBulls(String firstString, String secondString) {
if(firstString.equals(secondString))
return "All Bulls:" + firstString.length();
char[] fSArr = firstString.toCharArray();
char[] sSArr = secondString.toCharArray();
int countCow = 0;
int countBull = 0;
Map<String, Integer> fSMap = new HashMap<>();
Map<String, Integer> sSMap = new HashMap<>();
for (int i = 0; i < fSArr.length; i++) {
if(i < sSArr.length){
if(fSArr[i] == sSArr[i]){
countBull++;
}
else{
updateMapOfCharsCount(fSMap, fSArr[i]);
updateMapOfCharsCount(sSMap, sSArr[i]);
}
}
else{ //fSArr is bigger than sSArr
updateMapOfCharsCount(fSMap, fSArr[i]);
}
}
if(fSArr.length < sSArr.length){ //fSArr is shorter than sSArr
for(int i = fSArr.length; i < sSArr.length - fSArr.length; i++){
updateMapOfCharsCount(sSMap, sSArr[i]);
}
}
for (Map.Entry<String, Integer> entry : fSMap.entrySet()) {
String key = entry.getKey();
if(sSMap.containsKey(key)){
if(sSMap.get(key) <= fSMap.get(key))
countCow = countCow + sSMap.get(key);
else
countCow = countCow + fSMap.get(key);
}
}
return "countCow = " + countCow + " countBull = " + countBull;
}
private static void updateMapOfCharsCount(Map<String, Integer> fsMap, char c) {
String key1 = String.valueOf(c);
if (fsMap.containsKey(key1)) {
fsMap.put(key1, fsMap.get(key1) + 1);
} else
fsMap.put(key1, 1);
}

Related

Palindrome in java

Here what I tried
sample input is "aabaa"
eg: in if condition val[0] = a[4]
if it is equal i stored it in counter variable if it is half of the length it original string it is palindrome
if it is not it is not a palindrome
I tried with my basic knowledge in java if there is any errors let me know
boolean solution(String inputString) {
int val = inputString.length();
int count = 0;
for (int i = 0; i<inputString.length(); i++) {
if(inputString.charAt(i) == inputString.charAt(val-i)) {
count = count++;
if (count>0) {
return true;
}
}
}
return true;
}
How about
public boolean isPalindrome(String text) {
String clean = text.replaceAll("\\s+", "").toLowerCase();
int length = clean.length();
int forward = 0;
int backward = length - 1;
while (backward > forward) {
char forwardChar = clean.charAt(forward++);
char backwardChar = clean.charAt(backward--);
if (forwardChar != backwardChar)
return false;
}
return true;
}
From here
In your version you compare first element with last, second with second last etc.
last element in this case is inputString.length()-1(so need to use 'inputString.charAt(val-i-1)' . If you iterate till end, then the count should be equal to length of the string.
for(int i = 0; i<inputString.length(); i++){
if(inputString.charAt(i) == inputString.charAt(val-i-1)){
count ++;
}
}
return (count==val); //true when count=val
Or alternatlively iterate till the mid point of the array, then count value is val/2.
for(int i = 0; i<inputString.length()/2; i++){
if(inputString.charAt(i) == inputString.charAt(val-i-1)){
count ++;
}
}
return (count==val/2); //true when count=val/2
There's no constraints in the question so let me throw in a more cheesy solution.
boolean isPalindrome(String in)
final String inl = in.toLowerCase();
return new StringBuilder(inl).reverse().toString().equals(inl);
}
A palindrome is a word, sentence, verse, or even a number that reads the same forward and backward. In this java solution, we’ll see how to figure out whether the number or the string is palindrome in nature or not.
Method - 1
class Main {
public static void main(String[] args) {
String str = "Nitin", revStr = "";
int strLen = str.length();
for (int i = (strLen - 1); i >=0; --i) {
revStr = revStr + str.charAt(i);
}
if (str.toLowerCase().equals(revStr.toLowerCase())) {
System.out.println(str + " is a Palindrome String.");
}
else {
System.out.println(str + " is not a Palindrome String.");
}
Method - 2
class Main {
public static void main(String[] args) {
int n = 3553, revNum = 0, rem;
// store the number to the original number
int orgNum = n;
/* get the reverse of original number
store it in variable */
while (n != 0) {
remainder = n % 10;
revNum = revNum * 10 + rem;
n /= 10;
}
// check if reversed number and original number are equal
if (orgNum == revNum) {
System.out.println(orgNum + " is Palindrome.");
}
else {
System.out.println(orgNum + " is not Palindrome.");
}

I want the string pattern aabbcc to be displayed as 2a2b2c

I have somehow got the output with the help of some browsing. But I couldn't understand the logic behind the code. Is there any simple way to achieve this?
public class LetterCount {
public static void main(String[] args)
{
String str = "aabbcccddd";
int[] counts = new int[(int) Character.MAX_VALUE];
// If you are certain you will only have ASCII characters, I would use `new int[256]` instead
for (int i = 0; i < str.length(); i++) {
char charAt = str.charAt(i);
counts[(int) charAt]++;
}
for (int i = 0; i < counts.length; i++) {
if (counts[i] > 0)
//System.out.println("Number of " + (char) i + ": " + counts[i]);
System.out.print(""+ counts[i] + (char) i + "");
}
}
}
There are 3 conditions which need to be taken care of:
if (s.charAt(x) != s.charAt(x + 1) && count == 1) ⇒ print the counter and character;
if (s.charAt(x) == s.charAt(x + 1)) ⇒ increase the counter;
if (s.charAt(x) != s.charAt(x + 1) && count >= 2) ⇒ reset to counter 1.
{
int count= 1;
int x;
for (x = 0; x < s.length() - 1; x++) {
if (s.charAt(x) != s.charAt(x + 1) && count == 1) {
System.out.print(s.charAt(x));
System.out.print(count);
}
else if (s.charAt(x)== s.charAt(x + 1)) {
count++;
}
else if (s.charAt(x) != s.charAt(x + 1) && count >= 2) {
System.out.print(s.charAt(x));
System.out.print(count);
count = 1;
}
}
System.out.print(s.charAt(x));
System.out.println(count);
}
The code is really simple.It uses the ASCII value of a character to index into the array that stores the frequency of each character.
The output is simply got by iterating over that array and which character has frequency greater than 1, print it accordingly as you want in the output that is frequency followed by character.
If the input string has same characters consecutive then the solution can be using space of O(1)
For example in your string aabbcc, the same characters are consecutive , so we can take advantage of this fact and count the character frequency and print it at the same time.
for (int i = 0; i < str.length(); i++)
{
int freq = 1;
while((i+1)<str.length()&&str.charAt(i) == str.charAt(i+1))
{++freq;++i}
System.out.print(freq+str.charAt(i));
}
You are trying to keep count of the number of times each character is found. An array is referenced by an index. For example, the ASCII code for the lowercase letter a is the integer 97. Thus the count of the number of times the letter a is seen is in counts[97]. After every element in the counts array has been set, you print out how many have been found.
This should help you understand the basic idea behind how to approach the string compression problem
import java.util.*;
public class LetterCount {
public static void main(String[] args) {
//your input string
String str = "aabbcccddd";
//split your input into characters
String chars[] = str.split("");
//maintain a map to store unique character and its frequency
Map<String, Integer> compressMap = new LinkedHashMap<String, Integer>();
//read every letter in input string
for(String s: chars) {
//java.lang.String.split(String) method includes empty string in your
//split array, so you need to ignore that
if("".equals(s))
continue;
//obtain the previous occurances of the character
Integer count = compressMap.get(s);
//if the character was previously encountered, increment its count
if(count != null)
compressMap.put(s, ++count);
else//otherwise store it as first occurance
compressMap.put(s, 1);
}
//Create a StringBuffer object, to append your input
//StringBuffer is thread safe, so I prefer using it
//you could use StringBuilder if you don't expect your code to run
//in a multithreaded environment
StringBuffer output = new StringBuffer("");
//iterate over every entry in map
for (Map.Entry<String, Integer> entry : compressMap.entrySet()) {
//append the results to output
output.append(entry.getValue()).append(entry.getKey());
}
//print the output on console
System.out.println(output);
}
}
class Solution {
public String toFormat(String input) {
char inChar[] = input.toCharArray();
String output = "";
int i;
for(i=0;i<input.length();i++) {
int count = 1;
while(i+1<input.length() && inChar[i] == inChar[i+1]) {
count+=1;
i+=1;
}
output+=inChar[i]+String.valueOf(count);
}
return output;
}
public static void main(String[] args) {
Solution sol = new Solution();
String input = "aaabbbbcc";
System.out.println("Formatted String is: " + sol.toFormat(input));
}
}
def encode(Test_string):
count = 0
Result = ""
for i in range(len(Test_string)):
if (i+1) < len(Test_string) and (Test_string[i] == Test_string[i+1]):
count += 1
else:
Result += str((count+1))+Test_string[i]
count = 0
return Result
print(encode("ABBBBCCCCCCCCAB"))
If you want to get the correct count considering the string is not in alphabetical order. Sort the string
public class SquareStrings {
public static void main(String[] args) {
SquareStrings squareStrings = new SquareStrings();
String str = "abbccddddbd";
System.out.println(squareStrings.manipulate(str));
}
private String manipulate(String str1) {
//convert to charArray
char[] charArray = str1.toCharArray();
Arrays.sort(charArray);
String str = new String(charArray);
StringBuilder stbuBuilder = new StringBuilder("");
int length = str.length();
String temp = "";
if (length > 1) {
for (int i = 0; i < length; i++) {
int freq = 1;
while (((i + 1) < length) && (str.charAt(i) == str.charAt(i + 1))) {
++freq;
temp = str.charAt(i) + "" + freq;
++i;
}
stbuBuilder.append(temp);
}
} else {
return str + "" + 1;
}
return stbuBuilder.toString();
}
}
Kotlin:
fun compressString(input: String): String {
if (input.isEmpty()){
return ""
}
var result = ""
var count = 1
var char1 = input[0]
for (i in 1 until input.length) {
val char2 = input[i]
if (char1 == char2) {
count++
} else {
if (count != 1) {
result += "$count$char1"
count = 1
} else {
result += "$char1"
}
char1 = char2
}
}
result += if (count != 1) {
"$count$char1"
} else {
"$char1"
}
return result
}

Bug or Logical Error

I'm using Netbeans, and I've written a method that's not doing exactly what it should:
private ArrayList<String[]>ProductsInStock;
public void DisplayStock() {
ArrayList<String[]> Sort = new ArrayList<String[]>();
System.out.println("");
for (int i = 0; i < ProductsInStock.size(); i++) {
if (ProductsInStock.get(i)[2].equals(Products.get(ProductCodeCB.getSelectedIndex())[1])) {
boolean foundColor = false;
int size = Sort.size();//Since the size will differ dynamically
for (int k = 0; k < size; k++) {
if (Sort.get(k)[3].equals(ProductsInStock.get(i)[3])) {
foundColor = true;
if (Sort.get(k)[4].equals(ProductsInStock.get(i)[4])) {
String S[] = Sort.get(k);
S[5] = (Integer.parseInt(Sort.get(k)[5]) + Integer.parseInt(ProductsInStock.get(i)[5])) + "";
Sort.set(k, S);
break;
}
if (k == Sort.size() - 1) {
Sort.add(ProductsInStock.get(i));
}
} else if (foundColor == true) {
Sort.add(k, ProductsInStock.get(i));
break;
}
}
System.out.print(ProductsInStock.get(0)[5]+" ");
if (foundColor == false) {
Sort.add(ProductsInStock.get(i));
}
}
}
}
}
The method should NOT change the value of ProductsInStock.get(0)[5], yet it is incrementing it by 1 everytime the method is called, I've placed the "System.out.println()" to show you how the value is actually changing. Here are the results: 1 1 1 1 1 1 1 1 2
And when i added the line "S[5]=ProductsInStock.get(i)[5];", the result changed to: 1 1 1 1 1 1 1 1 1 (as it should be):
public void DisplayStock() {
ArrayList<String[]> Sort = new ArrayList<String[]>();
System.out.println("");
for (int i = 0; i < ProductsInStock.size(); i++) {
if (ProductsInStock.get(i)[2].equals(Products.get(ProductCodeCB.getSelectedIndex())[1])) {
boolean foundColor = false;
int size = Sort.size();//Since the size will differ dynamically
for (int k = 0; k < size; k++) {
if (Sort.get(k)[3].equals(ProductsInStock.get(i)[3])) {
foundColor = true;
if (Sort.get(k)[4].equals(ProductsInStock.get(i)[4])) {
String S[] = Sort.get(k);
S[5] = (Integer.parseInt(Sort.get(k)[5]) + Integer.parseInt(ProductsInStock.get(i)[5])) + "";
Sort.set(k, S);
S[5]=ProductsInStock.get(i)[5]; //<<<<HERE>>>>
break;
}
if (k == Sort.size() - 1) {
Sort.add(ProductsInStock.get(i));
}
} else if (foundColor == true) {
Sort.add(k, ProductsInStock.get(i));
break;
}
}
System.out.print(ProductsInStock.get(0)[5]+" ");
if (foundColor == false) {
Sort.add(ProductsInStock.get(i));
}
}
}
}
As you can see, there is not a single "ProductsInStock.set()" or "ProductsInStock.get()[]= " to change any value in the arraylist.
When you write this :
Sort.add(ProductsInStock.get(i));
you are adding a reference of the ProductsInStock.get(i) array to the Sort list. Any changes done in Sort.get(Sort.size()-1) will affect the original array.
Therefore code such as
String S[] = Sort.get(k);
S[5] = ...
modifies one of the arrays of ProductsInStock List.
In order to avoid that, you should create a copy of your array before adding it to the other List :
Sort.add(Arrays.copyOf(ProductsInStock.get(i),ProductsInStock.get(i).length));

Counting output appearances on screen

How to count number of occurrences when System.out prints something? In my example user input TR* and lets say program founds TRR; TRC; TRD, ect, but I can't manage to count number of outputs (3 in this example). I want to make so if 0 solutions are found to print out "No solutions found".
Any tips on how to make this work.
if (length == 3) {
System.out.println("Possible solutions:");
n = 0;
for (int i = 0; i < list3.size(); i++) {
String s = (String) list3.get(i);
if (s.matches(user_input))
System.out.println(s);
}
System.out.println(n);
if (n == 1) {
System.out.println("No solutions found");
}
}
Try this:
package stackoverflow.counting;
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
ArrayList<String> list3 = new ArrayList<>();
list3.add("TRA");
list3.add("XXX");
int length = 3;
String user_input = "TR.*";
if (length == 3) {
System.out.println("Possible solutions:");
int n = 0;
for (int i = 0; i < list3.size(); i++) {
String s = list3.get(i);
if (s.matches(user_input)) {
System.out.println(s);
n++;
}
}
System.out.println(n);
if (n == 0) {
System.out.println("No solutions found");
}
}
}
}
Output is:
Possible solutions:
TRA
1
Please also note that TR* is probably not the kind of regular expression you need. Use TR.* instead.
Try with this approach:
int countOfSystemPrintedOutput = 0;
if (length == 3) {
System.out.println("Possible solutions:");
for (String s : list3) {
if(s.matches(user_input)){
System.out.println(s);
countOfSystemPrintedOutput++;
}
}
if (countOfSystemPrintedOutput == 0) {
System.out.println("No solutions found");
}
else{
System.out.println("System.out.println called " + countOfSystemPrintedOutput + "times");
}
}

java recurrsion with ArrayList not working

I am doing recursion for a given phone number and print all the possible string representation of the number. The problem is in loop for (int j=0;j<ops;j++) { the size of the "perm" ArrayList keep increasing in every iteration. I want to get fixed pattern and add new number e.g perm = 11 and call recursion with tperm=110,111,112.
import java.util.*;
public class phoneNum {
public static void getSt ( List<Integer>list , List<Integer> perm ) {
Integer len = list.size();
Integer len1 = perm.size();
Integer ops = 0;
if (len == len1) {
for(int k=0;k<len;k++) {
System.out.print(" " + list.get(k));
}
for(int k=0;k<len;k++) {
System.out.print(" " + perm.get(k));
}
System.out.print("====");
System.out.print(getPattrn(list,perm));
System.out.println("\n");
} else {
for (int i=0; i<len1+1; i++) {
if(list.get(i) == 7 || list.get(i) == 9) {
ops = 4;
} else {
ops = 3;
}
for (int j=0;j<ops;j++) {
List<Integer> tperm = new ArrayList<Integer>(perm);
tperm.add(i,j);
System.out.println("Size=" + tperm.size() + " ---" + perm.size());
getSt(list,tperm);
}
}
}
}
You can add tperm.remove(i) at the end of inner for loop.

Categories

Resources