Doubling each letter in a String - java

I'm doing a project for Java 1, and I'm completely stuck on this question.
Basically I need to double each letter in a string.
"abc" -> "aabbcc"
"uk" -> "uukk"
"t" -> "tt"
I need to do it in a while loop in what is considered "Java 1" worthy. So i'm guessing that this means more of a problematic approach.
I know that the easiest way for me to do this, from my knowledge, would be using the charAt method in a while loop, but for some reason my mind can't figure out how to return the characters to another method as a string.
Thanks
[EDIT] My Code (wrong, but maybe this will help)
int index = 0;
int length = str.length();
while (index < length) {
return str.charAt(index) + str.charAt(index);
index++;
}

String s="mystring".replaceAll(".", "$0$0");
The method String.replaceAll uses the regular expression syntax which is described in the documentation of the Pattern class, where we can learn that . matches “any character”. Within the replacement, $number refers to numbered “capturing group” whereas $0 is predefined as the entire match. So $0$0 refers to the matching character two times. As the name of the method suggests, it is performed for all matches, i.e. all characters.

Yeah, a for loop would really make more sense here, but if you need to use a while loop then it would look like this:
String s = "abc";
String result = "";
int i = 0;
while (i < s.length()){
char c = s.charAt(i);
result = result + c + c;
i++;
}

You can do:
public void doubleString(String input) {
String output = "";
for (char c : input.toCharArray()) {
output += c + c;
}
System.out.println(output);
}

Your intuition is very good. charAt(i) will return the character in the string at location i, yes?
You also said you wanted to use a loop. A for loop, traversing the length of the list, string.length(), will allow you to do this. At every single node in the string, what do you need to do? Double the character.
Let's take a look at your code:
int index = 0;
int length = str.length();
while (index < length) {
return str.charAt(index) + str.charAt(index); //return ends the method
index++;
}
Problematically for your code, you are returning two characters immediately upon entering the loop. So for a string abc, you are returning aa. Let's store the aa in memory instead, and then return the completed string like so:
int index = 0;
int length = str.length();
String newString = "";
while (index < length) {
newString += str.charAt(index) + str.charAt(index);
index++;
}
return newString;
This will add the character to newString, allowing you to return the entire completed string, as opposed to a single set of doubled characters.
By the way, this may be easier to do as a for loop, condensing and clarifying your code. My personal solution (for a Java 1 class) would look something like this:
String newString = "";
for (int i = 0; i < str.length(); i++){
newString += str.charAt(i) + str.charAt(i);
}
return newString;
Hope this helps.

try this
String a = "abcd";
char[] aa = new char[a.length() * 2];
for(int i = 0, j = 0; j< a.length(); i+=2, j++){
aa[i] = a.charAt(j);
aa[i+1]= a.charAt(j);
}
System.out.println(aa);

public static char[] doubleChars(final char[] input) {
final char[] output = new char[input.length * 2];
for (int i = 0; i < input.length; i++) {
output[i] = input[i];
output[i + 1] = input[i];
}
return output;
}

Assuming this is inside a method, you should understand that you can only return once from a method. After encountering a return statement, the control goes back to the calling method. Thus your approach of returning char every time in a loop is faulty.
int index = 0;
int length = str.length();
while (index < length) {
return str.charAt(index) + str.charAt(index); // only the first return is reachable,other are not executed
index++;
}
Change your method to build a String and return it
public String modify(String str)
{
int index = 0;
int length = str.length();
String result="";
while (index < length) {
result += str.charAt[index]+str.charAt[index];
index++;
}
return result;
}

Related

How to obtain the length of the last word in the string

I have reversed the string and have a for loop to iterate through the reversed string.
I am counting characters and I know I have a logic flaw, but I cannot pinpoint why I am having this issue.
The solution needs to return the length of the last word in the string.
My first thought was to iterate through the string backward (I don't know why I decided to create a new string, I should have just iterated through it by decrementing my for loop from the end of the string).
But the logic should be the same from that point for my second for loop.
My logic is basically to try to count characters that aren't whitespace in the last word, and then when the count variable has a value, as well as the next whitespace after the count has counted the characters of the last word.
class Solution {
public int lengthOfLastWord(String s) {
int count = 0;
int countWhite = 0;
char ch;
String reversed = "";
for(int i = 0; i < s.length(); i++) {
ch = s.charAt(i);
reversed += ch;
}
for(int i = 0; i < reversed.length(); i++) {
if(!Character.isWhitespace(reversed.charAt(i))) {
count++;
if(count > 1 && Character.isWhitespace(reversed.charAt(i)) == true) {
break;
}
}
}
return count;
}
}
Maybe try this,
public int lengthOfLastWord(String s) {
String [] arr = s.trim().split(" ");
return arr[arr.length-1].length();
}
Another option would be to use index of last space and calculate length from it:
public int lengthOfLastWord(String string) {
int whiteSpaceIndex = string.lastIndexOf(" ");
if (whiteSpaceIndex == -1) {
return string.length();
}
int lastIndex = string.length() - 1;
return lastIndex - whiteSpaceIndex;
}
String.lastIndexOf() finds the start index of the last occurence of the specified string. -1 means the string was not found, in which case we have a single word and length of the entire string is what we need. Otherwise means we have index of the last space and we can calculate last word length using lastIndexInWord - lastSpaceIndex.
There are lots of ways to achieve that. The most efficient approach is to determine the index of the last white space followed by a letter.
It could be done by iterating over indexes of the given string (reminder: String maintains an array of bytes internally) or simply by invoking method lastIndexOf().
Keeping in mind that the length of a string that could be encountered at runtime is limited to Integer.MAX_VALUE, it'll not be a performance-wise solution to allocate in memory an array, produced as a result of splitting of this lengthy string, when only the length of a single element is required.
The code below demonstrates how to address this problem with Stream IPA and a usual for loop.
The logic of the stream:
Create an IntStream that iterates over the indexes of the given string, starting from the last.
Discard all non-alphabetic symbols at the end of the string with dropWhile().
Then retain all letters until the first non-alphabetic symbol encountered by using takeWhile().
Get the count of element in the stream.
Stream-based solution:
public static int getLastWordLength(String source) {
return (int) IntStream.iterate(source.length() - 1, i -> i >= 0, i -> --i)
.map(source::charAt)
.dropWhile(ch -> !Character.isLetter(ch))
.takeWhile(Character::isLetter)
.count();
}
If your choice is a loop there's no need to reverse the string. You can start iteration from the last index, determine the values of the end and start and return the difference.
Just in case, if you need to reverse a string that is the most simple and efficient way:
new StringBuilder(source).reverse().toString();
Iterative solution:
public static int getLastWordLength(String source) {
int end = -1; // initialized with illegal index
int start = 0;
for (int i = source.length() - 1; i >= 0; i--) {
if (Character.isLetter(source.charAt(i)) && end == -1) {
end = i;
}
if (Character.isWhitespace(source.charAt(i)) && end != -1) {
start = i;
break;
}
}
return end == -1 ? 0 : end - start;
}
main()
public static void main(String[] args) {
System.out.println(getLastWord("Humpty Dumpty sat on a wall % _ (&)"));
}
output
4 - last word is "wall"
Firstly, as you have mentioned, your reverse string formed is just a copy of your original string. To rectify that,
for (int i = s.length() - 1; i >= 0; i--) {
ch = s.charAt(i);
reversed += ch;
}
Secondly, the second if condition is inside your first if condition. That is why, it will never break ( because you are first checking if character is whitespace, if it is, then you are not going inside the if statement, thus your second condition of your inner if loop will never be satisfied).
public class HW5 {
public static void main(String[] args) {
String s = "My name is Mathew";
int count = lengthOfLastWord(s);
System.out.println(count);
}
public static int lengthOfLastWord(String s) {
int count = 0;
int countWhite = 0;
char ch;
String reversed = "";
System.out.println("original string is----" + s);
for (int i = s.length() - 1; i >= 0; i--) {
ch = s.charAt(i);
reversed += ch;
}
System.out.println("reversed string is----" + reversed);
for (int i = 0; i < reversed.length(); i++) {
if (!Character.isWhitespace(reversed.charAt(i)))
count++;
if (count > 1 && Character.isWhitespace(reversed.charAt(i)) == true) {
break;
}
}
return count;
}
}
=
and the output is :
original string is----My name is Mathew
reversed string is----wehtaM si eman yM
6
Another way to go about is : you use the inbuilt function split which returns an array of string and then return the count of last string in the array.

Java Code output If input is "aabbba" then output should be "a2b3a1" [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am doing one simple java code where if
input is : "aabbba"
then
output should be: "a2b3a1"
I have done the below coding but missing somewhere. So let me know my mistake.
public class Test {
public static void main(String[] args) {
String str = "aabbba";
int count = 1;
for (int i = 0; i < str.length(); i = i + count) {
count = 1;
for (int j = i + 1; j < str.length(); j++) {
if (str.charAt(i) == str.charAt(j)) {
count = count + 1;
} else {
System.out.println(str.charAt(i) + "" + count);
break;
}
}//end of inner for
}//end of outer for
}//end of main
}//end of class
Actually you have too much code, You only need one loop, and you should be comparing the letter to the previous one, not attempting to compare each letter to every letter after it.
If you are confused about what your program is doing, the best place to start is to use your debugger to step through the code.
for(int i = 0, count = 1; i < str.length(); i++, count++) {
char ch = str.charAt(i);
char next = i + 1 < str.length() ? str.charAt(i + 1) : (char) -1;
if (ch != next) {
System.out.print("" + ch + count);
count = 0;
}
}
Using your effort and code, you simply did put the print to the wrong place
String str = "aabbba";
int count = 1;
for(int i = 0; i <str.length();i=i+count){
count =1;
for(int j = i+1; j<str.length();j++){
if(str.charAt(i) == str.charAt(j)){
count = count+1;
}
else{
break;
}
}
// Print here otherwise you will miss the last group of letters
// Also if you just want one line use .print instead of println
System.out.print(str.charAt(i)+""+count);
}
Using Java-8 and my StreamEx library it's a one-liner:
String input = "aabbba";
String result = IntStreamEx.ofChars(input).mapToObj(ch -> (char)ch)
.runLengths().join("").joining();
Step-by step:
IntStreamEx.ofChars(input): create IntStreamEx (enhanced IntStream) where each element is the corresponding character of input line.
.mapToObj(ch -> (char)ch): transform to StreamEx<Character> (enhanced Stream<Character>) where each element is the Character object.
.runLengths(): convert to EntryStream<Character, Long> (enhanced Stream<Map.Entry<Character, Long>>) where keys are Character objects and values are counts of equal adjacent characters.
.join(""): convert to StreamEx<String>, joining keys (characters) and values (counts) via given empty separator.
.joining(): final reduction to the resulting string without additional separators.
You're just missing the print of the last group of letters. you only print inside the loop once you found a different letter, you should take into account the last group of letters that has no "different letter" after it
I would suggest using a StringBuilder:
public String myOutput(String str) {
if (str == null || str.length() == 0)
return str;
StringBuilder sb = new StringBuilder();
int count = 1;
char currentChar;
for (int i = 0; i < str.length() - 1; i++) {
currentChar = str.charAt(i);
if (currentChar == str.charAt(i+1)) {
count++;
} else {
sb.append(currentChar);
sb.append(String.valueOf(count));
count = 1;
}
}
sb.append(str.charAt(str.length()-1));
sb.append(String.valueOf(count));
return sb.toString();
}
You only need 1 loop
System.out.println() will cause your output to have line break. You better use System.out.print(). Now your currrent code is resulting :
a2
b3

Unsure how to implement for loop

Hello I am having trouble implementing this function
Function:
Decompress the String s. Character in the string is preceded by a number. The number tells you how many times to repeat the letter. return a new string.
"3d1v0m" becomes "dddv"
I realize my code is incorrect thus far. I am unsure on how to fix it.
My code thus far is :
int start = 0;
for(int j = 0; j < s.length(); j++){
if (s.isDigit(charAt(s.indexOf(j)) == true){
Integer.parseInt(s.substring(0, s.index(j))
Assuming the input is in correct format, the following can be a simple code using for loop. Of course this is not a stylish code and you may write more concise and functional style code using Commons Lang or Guava.
StringBuilder builder = new StringBuilder();
for (int i = 0; i < s.length(); i += 2) {
final int n = Character.getNumericValue(s.charAt(i));
for (int j = 0; j < n; j++) {
builder.append(s.charAt(i + 1));
}
}
System.out.println(builder.toString());
Here is a solution you may like to use that uses Regex:
String query = "3d1v0m";
StringBuilder result = new StringBuilder();
String[] digitsA = query.split("\\D+");
String[] letterA = query.split("[0-9]+");
for (int arrIndex = 0; arrIndex < digitsA.length; arrIndex++)
{
for (int count = 0; count < Integer.parseInt(digitsA[arrIndex]); count++)
{
result.append(letterA[arrIndex + 1]);
}
}
System.out.println(result);
Output
dddv
This solution is scalable to support more than 1 digit numbers and more than 1 letter patterns.
i.e.
Input
3vs1a10m
Output
vsvsvsammmmmmmmmm
Though Nami's answer is terse and good. I'm still adding my solution for variety, built as a static method, which does not use a nested For loop, instead, it uses a While loop. And, it requires that the input string has even number of characters and every odd positioned character in the compressed string is a number.
public static String decompress_string(String compressed_string)
{
String decompressed_string = "";
for(int i=0; i<compressed_string.length(); i = i+2) //Skip by 2 characters in the compressed string
{
if(compressed_string.substring(i, i+1).matches("\\d")) //Check for a number at odd positions
{
int reps = Integer.parseInt(compressed_string.substring(i, i+1)); //Take the first number
String character = compressed_string.substring(i+1, i+2); //Take the next character in sequence
int count = 1;
while(count<=reps)//check if at least one repetition is required
{
decompressed_string = decompressed_string + character; //append the character to end of string
count++;
};
}
else
{
//In case the first character of the code pair is not a number
//Or when the string has uneven number of characters
return("Incorrect compressed string!!");
}
}
return decompressed_string;
}

Comparing two unknown strings and finding match [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
If I have
String x = "test";
String s = "tastaegasghet;
you can find t e s t inside the string s. The naive way of doing this with a known string would be something like this:
.*t+.*e+.*s+.*t+.*
This will return true if we can find the letters t e s t in order and any characters inbetween. I want to do the same thing but with two unknown Strings x and s or in otherwords, String s and x can be anything. I don't want something hard coded but something for general use instead.
This is the pseudocode for looping solution:
function (
needle, // x
haystack // s
) {
j = 0
for (i = 0; i < haystack.length && j < needle.length; i++) {
if (haystack[i] == needle[j]) {
j++
}
}
return j == needle.length
}
You only need to loop through each character in haystack string and advance the pointer in needle string when you find a matching character. If the pointer reaches the end of the needle string, it means the needle string can be found as a subsequence of the haystack string.
A small optimization you can do is checking needle.length <= haystack.length before starting the loop.
Just for fun
If you want to go the Cthulhu's way, you can use this construction:
(?>.*?t)(?>.*?e)(?>.*?s)(?>.*?t).*+
This doesn't have the risk of catastrophic backtracking, and should work similar to the loop above (linear complexity), except that it has a lot of overhead compiling and matching the regex.
It's not that hard to just use a loop.
String x = "test";
String s = "tastaegasghet";
int index = 0;
for(int i = 0; i < s.length() && index < x.length(); i++){
if(s.charAt(i) == x.charAt(index)) index++;
}
boolean exists = index == x.length();
System.out.println(exists);
This should be significantly faster than a regex, at least for longer input.
I'd make a simple function, with a loop, instead of a regex. Something like the following:
public boolean containsLetters(string a, string b)
{
char[] aArray = a.toCharArray();
char[] bArray = b.toCharArray();
int lettersFound = 0, lastLocation = 0;
for (int i = 0; i < aArray.length; i++)
{
for (lastLocation=lastLocation; lastLocation < bArray.length; lastLocation++)
{
if (aArray[i] == bArray[lastLocation])
{
lettersFound++;
break;
}
}
}
return lettersFound == aArray.length;
}
The inner for loop stops the first time it finds the letter. It doens't need to determine if it appears more than once since the function returns a boolean, so this saves some time for large strings. It will only return true if it finds them in order. It remembers the index of the last letter it found, and searches through for the next letter from that location.
You can use the Pattern class for this.
String x= "yourValue";
Pattern pattern = Pattern.compile(Mention your pattern here);
Matcher matcher = pattern.matcher(x);
if (matcher.find()) {
System.out.println(matcher.group(0)); //prints /{item}/
} else {
System.out.println("Match not found");
}
Java code without using any built-in function
String s1 = "test";
String s2 = "tastaegasghets";
char ch[] = new char[s1.length()];
char ch1[] = new char[s2.length()];
int k = 0;
for (int i = 0; i < s1.length(); i++) {
ch[i] = s1.charAt(i);
for (int j = 0; j < s2.length(); j++) {
ch1[j] = s2.charAt(j);
if (ch[i] == ch1[j]) {
k++;
break;
}
}
}
if (k == s1.length()) {
System.out.println("true");
} else {
System.out.println("false");
}

Dynamic programming-memoization

I am working on a DP problem in which a string of words with space removed, and I need to implement both buttom-up and memoization version to split the string into individual english words. However, I got the buttom-up version, however, the memoization seems a little complicated.
/* Split a string into individual english words
* #String str the str to be splitted
* #Return a sequence of words separated by space if successful,
null otherwise
*/
public static String buttom_up_split(String str){
int len = str.length();
int[] S = new int[len+1];
/*Stores all the valid strings*/
String[] result = new String[len+1];
/*Initialize the array*/
for(int i=0; i <= len; i++){
S[i] = -1;
}
S[0] =0;
for(int i=0; i < len; i++){
if(S[i] != -1){
for(int j= i+1; j <= len; j++){
String sub = str.substring(i, j);
int k = j;
if(isValidEnglishWord(sub)){
S[k] = 1; //set true indicates a valid split
/*Add space between words*/
if(result[i] != null){
/*Add the substring to the existing words*/
result[i+ sub.length()] = result[i] + " " + sub;
}
else{
/*The first word*/
result[i+ sub.length()] = sub;
}
}
}
}
}
return result[len]; //return the last element of the array
}
I really confused how to convert this buttom_up_version to the memoized version, hope someone can help..
Well, I'm not an export of memoization, but the idea is to have a "memory" of previous good english words.
The objective is to save computation time: in your case, the call to isValidEnglishWord().
Therefore, you need to adapt your alorythm this way:
walk through the 'str' string
extract a substring from it
checkif the substring is a valid word in your memory.
It's in memory: add a space and the word to your result.
It's not in memory: calls isValidEnglishWord and process its return.
It will give something like (not tested nor compiled)
// This is our memory
import java.util.*
private static Map<String, Boolean> memory = new HashMap<String, Boolean>()
public static String buttom_up_split(String str){
int len = str.length();
int[] S = new int[len+1];
String[] result = new String[len+1];
for(int i=0; i <= len; i++){
S[i] = -1;
}
S[0] =0;
for(int i=0; i < len; i++){
if(S[i] != -1){
for(int j= i+1; j <= len; j++){
String sub = str.substring(i, j);
int k = j;
// Order is significant: first look into memory !
Boolean isInMemory = memory.contains(sub);
if (isInMemory || isValidEnglishWord(sub)){
S[k] = 1;
if(result[i] != null){
// Memoize the result if needed.
if (!isInMemory) {
memory.put(sub, true);
}
result[i+ sub.length()] = result[i] + " " + sub;
} else {
result[i+ sub.length()] = sub;
}
}
}
}
}
return result[len];
}
Personally I always prefer to use memoization as transparently as possible without modifying the algorithm. This is because I want to be able to test the algorithm separately from memoization. Also I am working on a memoization library in which you only have to add #Memoize to methods to which memoization is applicable. But unfortunately this will come too late for you.
The last time I used memoization (without my library) I implemented it using a proxy class. An important remark is that this implementation does not support recursion. But this shouldn't be a problem since your algorithm is not recursive.
Some other references are:
wikipedia
Java implementation
memoize using proxy class
Remark about your algorithm:
How do you handle words that have other words in them? like "verbose" contains "verb", "theory" contains "the" etc...

Categories