implementation for java substring with negative values - java

in java,
String month= "November 2014";
for making a substring giving the index from right hand side, I cannot use
someString.substring(-4);
as negative values are not supported.
Is there any simple implementation I can use to achieve this.

No, negative numbers are not allowed (it would throw a StringIndexOutOfBoundsException). You can use this:
if(month.length() >= 4) {
year = month.substring(month.length() - 4);
}

I love Python's indexing and prefer to be able to use it in Java as well ;)
A general implementation of substring with support for negative indexing could be implemented like this:
A method for converting negative indexes to their positive equivalent is useful:
private static int toPosIndex(String str, int index) {
if (index >= 0) return index;
else return str.length() + index;
This method can then be used to declare a substring method with support for negative indexes:
public static String negSubstring(String str, int index1, int index2) {
return str.substring(toPosIndex(str, index1), toPosIndex(str, index2));
}
and if needed an equivalent to the version of substring with only one index parameter:
public static String negSubstring(String str, int index) {
return str.substring(toPosIndex(str, index));
}
(I realise the question is more than two years old, but figured that other new users might be interested in a general answer to the question).

Related

Count the Characters in a String Recursively & treat "eu" as a Single Character

I am new to Java, and I'm trying to figure out how to count Characters in the given string and threat a combination of two characters "eu" as a single character, and still count all other characters as one character.
And I want to do that using recursion.
Consider the following example.
Input:
"geugeu"
Desired output:
4 // g + eu + g + eu = 4
Current output:
2
I've been trying a lot and still can't seem to figure out how to implement it correctly.
My code:
public static int recursionCount(String str) {
if (str.length() == 1) {
return 0;
}
else {
String ch = str.substring(0, 2);
if (ch.equals("eu") {
return 1 + recursionCount(str.substring(1));
}
else {
return recursionCount(str.substring(1));
}
}
}
OP wants to count all characters in a string but adjacent characters "ae", "oe", "ue", and "eu" should be considered a single character and counted only once.
Below code does that:
public static int recursionCount(String str) {
int n;
n = str.length();
if(n <= 1) {
return n; // return 1 if one character left or 0 if empty string.
}
else {
String ch = str.substring(0, 2);
if(ch.equals("ae") || ch.equals("oe") || ch.equals("ue") || ch.equals("eu")) {
// consider as one character and skip next character
return 1 + recursionCount(str.substring(2));
}
else {
// don't skip next character
return 1 + recursionCount(str.substring(1));
}
}
}
Recursion explained
In order to address a particular task using Recursion, you need a firm understanding of how recursion works.
And the first thing you need to keep in mind is that every recursive solution should (either explicitly or implicitly) contain two parts: Base case and Recursive case.
Let's have a look at them closely:
Base case - a part that represents a simple edge-case (or a set of edge-cases), i.e. a situation in which recursion should terminate. The outcome for these edge-cases is known in advance. For this task, base case is when the given string is empty, and since there's nothing to count the return value should be 0. That is sufficient for the algorithm to work, outcomes for other inputs should be derived from the recursive case.
Recursive case - is the part of the method where recursive calls are made and where the main logic resides. Every recursive call eventually hits the base case and stars building its return value.
In the recursive case, we need to check whether the given string starts from a particular string like "eu". And for that we don't need to generate a substring (keep in mind that object creation is costful). instead we can use method String.startsWith() which checks if the bytes of the provided prefix string match the bytes at the beginning of this string which is chipper (reminder: starting from Java 9 String is backed by an array of bytes, and each character is represented either with one or two bytes depending on the character encoding) and we also don't bother about the length of the string because if the string is shorter than the prefix startsWith() will return false.
Implementation
That said, here's how an implementation might look:
public static int recursionCount(String str) {
if(str.isEmpty()) {
return 0;
}
return str.startsWith("eu") ?
1 + recursionCount(str.substring(2)) : 1 + recursionCount(str.substring(1));
}
Note: that besides from being able to implement a solution, you also need to evaluate it's Time and Space complexity.
In this case because we are creating a new string with every call time complexity is quadratic O(n^2) (reminder: creation of the new string requires allocating the memory to coping bytes of the original string). And worse case space complexity also would be O(n^2).
There's a way of solving this problem recursively in a linear time O(n) without generating a new string at every call. For that we need to introduce the second argument - current index, and each recursive call should advance this index either by 1 or by 2 (I'm not going to implement this solution and living it for OP/reader as an exercise).
In addition
In addition, here's a concise and simple non-recursive solution using String.replace():
public static int count(String str) {
return str.replace("eu", "_").length();
}
If you would need handle multiple combination of character (which were listed in the first version of the question) you can make use of the regular expressions with String.replaceAll():
public static int count(String str) {
return str.replaceAll("ue|au|oe|eu", "_").length();
}

Why use bit shifting instead of a for loop?

I created the following code to find parity of a binary number (i.e output 1 if the number of 1's in the binary word is odd, output 0 if the number of 1's is even).
public class CalculateParity {
String binaryword;
int totalones = 0;
public CalculateParity(String binaryword) {
this.binaryword = binaryword;
getTotal();
}
public int getTotal() {
for(int i=0; i<binaryword.length(); i++) {
if (binaryword.charAt(i) == '1'){
totalones += 1;
}
}
return totalones;
}
public int calcParity() {
if (totalones % 2 == 1) {
return 1;
}
else {
return 0;
}
}
public static void main(String[] args) {
CalculateParity bin = new CalculateParity("1011101");
System.out.println(bin.calcParity());
}
}
However, all of the solutions I find online almost always deal with using bit shift operators, XORs, unsigned shift operations, etc., like this solution I found in a data structure book:
public static short parity(long x){
short result = 0;
while (x != 0) {
result A=(x&1);
x >>>= 1;
}
return result;
}
Why is this the case? What makes bitwise operators more of a valid/standard solution than the solution I came up with, which is simply iterating through a binary word of type String? Is a bitwise solution more efficient? I appreciate any help!
The code that you have quoted uses a loop as well (i.e., while):
public static short parity(long x){
short result = 9;
while (x != 9) {
result A=(x&1);
x >>>= 1;
}
return result;
}
You need to acknowledge that you are using a string that you know beforehand will be composed of only digits, and conveniently in a binary representation. Naturally, given those constraints, one does not need to use bitwise operations instead one just parsers char-by-char and does the desired computations.
On the other hand, if you receive as a parameter a long, as the method that you have quoted, then it comes in handy to use bitwise operations to go through each bit (at a time) in a number and perform the desired computation.
One could also convert the long into a string and apply the same logic code-wise that you have applied, but first, one would have to convert that long into binary. However, that approach would add extra unnecessary steps, more code, and would be performance-wise worse. Probably, the same applies vice-versa if you have a String with your constraints. Nevertheless, a String is not a number, even if it is only composed of digits, which makes using a type that represents a number (e.g., long) even a more desirable approach.
Another thing that you are missing is that you did some of the heavy lifting by converting already a number to binary, and encoded into a String new CalculateParity("1011101");. So you kind of jump a step there. Now try to use your approach, but this time using "93" and find the parity.
If you want know if a String is even. I think this method below is better.
If you convert a String too
long which the length of the String is bigger than 64. there will a error occur.
both of the method you
mention is O(n) performance.It will not perform big different. but
the shift method is more precise and the clock of the cpu use will a little bit less.
private static boolean isEven(String s){
char[] chars = s.toCharArray();
int i = 0;
for(char c : chars){
i ^= c;
}
return i == 0;
}
You use a string based method for a string input. Good choice.
The code you quote uses an integer-based method for an integer input. An equally good choice.

C++ vs Java Memoization Discrepancy [duplicate]

This question already has answers here:
What is a debugger and how can it help me diagnose problems?
(2 answers)
Closed 4 years ago.
So I've been trying to solve the word break Dynamic Programming problem, which basically means that given a dictionary of strings and a string, see if the words in the dictionary can be combined to form the string. For example, given word "applepenapple" and dictionary ["apple","pen"] it should return true.
I have a working java solution, but I'm trying to improve my C++ skills. My problem is even though my code looks extremely similar to the working solution in Java, I am failing a niche test case and I can't figure out why.
C++ code:
bool wordBreak(string s, vector<string> &wordDict) {
vector<int> bArr(s.length(), -1);
unordered_set<string> set(wordDict.begin(), wordDict.end());
return wordBreak(s, bArr, 0, set);
}
bool wordBreak(string s, vector<int> &bArr, int start, unordered_set<string> &set) {
if (start == s.length())
return true;
//If we have a memoized solution to this problem, avoid recurion
if (bArr[start] != -1)
return (bArr[start] == 1);
for (int end = start + 1; end <= s.length(); end++) {
if (set.count(s.substr(start, end)) && wordBreak(s, bArr, end, set)) {
bArr[start] = 1;
return bArr[start] == 1;
}
}
bArr[start] = 0;
return false;
}
Working code using java:
public boolean wordBreak(String s, List<String> wordDict) {
Integer[] memo =new Integer[s.length()];
Arrays.fill(memo,-1);
return word_Break(s, new HashSet(wordDict), 0, memo);
}
public boolean word_Break(String s, Set<String> wordDict, int start, Integer[] memo) {
if (start == s.length()) {
return true;
}
if (memo[start] != -1) {
return memo[start]==1;
}
for (int end = start + 1; end <= s.length(); end++) {
if (wordDict.contains(s.substring(start, end)) && word_Break(s, wordDict, end, memo)) {
memo[start] = 1;
return memo[start] == 1;
}
}
memo[start] = 0;
return false;
}
The C++ code is returning false for "applepenapple" with dictionary ["apple","pen"] and I don't know why since the java return true which is correct. The only major difference (I think) between the two solutions is that my C++ uses a vector instead of a native array in the java code. Initially I thought it might have to do with C++ using automatic storage (stack) vs the free store (heap) which is why I used the vector instead of a C-style array to avoid memory management because of RAII. Despite this change, the bug persists. There is an easier solution avoiding recursion altogether, but I am very curious as to why the C++ is returning different output than the java.
I see a potential problem. From java.lang.String Javadoc (emphasis mine):
public String substring(int beginIndex, int endIndex)
Returns a new string that is a substring of this string. The substring begins at the specified beginIndex and extends to the character at index endIndex - 1. Thus the length of the substring is endIndex-beginIndex.
Examples:
"hamburger".substring(4, 8) returns "urge"
"smiles".substring(1, 5) returns "mile"
Parameters:
beginIndex - the beginning index, inclusive.
endIndex - the ending index, exclusive.
From cppreference.com documentation on strings:
basic_string substr( size_type pos = 0, size_type count = npos ) const;
Returns a substring [pos, pos+count). If the requested substring extends past the end of the string, or if count == npos, the returned substring is [pos, size()).
Parameters
pos - position of the first character to include
count - length of the substring
That is, in Java you should pass an index as second parameter to String.substring(...), but in C++ you should pass a length to basic_string::substr(...). However, you are doing:
s.substr(start, end)
and
s.substring(start, end)
in both cases.
Maybe adjusting the C++ invocation to
s.substr(start, end - start)
will work?

How can I use recursion to count the occurrences of a substring in Java?

I need to count the occurrences of a substring in a larger string in Java using recursion. I get the idea of recursion, but I'm not sure how it applies to problems like these. Does anyone know how to do this?
I have a lot of similar problems too. Any advice for solving a general problem recursively? My biggest concern is finding the base case.
Thanks!
There's no really general way of doing it, I don't think. But here's how I'd do it for this problem:
You wouldn't actually solve this using recursion (in Java, at least). You'd write something like this:
int countOccurrences(String str, String search) {
int count = 0;
int i = 0;
while (true) {
i = str.indexOf(search, i);
if (i == -1) {
break;
} else {
count += 1;
i += search.length();
}
}
return count;
}
So, you can rewrite this as a tail recursion, something like:
int countOccurrences(String str, String search) {
return recurse(str, search, 0, 0);
}
int recurse(String str, String search, int count, int i) {
i = str.indexOf(search, i);
if (i == -1) {
// Like the while loop where i == -1, i.e. no more occurrences found.
// Break the recursion.
return count;
} else {
// Like the while loop where i != -1: an occurrence was found.
// Increment count, and keep on searching.
return recurse(str, search, count + 1, i + search.length());
}
}
Hopefully you can see the commonality between the loop and recursive approaches.
Note that you don't need to write a tail recursion: you can write a non-tail recursion by dropping the count parameter from the recurse method, and making the non-terminal case:
return 1 + recurse(str, search, i + search.length());
It doesn't make too much of a difference in Java, which doesn't perform tail call optimization, but the tail recursive form may be more efficient in other languages (where it can be converted back into a loop, as above).

Alternating string of char and int [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
when given a input string i am suppose to break it up into two groups
char
int.
with these two groups i want to create a new alternating string.
for example
abc1234defgh567jk89
will transform into
a1b2c3d5e6f7j8k9
notice that the digit 4,g,h has been discarded.
i figured that a queue can be implemented in this case.
queue1> abc
queue2> 123
index 0 to 2 is a char
index three is a int, so for queue 2 we only take in 3 values.
my question is there a more efficient data structure to perform this operation?
and during implementation, how to i compare to see if a particular value is a int or a char?
please advise.
Treating the string as an array of char integers would make this easier to compare, as you can do a simple comparision on the entry. If array[x]>64 it is a character else it is a number. You can use two pointers to do the interleaving. One for character and the other for integer. Find a character and then advance the integer pointer until it finds a match, then advance them as long as they are both true, then fast forward both of them. For example:
char array[]=(char *)string;
int letter=array[0];
int number=array[0];
// Initialize
while(number >= 64)
number++;
while (letter<64)
letter++;
//Now that the pointers are initialized, interleave them.
while(letter>=64 && number<64)
{
output[i++]=letter;
output[i++]=number;
number++;
letter++;
}
// Now you need to advance to the next batch, so you need to see the comparison false and then true again.
....
You are right, a queue is a good data structure for this problem. If, however, you want fancier methods at hand, a Linked List would be another very similar alternative.
To check if a particular value is a letter or a number, you can use the Character class. For example,
String sample = "hello1";
Character.isLetter( sample.charAt(0) ); // returns true
Character.isLetter( sample.charAt(5) ); // returns false
how to i compare to see if a particular value is a int or a char?
You can do something like this:
String string = "abc1234defgh567jk89";
for(int i=0; i<string.length;i++){
int c = (int)string.charAt(i);
boolean isChar = 97<=c&&c<=122 || 65<=c&&c<=90;
boolean isNum = 48<=c&&c<=57;
if(!isChar && !isNum){
throw new IllegalArgumentException("I don't know what you are")
}
}
About the datastructutures, personally I will use two single linked list, one for chars and one for numbers and every character will be stored in a different node. Why?, well if you store the characters (in general, I mean chars and ints) in groups of threes later you will have to add more code to split those groups and put chars and ints together, putting them in a linked list makes sense because
you can put as much nodes as you want (or memory lets you but let's assume is infinite)
data will be stored in order (which looks like some kind of requirement you have in order to display the output, also this discards trees and stacks(FILO))
since you only need to go forward when generating the output a double linked list will be over engineering.
To generate the output:
Having two datastructures let's you add another check like:
if(listChars.size() != listNums.size()){
throw new IllegalArgumentException("Wrong input!!!")
}
Additionally,
Reviewing the list will take you O(n) time, memory used will be O(n), reviewing both list will take you O(n/m) where m is the size of the initial group of chars.
You can do that like this:
Iterator<Character> iterChar = listChar.iterator();
Iterator<Integer> iterNum = listChar.iterator();
String result = "";
while(iterChar.hasNext() && iterNum.hasNext() ){
result+=iterChar.next()+iterNum.next();
}
Finally, you can use queues or linked list here both give you the same in this scenario
To check if the next char is a letter or number you can use this:
public static boolean isNumber(char c) { return c >= '0' && c <= '9'; }
public static boolean isLetter(char c) { return c >= 'a' && c <= 'z'; }
These functions find the index of the next number or letter, starting at pos i:
public static int nextNumber(String s, int i) {
while(i < s.length() && !isNumber(s.charAt(i))) i++;
return i;
}
public static int nextLetter(String s, int i) {
while(i < s.length() && !isLetter(s.charAt(i))) i++;
return i;
}
You don't really need a data structure, all you need is 3 pointers:
public static String alternate(String s){
// pointers
int start = 0, mid = 0, end = 0;
StringBuilder sb = new StringBuilder(s.length());
while(end < s.length()){
// E.g. for 'abc1234' {start, mid, end} = {0, 3, 7}
start = Math.min(nextLetter(s, end), nextNumber(s, end));
mid = Math.max(nextLetter(s, end), nextNumber(s, end));
end = Math.max(nextLetter(s, mid), nextNumber(s, mid));
for(int i = 0; i < Math.min(mid - start, end - mid); i++)
sb.append(s.charAt(start + i)).append(s.charAt(mid + i));
}
return sb.toString();
}
Running the example below outputs the desired result: a1b2c3d5e6f7j8k9
public static void main(String... args){
System.out.println(alternate("abc1234defgh567jk89"));
}

Categories