Reputation: 5146
I am working on an interview question:
Capitalize 2nd, 4th, 8th, 16th letters in a string
input - "letters in a string"
output - "lEtTers in a stRing"
Here is my solution:
public static void main(String[] args) {
String input = "letters in a string";
String output = input.substring(0, 1) + input.substring(1, 2).toUpperCase() + input.substring(2, 3)
+ input.substring(3, 4).toUpperCase() + input.substring(4, 7) + input.substring(7, 8).toUpperCase()
+ input.substring(8, 15) + input.substring(15, 16).toUpperCase() + input.substring(15);
System.out.println(output);
}
Is there any way we can generalize this without hard coding the offset numbers here? In general, what I am looking for is - given the letter number which we want to capitalize, our program should work on that without changing the core logic and should be efficient as well in terms of complexity?
Upvotes: 0
Views: 2664
Reputation: 1471
My safer implementation:
public static String toCapitalizedCase(String givenString) {
if(TextUtils.isEmpty(givenString)){
return givenString;
}
String[] arr = givenString.toLowerCase().split(" ");
StringBuffer sb = new StringBuffer();
for (int i = 0; i < arr.length; i++) {
sb.append(Character.toUpperCase(arr[i].charAt(0)))
.append(arr[i].substring(1)).append(" ");
}
return sb.toString().trim();
}
Upvotes: 0
Reputation: 4703
Here is I think the best way:
//here index is the nth letter to capitalize, i.e. 2 changes the character
//at index 1, hence the subtraction
public String capitalize(String s, int index)
{
StringBuilder sb = new StringBuilder(s);
sb.setCharAt(index - 1, Character.toUpperCase(sb.charAt(index - 1)));
return (sb.toString());
}
//indices in the array should the follow the same convention as above
public String capitalize(String s, int[] indices)
{
for (int i = 0; i < indices.length; i++)
{
s = Capitalize(s, indices[i]);
}
return s;
}
From here calling the method on retrieved input is simple.
EDIT: After returning to look at this randomly, the creation of a StringBuilder in a loop could be costly, since it's only useful inside one method body. A better way would be to extend the pattern to pass around a StringBuilder reference to the string within the methods (in some private manner) to avoid creating a new one all the time.
Upvotes: 0
Reputation: 2073
As others stated, the best way to do this is by writing a method which you can use more than once. Try this:
public static String capitalize(String string, int[] caps) {
if (caps[caps.length - 1] > string.length()) {
return "String not long enough.";
}
StringBuilder sb = new StringBuilder(string);
for (int i : caps) {
sb.setCharAt(i - 1, Character.toUpperCase(sb.charAt(i - 1)));
}
return sb.toString();
}
public static void main(String[] args) {
int[] caps = {2, 4, 8, 16};
System.out.println(capitalize("letters in a string", caps));
}
Upvotes: 0
Reputation: 100
Maybe you could do something like
public static String capitalize(String s, int[] array)//array would be the indexes you want to be caps.
{
char[] stringChars = new char[s.length];
for(int x = 0; x < stringChars.length; x++)
{
stringChars[x] = s.charAt(x);
}
String finalString;
boolean matches;
for(int x = 0; x < stringChars.length; x++)
{
for(int y = 0; y < array.length; y++)
{
if(array[y] == x)
{
matches = true;
break;
}
if(matches == true)
stringChars[x] = Character.toUppercase(stringChars[x]);
finalString += stringChars[x];
}
}
return finalString;
}
I haven't tested this code and there may be some bugs but it could work.
Upvotes: 0
Reputation: 347334
Assuming that you want to set the character at an ever increasing range of power by 2 (2, 4, 8, 16, 32, 64...), you could simply use a loop.
The problem is, String
isn't mutable (it can't be changed) and you should avoid String
concatenation within loops where possible (okay, in your case, it's probably not a big deal, but it's still good practice).
To that end, you could either convert the String
to a char
array (String#toCharArray()
) or use a StringBuilder
, for example...
String text = "letters in a string";
int index = 2;
StringBuilder sb = new StringBuilder(text);
while (index < sb.length()) {
sb.setCharAt(index - 1, Character.toUpperCase(sb.charAt(index - 1)));
index *= 2;
System.out.println(index);
}
System.out.println(sb.toString());
Which outputs lEtTers in a stRing
Upvotes: 3
Reputation: 1438
Yes you can do this without hard coding the offset. Here is an example:
int[] toCaps = new int[]{2, 4, 8, 16};
String input = "letters in a string";
String newString = "";
for(int i = 0; i < input.length(); i++){
boolean b = false;
for(int j : toCaps){
if(i == (j-1)){//Subtract 1 since the indexing starts at 0.
b = true;
}
}
if(b){
newString += Character.toUpperCase(input.charAt(i));
}else{
newString += input.charAt(i);
}
}
System.out.println(newString);
Now what ever numbers are in the toCaps array will be the location of the string which is converted to uppercase.
Upvotes: 0