I was wondering if it possible to mix two strings in java.
Suppose I have
11111
and
22222
What would be the best way to combine them to form?
1212121212
Assuming both strings are of equal length, you could simply write a loop to go over the characters and do what you want:
String s1, s2; /* input strings */
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s1.length(); i++) {
sb.append(s1.charAt(i));
sb.append(s2.charAt(i));
}
String result = sb.toString();
Here's an implementation that preserves the remainder of unequal length strings:
public static String mix(String a, String b) {
final int aLength = a.length();
final int bLength = b.length();
final int min = Math.min(aLength, bLength);
final StringBuilder sb = new StringBuilder(aLength + bLength);
for(int i = 0; i < min; i++) {
sb.append(a.charAt(i));
sb.append(b.charAt(i));
}
if (aLength > bLength) {
sb.append(a, bLength, aLength);
} else if (aLength < bLength) {
sb.append(b, aLength, bLength);
}
return sb.toString();
}
Yes - iterate the first string, and for each char in it, append to a builder the char in the same position from the second string (if it exists):
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str1.length(); i++) {
sb.append(str1.charAt(i));
if (str.length() > i) {
sb.append(str2.charAt(i));
}
}
return sb.toString();
I wonder if the example given is intentional, i.e they all have 1 char repeated. In that case it is much simpler. If they are not, then other answers are good.
Related
I want to shuffle a string without using any arrays, StringBuilder, or power tools (packages or methods that do the work for you) and using Math.random().
My code below works but I don't like it because I can't use string builder or .append(). Could someone help me and fix it?
public class loopPrr
{
static String shuffle(int a) {
String s = "BaaBooDaaDoo";
StringBuilder sb = new StringBuilder(a);
for (int i = 0; i < a; i++) {
int r = (int)(s.length() * Math.random());
sb.append(s.charAt(r));
}
return sb.toString();
}
}
If I got it right, you can simply use String:
static String shuffle(int a) {
String s = "BaaBooDaaDoo";
String sb = "";
for (int i = 0; i < a; i++) {
int r = (int) (s.length() * Math.random());
sb += s.charAt(r);
}
return sb;
}
I would suggest changing the name of "sb" variable to avoid misunderstanding though.
It is possible to shuffle a string by applying Fisher--Yates algorithm to the character array of the input string.
The algorithm basically consists in swapping the characters at randomized indexes as shown below.
static String shuffle(String str) {
char[] arr = str.toCharArray();
for (int i = str.length() - 1; i > 0 ; i--) { // starting from the last character
int x = (int)(i * Math.random()); // next index is in range [0...i-1]
char t = arr[i];
arr[i] = arr[x];
arr[x] = t;
}
return new String(arr);
}
If a randomized String of length a from the predefined alphabet needs to be generated, the following method can be implemented based on previous implementation for String to guarantee that all characters of the alphabet are used at least once if a >= alphabet.length:
private static final String LETTERS = "AaBbCcDdEe";
static String shuffle(int a) {
if (a <= 0) {
return "";
}
if (a < LETTERS.length()) {
char[] res = new char[a];
for (int i = 0, x = LETTERS.length(); x > 0 && i < a; i++, x--) {
res[i] = LETTERS.charAt((int)(Math.random() * x));
}
return new String(res);
}
return shuffle(shuffle(LETTERS) + shuffle(a - LETTERS.length()));
}
I am stuck in one of the problem related string in Java. My logic has worked well for some test cases, but not for all test cases. Please suggest me the actual logic of the following question::
I am given a string s of n character, comprising only of A's and B's . I can choose any index i and change s(i) to either A or B. Find the minimum no. Of changes that you must make to string S such that the resultant string is of format : AAAAA.....BBBBB. In other words, my task is to determine minimum no. of changes such that string s has x no. of A's in the beginning, followed by the remaining (n-x) no. of B's.
Sample Input is as below
4
3
AAB
5
AABAA
1
B
4
BABA
First line: A single integer denoting the number of test cases
For each test case:
First line contains a single integer denoting the size of the string
Second line contains string
My code is as below
import java.util.*;
class TestClass {
public static void main(String args[] ) throws Exception {
Scanner s = new Scanner(System.in);
TestClass t = new TestClass();
int test_case = s.nextInt();
for(int i = 0; i < test_case; i++){
int len = s.nextInt();
String none = s.nextLine();
String str = s.nextLine();
int cnta = t.count_ab(str,'A');
int cntb = t.count_ab(str,'B');
char c1 = '1';
if(cnta > cntb){
c1 = 'A';
}
else{
c1 = 'B';
}
int count = 0;
int c1_count = 0;
int c2_count = 0;
if(str.length() > 1){
String rev = "";
c1_count = t.cnt_init_a(str, 'A');
StringBuilder sb = new StringBuilder(str);
rev = sb.reverse().toString();
c2_count = t.cnt_init_a(rev, 'B');
int rem_len = str.length() - c2_count;
for(int h = c1_count; h < rem_len; h++){
if(Character.compare(str.charAt(h), c1) != 0){
count = count + 1;
}
}
}
System.out.println(count);
}
}
public int cnt_init_a(String str, char c){
int cnt = 0;
for(int l = 0; l < str.length(); l++){
if(Character.compare(str.charAt(l), c) == 0){
cnt = cnt + 1;
}
else{
break;
}
}
return cnt;
}
public int count_ab(String str, char c){
int cnt = 0;
for(int g = 0; g < str.length(); g++){
if(Character.compare(str.charAt(g), c) == 0){
cnt = cnt + 1;
}
}
return cnt;
}
Your logic fails for e.g. "BAAAAAAAAAABBBBBBBBBB" and "AAAAAAAAAABBBBBBBBBBA".
You should start by ignoring all leading A's and all trailing B's, since they should never be changed.
"BAAAAAAAAAABBBBBBBBBB" -> "BAAAAAAAAAA" (removed trailing B's)
"AAAAAAAAAABBBBBBBBBBA" -> "BBBBBBBBBBA" (removed leading A's)
Then change either the leading B's to A's, or the trailing A's to B's, whichever is shorter.
Then repeat the process.
I am working on a problem of replacing spaces with %20 from Cracking the Coding Interview 5th edition:
Write a method to replace all spaces in a string with '%20'. You may assume that the string has sufficient space at the end of the string to hold the additional characters, and that you are given the "true" length of the string. (Note: if implementing in Java, please use a character array so that you can perform this operation in place)
The algorithm I have is:
public static void replaceSpaces(String input, int length) {
char[] str = input.toCharArray();
int spaceCount = 0;
for(int i = length - 1; i >= 0; i--){
if(str[i] == ' ') {
spaceCount++;
}
}
int newLength = length + spaceCount * 2;
str[newLength] = '\0';
for(int i = length - 1; i >= 0; i--) {
if(str[i] == ' ') {
str[newLength - 1] = '0';
str[newLength - 2] = '2';
str[newLength - 3] = '%';
newLength = newLength - 3;
System.out.println(str);
} else {
str[newLength - 1] = str[i];
newLength = newLength - 1;
System.out.println(str);
}
}
}
Printing out each step of the function, here are my outputs:
Mr John Smith h
Mr John Smith th
Mr John Smith ith
Mr John Smithmith
Mr John SmitSmith
Mr John S%20Smith
Mr John n%20Smith
Mr Johnhn%20Smith
Mr Johohn%20Smith
Mr JoJohn%20Smith
Mr%20John%20Smith
Mr%20John%20Smith
Mr%20John%20Smith
I have two questions:
We know the new length of the string is 17. What I do not understand is, why we need to have [newLength - 1] instead of [newLength]. We are interested in replacing the current index, no? Or is it because the new length is 17, but when converted to indices, it's actually 16 (0th index).
What is the purpose of: str[newLength] = '\0';
We don't all have that book, but from a pending edit, I see that the exact question is:
Write a method to replace all spaces in a string with '%20'. You may assume that the string has sufficient space at the end of the string to hold the additional characters, and that you are given the "true" length of the string. (Note: if implementing in Java, please use a character array so that you can perform this operation in place)
From Cracking the Coding Interview 5th edition
So, it says that your input argument should be a char[].
Since you're changing the length of the text, your method would need to return the new length.
Question 1:
We know the new length of the string is 17. What I do not understand is, why we need to have [newLength - 1] instead of [newLength]. We are interested in replacing the current index, no? Or is it because the new length is 17, but when converted to indices, it's actually 16 (0th index).
You answered it yourself. With a length of 17, the indices are 0 to 16. If the array is only 17 long, accessing index 17 with throw an IndexOutOfBoundsException.
Question 2:
What is the purpose of: str[newLength] = '\0';
None whatsoever. It's is invalid and has no purpose in Java. Remove it.
Java Strings have a length(). In C, strings are zero-terminated, but not in Java.
To test the code, try running it with this:
char[] buffer = { 'M','r',' ','J','o','h','n',' ','S','m','i','t','h','*','*','*','*' };
int inLen = 13;
System.out.println("buffer: '" + new String(buffer) + "'");
System.out.println("inLen : " + inLen);
System.out.println("input : '" + new String(buffer, 0, inLen) + "'");
int outLen = replaceSpaces(buffer, inLen);
System.out.println("outLen: " + outLen);
System.out.println("result: '" + new String(buffer, 0, outLen) + "'");
Output should be:
buffer: 'Mr John Smith****'
inLen : 13
input : 'Mr John Smith'
outLen: 17
result: 'Mr%20John%20Smith'
Accessing input[17] in the method would throw IndexOutOfBoundsException.
Here is one possible implementation based on the shown code, that follows the quoted text, and stop processing once all spaces are replaced.
public static int replaceSpaces(char[] str, int length) {
int spaceCount = 0;
for (int i = length - 1; i >= 0; i--)
if (str[i] == ' ')
spaceCount++;
int shift = spaceCount * 2;
int newLength = length + shift;
for (int i = newLength - 1; shift > 0; i--) {
char c = str[i - shift];
if (c != ' ') {
str[i] = c;
} else {
str[i] = '0';
str[--i] = '2';
str[--i] = '%';
shift -= 2;
}
}
return newLength;
}
This produces the expected output from the test code above.
Code posted below works good. Cheers.
Sample Output
package StringAndArray;
public class Question_Four_Replace_Spaces {
public static void main(String[] args) {
String string = "Mr Shubham Dilip Yeole";
char[] array = string.toCharArray();
System.out.println("\n\nInput : " +string);
System.out.println("\n\nResult: "+method_1(array,string.length()));
method_1(array,string.length());
}
private static String method_1(char[] array, int length) {
int spaceCount = 0;
for(int i=0; i<array.length; i++){
if(array[i]==' ') spaceCount++;
}
int count = 0;
int newLength = length + spaceCount*2;
char[] newArray = new char[newLength];
for(int i= 0; i<array.length; i++){
if(array[i]==' '){
newArray[count++] = '%';
newArray[count++] = '2';
newArray[count++] = '0';
}else{
newArray[count] = array[i];
count++;
}
}
String newString1 = new String(newArray);
return newString1;
}
}
I believe that your direct questions have been answered in the comments, so here instead I will focus on issues with the method as written.
Ignoring the fact that this functionality already exists in the base String class (and many other 3rd party string utility classes), we can still write a basic string replacement function. The function as written in the question does not appear to be written for Java, and does not return any value, which since Strings are immutable means that the function cannot possibly be fulfilling its name.
Instead, we need to create a new array which we copy the existing characters to while replacing any spaces we encounter with %20. We then return this array as a new String. Conveniently, Java has a class which encapsulates a variable size array of characters that we can use to assemble our new String called StringBuilder.
So a simpler and working (but not optimized) replacement function in Java may look like:
public static String replaceSpaces(String input)
{
if (input == null) return null;
// New string builder with some padding to account for replacements...
// Padding was chosen pretty arbitrarily, there are certainly better values.
StringBuilder builder = new StringBuilder(input.length() + 128);
for (int i = 0; i < input.length(); i++)
{
char c = input.chatAt(i);
if (c == ' ') {
builder.append("%20");
} else {
builder.append(c);
}
}
return builder.toString();
}
It may be more optimal to convert the entire String to a char[] at the beginning, and iterate over the array instead of using String.charAt(i). And we could probably choose a more appropriate padding for the StringBuilder by multiplying the length of the existing string by some constant based on the expected number of spaces. For very large strings it could even make sense to first count the number of spaces before declaring our array, but those optimizations are left as an exercise for the reader.
#Test public void replaceTest() {
String s = "Mr John Smith ";
char[] chars = s.toCharArray();
int length = 13;
char[] chars1 = subString(chars, length);
//actualString = actualString.replace(" ", "%20");
Assert.assertEquals(replace(chars1, "%20"), "Mr%20John%20Smith");
}
private char[] subString(char[] chars, int length) {
char[] newChar = new char[length];
for (int i = 0; i < length; i++) {
newChar[i] = chars[i];
}
return newChar;
}
private String replace(char[] chars, String s) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < chars.length; i++) {
if (chars[i] == ' ') {
builder.append(s);
} else {
builder.append(chars[i]);
}
}
return builder.toString();
}
public static String urlify(String s1, int truelength) {
int countspaces = 0;
char[] charobj = s1.toCharArray();
for (int i = truelength - 1; i < charobj.length; i++) {
if (charobj[i] == ' ') {
countspaces++;
}
}
for (int i = truelength - 1; i >= 0; i--) {
if (charobj[i] == ' ' && countspaces != 0) {
for (int j = truelength - 1; j > i; j--) {
char temp = charobj[j];
charobj[j + 2] = temp;
}
countspaces = countspaces - 2;
charobj[i] = '%';
charobj[i + 1] = '2';
charobj[i + 2] = '0';
truelength = truelength + 2;
}
}
return String.valueOf(charobj);
}
I am comparing two strings, in Java, to see how many characters from the first string show up in the second string. The following is some expectations:
matchingChars("AC", "BA") → 1
matchingChars("ABBA", "B") → 2
matchingChars("B", "ABBA") → 1
My approach is as follows:
public int matchingChars(String str1, String str2) {
int count = 0;
for (int a = 0; a < str1.length(); a++)
{
for (int b = 0; b < str2.length(); b++)
{ char str1Char = str1.charAt(a);
char str2Char = str2.charAt(b);
if (str1Char == str2Char)
{ count++;
str1 = str1.replace(str1Char, '0');
}
}
}
return count;
}
I know my approach is not the best, but I think it should do it. However, for
matchingChars("ABBA", "B") → 2
My code yields "1" instead of "2". Does anyone have any suggestion or advice? Thank you very much.
Assuming that comparing "AABBB" with "AAAABBBCCC" should return 15 (2*3 + 3*3 + 0*3) then:
For each string make a Map from the character of the string to the count of characters.
Compute the intersection of the keysets for the two maps.
For each element in the keyset accumulate the product of the values. Print the result.
This is linear in the size of the two strings.
Is it ok to supply working code on homework problems?
public long testStringCount() {
String a = "AABBBCCC";
String b = "AAABBBDDDDD";
Map<Character,Integer> aMap = mapIt(a);
Map<Character,Integer> bMap = mapIt(b);
Set<Character> chars = Sets.newHashSet(aMap.keySet());
chars.addAll(bMap.keySet());
long result = 0;
for (Character c : chars) {
Integer ac = aMap.get(c);
Integer bc = bMap.get(c);
if (null != ac && null != bc) {
result += ac*bc;
}
}
return result;
}
private Map<Character, Integer> mapIt(String a) {
Map<Character,Integer> result = Maps.newHashMap();
for (int i = 0; i < a.length(); i++) {
Character c = a.charAt(i);
Integer x = result.get(c);
if (null == x) {
x = 0;
}
x++;
result.put(c, x);
}
return result;
}
Clearly you have to make sure you only count unique characters from string 1. You're double-counting B because you're counting B's twice, once for each occurrence in string 1.
Well your code is only showing 1 because of this line:
str1 = str1.replace(str1Char, '0');
That's turning "ABBA" into "A00A" - so the second B doesn't get seen.
Perhaps you should turn the second string into a HashSet<Character> instead... then you could just use something like:
int count = 0;
for (int i = 0; i < str1.length; i++)
{
if (otherSet.contains(str1.charAt(i))
{
count++;
}
}
It's not clear what result you want to get from "ABBA" / "CBCB" - if it's 2 (because there are 2 Bs) then the above approach will work. If it's 4 (because each of the 2 Bs in the first string matches 2 Bs in the second string) then all you need to do is get rid of your replace call.
EDIT: With the clarifications, it sounds like you could just do this:
for (int a = 0; a < str1.length(); a++)
{
for (int b = 0; b < str2.length(); b++)
{
if (str1.charAt(a) == str2.charAt(b))
{
count++;
// Terminate the inner loop which is iterating over str2,
// and move on to the next character in str1
break;
}
}
}
Your solution works, but is quadratic. If all characters are below 256, then you can do something like this:
int matching(String s1, String s2) {
int[] count1 = frequencies(s1);
int[] count2 = frequencies(s2);
sum = 0;
for(int i = 0; i< 256; i++) {
sum += count1[i]*count2[i] != 0 ? Math.max(count1[i], count2[i]) : 0;
}
return sum;
}
int[] frequencies(String s) {
int[] ret = new int[256];
for(char c : s) {
int[c]+=1;
}
}
Otherwise, you'll need a multiset.
I have a string, "abc". How would a program look like (if possible, in Java) who permute the String?
For example:
abc
ABC
Abc
aBc
abC
ABc
abC
AbC
Something like this should do the trick:
void printPermutations(String text) {
char[] chars = text.toCharArray();
for (int i = 0, n = (int) Math.pow(2, chars.length); i < n; i++) {
char[] permutation = new char[chars.length];
for (int j =0; j < chars.length; j++) {
permutation[j] = (isBitSet(i, j)) ? Character.toUpperCase(chars[j]) : chars[j];
}
System.out.println(permutation);
}
}
boolean isBitSet(int n, int offset) {
return (n >> offset & 1) != 0;
}
As you probably already know, the number of possible different combinations is 2^n, where n equals the length of the input string.
Since n could theoretically be fairly large, there's a chance that 2^n will exceed the capacity of a primitive type such as an int. (The user may have to wait a few years for all of the combinations to finish printing, but that's their business.)
Instead, let's use a bit vector to hold all of the possible combinations. We'll set the number of bits equal to n and initialize them all to 1. For example, if the input string is "abcdefghij", the initial bit vector values will be {1111111111}.
For every combination, we simply have to loop through all of the characters in the input string and set each one to uppercase if its corresponding bit is a 1, else set it to lowercase. We then decrement the bit vector and repeat.
For example, the process would look like this for an input of "abc":
Bits: Corresponding Combo:
111 ABC
110 ABc
101 AbC
100 Abc
011 aBC
010 aBc
001 abC
000 abc
By using a loop rather than a recursive function call, we also avoid the possibility of a stack overflow exception occurring on large input strings.
Here is the actual implementation:
import java.util.BitSet;
public void PrintCombinations(String input) {
char[] currentCombo = input.toCharArray();
// Create a bit vector the same length as the input, and set all of the bits to 1
BitSet bv = new BitSet(input.length());
bv.set(0, currentCombo.length);
// While the bit vector still has some bits set
while(!bv.isEmpty()) {
// Loop through the array of characters and set each one to uppercase or lowercase,
// depending on whether its corresponding bit is set
for(int i = 0; i < currentCombo.length; ++i) {
if(bv.get(i)) // If the bit is set
currentCombo[i] = Character.toUpperCase(currentCombo[i]);
else
currentCombo[i] = Character.toLowerCase(currentCombo[i]);
}
// Print the current combination
System.out.println(currentCombo);
// Decrement the bit vector
DecrementBitVector(bv, currentCombo.length);
}
// Now the bit vector contains all zeroes, which corresponds to all of the letters being lowercase.
// Simply print the input as lowercase for the final combination
System.out.println(input.toLowerCase());
}
public void DecrementBitVector(BitSet bv, int numberOfBits) {
int currentBit = numberOfBits - 1;
while(currentBit >= 0) {
bv.flip(currentBit);
// If the bit became a 0 when we flipped it, then we're done.
// Otherwise we have to continue flipping bits
if(!bv.get(currentBit))
break;
currentBit--;
}
}
String str = "Abc";
str = str.toLowerCase();
int numOfCombos = 1 << str.length();
for (int i = 0; i < numOfCombos; i++) {
char[] combinations = str.toCharArray();
for (int j = 0; j < str.length(); j++) {
if (((i >> j) & 1) == 1 ) {
combinations[j] = Character.toUpperCase(str.charAt(j));
}
}
System.out.println(new String(combinations));
}
You can also use backtracking to solve this problem:
public List<String> letterCasePermutation(String S) {
List<String> result = new ArrayList<>();
backtrack(0 , S, "", result);
return result;
}
private void backtrack(int start, String s, String temp, List<String> result) {
if(start >= s.length()) {
result.add(temp);
return;
}
char c = s.charAt(start);
if(!Character.isAlphabetic(c)) {
backtrack(start + 1, s, temp + c, result);
return;
}
if(Character.isUpperCase(c)) {
backtrack(start + 1, s, temp + c, result);
c = Character.toLowerCase(c);
backtrack(start + 1, s, temp + c, result);
}
else {
backtrack(start + 1, s, temp + c, result);
c = Character.toUpperCase(c);
backtrack(start + 1, s, temp + c, result);
}
}
Please find here the code snippet for the above :
public class StringPerm {
public static void main(String[] args) {
String str = "abc";
String[] f = permute(str);
for (int x = 0; x < f.length; x++) {
System.out.println(f[x]);
}
}
public static String[] permute(String str) {
String low = str.toLowerCase();
String up = str.toUpperCase();
char[] l = low.toCharArray();
char u[] = up.toCharArray();
String[] f = new String[10];
f[0] = low;
f[1] = up;
int k = 2;
char[] temp = new char[low.length()];
for (int i = 0; i < l.length; i++)
{
temp[i] = l[i];
for (int j = 0; j < u.length; j++)
{
if (i != j) {
temp[j] = u[j];
}
}
f[k] = new String(temp);
k++;
}
for (int i = 0; i < u.length; i++)
{
temp[i] = u[i];
for (int j = 0; j < l.length; j++)
{
if (i != j) {
temp[j] = l[j];
}
}
f[k] = new String(temp);
k++;
}
return f;
}
}
You can do something like
```
import java.util.*;
public class MyClass {
public static void main(String args[]) {
String n=(args[0]);
HashSet<String>rs = new HashSet();
helper(rs,n,0,n.length()-1);
System.out.println(rs);
}
public static void helper(HashSet<String>rs,String res , int l, int n)
{
if(l>n)
return;
for(int i=l;i<=n;i++)
{
res=swap(res,i);
rs.add(res);
helper(rs,res,l+1,n);
res=swap(res,i);
}
}
public static String swap(String st,int i)
{
char c = st.charAt(i);
char ch[]=st.toCharArray();
if(Character.isUpperCase(c))
{
c=Character.toLowerCase(c);
}
else if(Character.isLowerCase(c))
{
c=Character.toUpperCase(c);
}
ch[i]=c;
return new String(ch);
}
}
```