How to add string in the last foreach item? - java

I want to append certain string in the last item of the foreach array.
The program works perfectly fine. Given the items in the "pending" array, it should append the out value in the last item in the pending value:
String a = out + "-" + rptdate + "-";
for (String pn : pending) {
//checks if total value + pending length value is less than 160
if (a.length() + pn.length() < 160) { // < to leave room for the comma as well
if (a.length() != 0) {
if (a.length() != 14) {
a += ",";
}
}
a += pn;
} else {
resultingStrings.add(a);
a = pn;
Log.d("messages", a);
}
}
resultingStrings.add(a);
for (String r : resultingStrings) {
sendSMS(r);
}

Try simple code
int size = pending.size();
int index = 0;
for (String pn : pending) {
if(index == size - 1){
// it is last foreach => add your last string here
}
index++;
...
}
Hope this help

You could also do,
for(int i = 0; i < array.length; i++) {
if(i = (array.length - 1)) {
//this is the last element in the array
}
}

If all you need to do is grab the last element of a Collection and append some text to it then this should work.
String out = "Some value";
int lastIndex = pending.getSize() -1; // < 0 indexed
String lastItem = pending.get(lastIndex)
String newLastItem = lastItem + out; // < String concatenation
but from your snippet I don't think that's what your after because if we remove some of the magic numbers and correct the indentation, and make some assumptions about what your trying to do your left with
String a = out + "-" + rptdate + "-";
int prefixLength = a.length();
for (String pn : pending) {
//checks if total value + pending length value is less than 160
if (a.length() + pn.length() < MAX_LENGTH) { // < to leave room for the comma as well
if (a.length() > prefixLength) {
a += ",";
}
a += pn;
} else {
// have string longer than max length, so save and start a new sms.
resultingStrings.add(a);
Log.d("messages", a); // < log a before you overwrite it.
a = pn;
}
}
// DO YOU WANT TO APPEND out AS A SUFFIX TO a HERE ???
// a += out;
// but if so youll want to consider the case if a is now > MAX_LENGTH
resultingStrings.add(a); // add the last string
// send all composed strings
for (String r : resultingStrings) {
sendSMS(r);
}
I am picking your relatively new to coding so I'd suggest first you start off with some pseudo-code of what your trying to do, it can then become comments in your code. Always keep your code formatted nicely so that indents are matched, and use descriptive names for your variables, and constants.

Related

Find n:th word in a string

I'm trying to find nth word in a string. I am not allowed to use StringToknizer or split method from String class.
I now realize that I can use white space as a separator. The only problem is I don't know how to find the location of the first white space.
public static String pick(String message, int number){
String lastWord;
int word = 1;
String result = "haha";
for(int i=0; i<message.length();i++){
if(message.charAt(i)==' '){enter code here
word++;
}
}
if(number<=word && number > 0 && number != 1){//Confused..
int space = message.indexOf(" ");//improve
int nextSpace = message.indexOf(" ", space + 1);//also check dat
result = message.substring(space,message.indexOf(' ', space + 1));
}
if(number == 1){
result = message.substring(0,message.indexOf(" "));
}
if(number>word){
lastWord = message.substring(message.lastIndexOf(" ")+1);
return lastWord;
}
else return result;
}
The current implementation is overcomplicated, hard to understand.
Consider this alternative algorithm:
Initialize index = 0, to track your position in the input string
Repeat n - 1 of times:
Skip over non-space characters
Skip over space characters
At this point you are at the start of the n-th word, save this to start
Skip over non-space characters
At this point you are just after the end of the n-th word
Return the substring between start and end
Like this:
public static String pick(String message, int n) {
int index = 0;
for (int i = 1; i < n; i++) {
while (index < message.length() && message.charAt(index) != ' ') index++;
while (index < message.length() && message.charAt(index) == ' ') index++;
}
int start = index;
while (index < message.length() && message.charAt(index) != ' ') index++;
return message.substring(start, index);
}
Note that if n is higher than there are words in the input,
this will return empty string.
(If that's not what you want, it should be easy to tweak.)
CHEAT (using regex)1
public static String pick(String message, int number){
Matcher m = Pattern.compile("^\\W*" + (number > 1 ? "(?:\\w+\\W+){" + (number - 1) + "}" : "") + "(\\w+)").matcher(message);
return (m.find() ? m.group(1) : null);
}
Test
System.out.println(pick("This is a test", 1));
System.out.println(pick("! This # is # a $ test % ", 3));
System.out.println(pick("This is a test", 5));
Output
This
a
null
1) Only StringTokenizer and split are disallowed ;-)
This needs some edge case handling (e.g. there are fewer than n words), but here's the idea I was getting at. This is similar to your solution, but IMO less elegant than janos'.
public static String pick(String message, int n) {
int wordCount = 0;
String word = "";
int wordBegin = 0;
int wordEnd = message.indexOf(' ');
while (wordEnd >= 0 && wordCount < n) {
word = message.substring(wordBegin, wordEnd).trim();
message = message.substring(wordEnd).trim();
wordEnd = message.indexOf(' ');
wordCount++;
}
if (wordEnd == -1 && wordCount + 1 == n) {
return message;
}
if (wordCount + 1 < n) {
return "Not enough words to satisfy";
}
return word;
}
Most iteration in Java can now be replaced by streams. Whether this is an improvement is a matter of (strong) opinion.
int thirdWordIndex = IntStream.range(0, message.size() - 1)
.filter(i -> Character.isWhiteSpace(message.charAt(i)))
.filter(i -> Character.isLetter(message.charAt(i + 1)))
.skip(2).findFirst()
.orElseThrow(IllegalArgumentException::new) + 1;

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
}

Is there something wrong with my binary search algorithm?

I'm writing a program where you can enter a words which will get stored in an ArrayList. You can then search for these words, by entering them in a textField and pressing a button. (You can also sort them, if pressing another button). If the word is found the place in the ArrayList of the word should be printed out and if it's not found that should be printed out. I thought this worked until just recently when I tested it (it have worked before): I entered a word I knew was in the ArrayList which made it print out the position of the word in the ArrayList (which is what I want it to do). I then entered a word which I knew didn't exist in the ArrayList which made it print out that the word doesn't exist (which is also what I want it to do). But when I after that searched for a word I knew existed in the ArrayList, it printed out that the word couldn't be found. I then tried this with another word I knew existed in the ArrayList, but I couldn't find that either. I have after this restarted the program several times and sometimes it works and sometimes it doesn't and I have no idea why or why not...
The array gets sorted before I run the algorithm so I know that's not the problem...
Down below is the class with my search algorithm:
public class SearchAlg {
public static String binary (ArrayList<String> list, String user) {
int first = 0;
int found = 0;
int middle = 0;
int last = list.size();
String strFound = "";
while (first < last && found == 0) {
middle = ((first + last) / 2);
if (user.compareTo(list.get(middle)) > 0) {
first = middle + 1;
} else if (user.compareTo(list.get(middle)) == 0) {
found = 1;
} else if (user.compareTo(list.get(middle)) < 0) {
last = middle - 1;
}
}
if (found == 1) {
strFound = "The word " + user + " exists on the place " + middle + " in the Arraylist";
} else {
strFound = "The word " + user + " does not exist in the Arraylist";
}
return strFound;
}
}
Here is my sorting algorithm:
public class Sort {
static private String strTemp;
static private int i;
static private int n;
public static ArrayList bubbelSort (ArrayList<String> list) {
for (i = 0; i < list.size(); i++) {
for (n = 0; n < list.size() - i - 1; n++) {
if (list.get(n).compareTo(list.get(n + 1)) > 0) {
strTemp = list.get(n);
list.set(n, list.get(n + 1));
list.set(n + 1, strTemp);
}
}
}
return list;
}
And this is my Main class:
ArrayList<String> list = new ArrayList();
private void btnEnterActionPerformed(java.awt.event.ActionEvent evt) {
txtaOutput.setText("");
String wrd = txtfEnter.getText();
list.add(wrd);
for (int i = 0; i < list.size(); i++) {
txtaOutput.append(list.get(i) + "\n");
}
}
private void btnSortActionPerformed(java.awt.event.ActionEvent evt) {
txtaOutput.setText("");
Sort.bubbelSort(list);
}
private void btnSearchActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
String user = txtfSearch.getText();
txtaOutput.setText("");
String bin = SearchAlg.binary(list, user);
txtaOutput.append(bin);
}
I have no idea what's causing this, so any help is appreciated!
EDIT: I now know that the problem is that the first item in the ArrayList ins't searchable. So if the ArrayList consists of a, b, c for example, then only b and c are searchable. If I try and search for a, it says that it can't be found.
int first= 0;
int last= a.length - 1;
while (first<= last) {
int middle = first+ (last- first) / 2;
if (user.compareTo(list.get(middle)) < 0) last = middle - 1;
else if (user.compareTo(list.get(middle)) > 0) first= middle + 1;
else {
found =1 ;
break;
}
}
and don't forget to sort your list as mentioned in the previous post
The problem is in the very last step of your search. There is a chance you update the 'first' and 'last', and in the next iteration you would find the value, but instead you break from the loop.
Solution: remove the variable found entirely, and also these two lines:
} else if (user.compareTo(list.get(middle)) == 0) {
found = 1;
and where you now write...
if (found == 1) {
...instead do...
if (user.compareTo(list.get(first)) == 0) {
You're off by one.
You initialize the method with last = list.size(), implying that you're searching the half open interval [first, last> (from and including first, to but excluding last).
However, in your loop, you set last = middle - 1, which would work if your search range was the closed interval [first, last] (from and including first, to and including last).
You should make up your mind as to whether last should point on the last element, or after the last element. Here's your loop if you go with the latter:
while (first < last && found == 0) {
middle = ((first + last) / 2);
if (user.compareTo(list.get(middle)) > 0) {
first = middle + 1;
} else if (user.compareTo(list.get(middle)) == 0) {
found = 1;
} else if (user.compareTo(list.get(middle)) < 0) {
last = middle; // <-- Remove -1
}
}

Substring between two same or different delimiters (when delimiters occur multiple times)

I need to fetch a sub string that lies between two same or different delimiters. The delimiters will be occurring multiple times in the string, so i need to extract the sub-string that lies between mth occurrence of delimiter1 and nth occurrence of delimiter2.
For eg:
myString : Ron_CR7_MU^RM^_SAF_34^
What should i do here if i need to extract the sub-string that lies between 3rd occurrence of '_' and 3rd occurence of '^'?
Substring = SAF_34
Or i could look for a substring that lies between 2nd '^' and 4th '_', i.e :
Substring = _SAF
An SQL equivalent would be :
substr(myString, instr(myString, '',1,3)+1,instr(myString, '^',1,3)-1-instr(myString, '',1,3))
I would use,
public static int findNth(String text, String toFind, int count) {
int pos = -1;
do {
pos = text.indexOf(toFind, pos+1);
} while(--count > 0 && pos >= 0);
return pos;
}
int from = findNth(text, "_", 3);
int to = findNth(text, "^", 3);
String found = text.substring(from+1, to);
If you can use a solution without regex you can find indexes in your string where your resulting string needs to start and where it needs to end. Then just simply perform: myString.substring(start,end) to get your result.
Biggest problem is to find start and end. To do it you can repeat this N (M) times:
int pos = indexOf(delimiterX)
myString = myString.substring(pos) //you may want to work on copy of myString
Hope you get an idea.
You could create a little method that simply hunts for such substrings between delimiters sequentially, using (as noted) String.indexOf(string); You do need to decide whether you want all substrings (whether they overlap or not .. which your question indicates), or if you don't want to see overlapping strings. Here is a trial for such code
import java.util.Vector;
public class FindDelimitedStrings {
public static void main(String[] args) {
String[] test = getDelimitedStrings("Ron_CR7_MU'RM'_SAF_34'", "_", "'");
if (test != null) {
for (int i = 0; i < test.length; i++) {
System.out.println(" " + (i + 1) + ". |" + test[i] + "|");
}
}
}
public static String[] getDelimitedStrings(String source,
String leftDelimiter, String rightDelimiter) {
String[] answer = null;
;
Vector<String> results = new Vector<String>();
if (source == null || leftDelimiter == null || rightDelimiter == null) {
return null;
}
int loc = 0;
int begin = source.indexOf(leftDelimiter, loc);
int end;
while (begin > -1) {
end = source
.indexOf(rightDelimiter, begin + leftDelimiter.length());
if (end > -1) {
results.add(source.substring(begin, end));
// loc = end + rightDelimiter.length(); if strings must be
// returned as pairs
loc = begin + 1;
if (loc < source.length()) {
begin = source.indexOf(leftDelimiter, loc);
} else {
begin = -1;
}
} else {
begin = -1;
}
}
if (results.size() > 0) {
answer = new String[results.size()];
results.toArray(answer);
}
return answer;
}
}

Checking if a string matches all characters but one of another string

I have a list of strings and with each string I want to check it's characters against every other string to see if all it's characters are identical except for one.
For instance a check that would return true would be checking
rock against lock
clock and flock have one character that is different, no more no less.
rock against dent will obviously return false.
I have been thinking about first looping through the list and then having a secondary loop within that one to check the first string against the second.
And then using split(""); to create two arrays containing the characters of each string and then checking the array elements against each other (i.e. comparing each string with the same position in the other array 1-1 2-2 etc...) and so long as only one character comparison fails then the check for those two strings is true.
Anyway I have a lot of strings (4029) and considering what I am thinking of implementing at the moment would contain 3 loops each within the other that would result in a cubic loop(?) which would take a long long time with that many elements wouldn't it?
Is there an easier way to do this? Or will this method actually work okay? Or -hopefully not- but is there some sort of potential logical flaw in the solution I have proposed?
Thanks a lot!
Why not do it the naive way?
bool matchesAlmost(String str1, String str2) {
if (str1.length != str2.length)
return false;
int same = 0;
for (int i = 0; i < str1.length; ++i) {
if (str1.charAt(i) == str2.charAt(i))
same++;
}
return same == str1.length - 1;
}
Now you can just use a quadratic algorithm to check every string against every other.
Assuming the length of two strings are equal
String str1 = "rock";
String str2 = "lick";
if( str1.length() != str2.length() )
System.out.println( "failed");
else{
if( str2.contains( str1.substring( 0, str1.length()-1)) || str2.contains( str1.substring(1, str1.length() )) ){
System.out.println( "Success ");
}
else{
System.out.println( "Failed");
}
}
Not sure if this is the best approach but this one works even when two strings are not of same length. For example : cat & cattp They differ by one character p and t is repeated. Looks like O(n) time solution using additional space for hashmap & character arrays.
/**
* Returns true if two strings differ by one character
* #param s1 input string1
* #param s2 input string2
* #return true if strings differ by one character
*/
boolean checkIfTwoStringDifferByOne(String s1, String s2) {
char[] c1, c2;
if(s1.length() < s2.length()){
c1 = s1.toCharArray();
c2 = s2.toCharArray();
}else{
c1 = s2.toCharArray();
c2 = s1.toCharArray();
}
HashSet<Character> hs = new HashSet<Character>();
for (int i = 0; i < c1.length; i++) {
hs.add(c1[i]);
}
int count = 0;
for (int j = 0; j < c2.length; j++) {
if (! hs.contains(c2[j])) {
count = count +1;
}
}
if(count == 1)
return true;
return false;
}
Assuming that all the strings have the same length, I think this would help:
public boolean differByOne(String source, String destination)
{
int difference = 0;
for(int i=0;i<source.length();i++)
{
if(source.charAt(i)!=destination.charAt(i))
{
difference++;
if(difference>1)
{
return false;
}
}
}
return difference == 1;
}
Best way is to concatenate strings together one forward and other one in reverse order. Then check in single loop for both ends matching chars and also start from middle towards ends matching char. If more than 2 chars mismatch break.
If one mismatch stop and wait for the next one to complete if it reaches the same position then it matches otherwise just return false.
public static void main(String[] args) {
New1 x = new New1();
x.setFunc();
}
static void setFunc() {
Set s = new HashSet < Character > ();
String input = " aecd";
String input2 = "abcd";
String input3 = new StringBuilder(input2).reverse().toString();
String input4 = input.concat(input3);
int length = input4.length();
System.out.println(input4);
int flag = 0;
for (int i = 1, j = length - 1; j > i - 1; i++, j--) {
if (input4.charAt(i) != input4.charAt(j)) {
System.out.println(input4.charAt(i) + " doesnt match with " + input4.charAt(j));
if (input4.charAt(i + 1) != input4.charAt(j)) {
System.out.println(input4.charAt(i + 1) + " doesnt match with " + input4.charAt(j));
flag = 1;
continue;
} else if (input4.charAt(i) != input4.charAt(j - 1)) {
System.out.println(input4.charAt(i) + " doesnt match with " + input4.charAt(j - 1));
flag = 1;
break;
} else if (input4.charAt(i + 1) != input4.charAt(j - 1) && i + 1 <= j - 1) {
System.out.println(input4.charAt(i + 1) + " doesnt match with xxx " + input4.charAt(j - 1));
flag = 1;
break;
}
} else {
continue;
}
}
if (flag == 0) {
System.out.println("Strings differ by one place");
} else {
System.out.println("Strings does not match");
}
}

Categories

Resources