I'm supposed to write a simple method that returns given string for given amount, seperated by comma (and no comma in the end), with recursion. If there are less than two counts, the return is empty string "".
final static String COMMA = ", ";
public static String replicate(String s, int count) {
String answer = "";
if (count < 2) {
return answer;
}
else {
answer = s + COMMA + replicate(s, (count - 1));
return answer;
}
}
If I put s = cat and count = 5, I get cat, cat, cat, cat,- One short what I need.
I'm at my wits end here what to do, to get proper amount of repeats here without the comma at the end.
EDIT: Clearly I failed to communicate, that the method SHOULD return an empty string, if the count is two or less. Sorry for the lack of clarity there.
You're extremely close! When you hit your base case count < 2, instead of returning an empty string, you can return your input string. Be sure to check that length isn't 0, too.
EDIT: from information in the comments, you want to return an empty string for any counts less than or equal to two. Odd requirement, but this will fit that issue; it uses three as a base case instead of two, returning three s inputs concatenated together.
final static String COMMA = ", ";
public static String replicate(String s, int count) {
String answer = "";
if(count <= 2) {
return answer;
}
if(count == 3) {
return (s + COMMA + s + COMMA + s);
}
else {
answer = s + COMMA + replicate(s, (count - 1));
return answer;
}
}
Demo
Every element is there, just a bit unreadable code.
If count is 0, "".
If one, s itself.
Otherwise s, + recursive result.
So:
public static String replicate(String s, int count) {
if (count <= 0) {
return "";
} else if (count == 1) {
return s;
} else {
return s + COMMA + replicate(s, count - 1);
}
}
What lead to mental failure was the variable answer, and the two cases of < 2.
public static String replicate(String s, int count) {
if (count >= 2) {
s = s + COMMA + replicate(s, --count);
}
return s;
}
replicate("hii", 4) --> return "hii,hii, hii, hii"
COMMA + replicate("hii", 3) --> return "hii, hii, hii"
COMMA + replicate("hii", 2) --> return "hii, hii"
COMMA + replicate("hii", 1) --> return "hii"
Related
I have to create a code that can find the longest palindrome contained inside sentences. (eg. Some people like cake but I prefer pie; the longest palindrome is i prefer pi). The problem is that upon running the code it doesn't return the palindrome. I'm not sure what the problem is but if anyone can figure it out I'd appreciate you letting me know. Thanks!
Code is below...
public class Recursion6 {
static String recursion(String word, int currentLength, int x, String substring) {
String reverse =new StringBuffer(word).reverse().toString();
if(word.length() == 1 ){
return substring;
}
if(word.charAt(0) != word.charAt(x)) {
if(x == word.length() - 1) {
recursion(word.substring(1), currentLength, 1, substring);
}
x++;
recursion(word, currentLength, x, substring);
} else {
if(word.substring(0, x + 1).equalsIgnoreCase(reverse.substring(word.length() - (x+1), word.length()))) {
if(word.substring(0, x).length() > currentLength) {
currentLength = word.substring(0, x + 1).length();
substring = word.substring(0, x + 1);
}
recursion(word.substring(1), currentLength, 1, substring);
}
recursion(word.substring(1), currentLength, 1, substring);
}
return substring;
}
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
System.out.println("Enter a Sentence:");
String word=sc.nextLine();
System.out.println("The Palendrome is "+recursion(word.replaceAll(" ", ""), 1, 1, null));
sc.close();
}
}
You ignore the return value.
For example:
recursion(word, currentLength, x, substring);
There's a return value, all right. You just do nothing with it for the recursive calls. What gets returned from the outermost call is just the input to the outermost call, which is a null string.
You probably need to review how recursive activation works. The 'return' statement only returns from the current level, it does not empty the entire call stack.
Here's another approach.
First, just get all the substrings on the stack. That's what the first two recursive calls do.
Then just check each substring as the stack unwinds to see if it is a palindrome.
the private method does the actual check. It simply compares characters at both ends towards the middle.
Final output may contain white space and/or punctuation characters.
public static void main(String[] args) {
String s =
"Some people like radar, others " +
"like a man, a plan, a canal, panama!, but " +
"my favorite is 'I prefer pie'";
String res = findLongestPalindrome(s,0,s.length());
System.out.printf("'%s'%n", res);
prints
' a man, a plan, a canal, panama!, '
The method takes the string, and starting and ending indices.
public static String findLongestPalindrome(String s, int start, int end) {
String save = "";
if (end - start > 0) {
save = findLongestPalindrome(s, start + 1, end);
} else if (end > 1) {
save = findLongestPalindrome(s, 0, end - 1);
}
String temp;
if (isPalindrome(temp = s.substring(start, end))) {
if (temp.length() > save.length()) {
save = temp;
}
}
return save;
}
// iterates from the ends toward the middle.
private static boolean isPalindrome(String s) {
s = s.replaceAll("\\W+", "").toLowerCase();
int end = s.length();
for (int i = 0; i < s.length() >> 1; i++) {
if (s.charAt(i) != s.charAt(--end)) {
return false; // fast fail if any two are not equal
}
}
return true;
}
Here is my code:
private static String recString(final int i) {
return (i>0 ? i + "." + recString(i-1) : i<0? "." + recString(i+1) : "" ) ;
}
The method should return i dots and the number of dots at begin (example recString(4) returns "4....") when i>0 and just dots when i<=0 (example recString(-4) returns "...."). The condition is that I use just one return line any other modification is not allowed. All I get "4.3.2.1." when I call recString(4). I see where is the problem but cant figure out how to take variable just at the beginning and not change it ? Thanks in advance
As for a positive number you have to output the initial number only once, and you can only output that number in the 'positive' branch, you have to leave that 'positive' branch after one iteration.
A possible solution is to negate your number after you output it in your 'positive' branch and then allow the 'negative' branch to finish the job (output all the dots):
return (i > 0 ? i + recString(-i) : i < 0 ? "." + recString(i + 1) : "");
The initial code of the question author worked for non-negative numbers. The suggested sulution makes it work for positive ones too.
If non-recursive solutions are allowed, you can use
public static String recString(final int length) {
return String.format("%d%" + length + "s", length, "").replace(' ', '.');
}
Which returns "1." for length = 1, "2.." for length = 2, and so on, but fails for length < 1. If you also need the non-positive numbers, you can use:
public static String recString(final int length) {
return length < 1
? length + ""
: String.format("%d%" + length + "s", length, "").replace(' ', '.');
}
By the way: »Only one return line« could also mean that your you are allowed to write functions like the following.
public static String recString(final int length) {
String result;
// do something
return result;
}
if i value is >0 i is appended to a StringBuilder and then i dots follow otherwise i dots are appended to this StringBuilder, finally a String is returned from the our StringBuilder using toString method.
private static String recString(final int i) {
StringBuilder recString= new StringBuilder();
if (i > 0) {
recString.append(i);
for (int x = 0; x < i; x++) {
recString.append(".");
}
} else {
for (int x = 0; x > i; x--)
recString.append(".");
}
return recString.toString();
}
I am going through the Java CodeBat exercises. Here is the one I am stuck on:
Look for patterns like "zip" and "zap" in the string -- length-3, starting with 'z' and ending with 'p'. Return a string where for all such words, the middle letter is gone, so "zipXzap" yields "zpXzp".
Here is my code:
public String zipZap(String str){
String s = ""; //Initialising return string
String diff = " " + str + " "; //Ensuring no out of bounds exceptions occur
for (int i = 1; i < diff.length()-1; i++) {
if (diff.charAt(i-1) != 'z' &&
diff.charAt(i+1) != 'p') {
s += diff.charAt(i);
}
}
return s;
}
This is successful for a few of them but not for others. It seems like the && operator is acting like a || for some of the example strings; that is to say, many of the characters I want to keep are not being kept. I'm not sure how I would go about fixing it.
A nudge in the right direction if you please! I just need a hint!
Actually it is the other way around. You should do:
if (diff.charAt(i-1) != 'z' || diff.charAt(i+1) != 'p') {
s += diff.charAt(i);
}
Which is equivalent to:
if (!(diff.charAt(i-1) == 'z' && diff.charAt(i+1) == 'p')) {
s += diff.charAt(i);
}
This sounds like the perfect use of a regular expression.
The regex "z.p" will match any three letter token starting with a z, having any character in the middle, and ending in p. If you require it to be a letter you could use "z[a-zA-Z]p" instead.
So you end up with
public String zipZap(String str) {
return str.replaceAll("z[a-zA-Z]p", "zp");
}
This passes all the tests, by the way.
You could make the argument that this question is about raw string manipulation, but I would argue that that makes this an even better lesson: applying regexes appropriately is a massively useful skill to have!
public String zipZap(String str) {
//If bigger than 3, because obviously without 3 variables we just return the string.
if (str.length() >= 3)
{
//Create a variable to return at the end.
String ret = "";
//This is a cheat I worked on to get the ending to work easier.
//I noticed that it wouldn't add at the end, so I fixed it using this cheat.
int minusAmt = 2;
//The minus amount starts with 2, but can be changed to 0 when there is no instance of z-p.
for (int i = 0; i < str.length() - minusAmt; i++)
{
//I thought this was a genius solution, so I suprised myself.
if (str.charAt(i) == 'z' && str.charAt(i+2) == 'p')
{
//Add "zp" to the return string
ret = ret + "zp";
//As long as z-p occurs, we keep the minus amount at 2.
minusAmt = 2;
//Increment to skip over z-p.
i += 2;
}
//If it isn't z-p, we do this.
else
{
//Add the character
ret = ret + str.charAt(i);
//Make the minus amount 0, so that we can get the rest of the chars.
minusAmt = 0;
}
}
//return the string.
return ret;
}
//If it was less than 3 chars, we return the string.
else
{
return str;
}
}
The problem I'm trying to solve is given a string that may contain carriage returns, insert additional carriage returns such that each line does not exceed a set number of characters. Also it should try to keep a word intact if possible.
Is there a library in either Java or Scala that does what I need?
There is a BreakIterator class in the java.text package that can tell you where you could insert a line break, but it's a little complicated to use. A regular expression like this can do 80% of the job:
str += "\n"; // Needed to handle last line correctly
// insert line break after max 50 chars on a line
str = str.replaceAll("(.{1,50})\\s+", "$1\n");
The Apache commons lang library has a WordUtils class, which includes a wrap method, to wrap a long line of text to several lines of given length on word boundaries.
public static String addReturns(String s, int maxLength)
{
String newString = "";
int ind = 0;
while(ind < s.length())
{
String temp = s.substring(ind, Math.min(s.length(), ind+maxLength));
int lastSpace = temp.lastIndexOf(" ");
int firstNewline = temp.indexOf("\n");
if(firstNewline>-1)
{
newString += temp.substring(0, firstNewline + 1);
ind += firstNewline + 1;
}
else if(lastSpace>-1)
{
newString += temp.substring(0, lastSpace + 1) + "\n";
ind += lastSpace + 1;
}
else
{
newString += temp + "\n";
ind += maxLength;
}
}
return newString;
}
This will do the trick if you don't want to use regular expressions.
System.out.println(addReturns("Hi there, I'm testing to see if this\nalgorithm is going to work or not. Let's see. ThisIsAReallyLongWordThatShouldGetSplitUp", 20));
Output:
Hi there, I'm
testing to see if
this
algorithm is going
to work or not.
Let's see.
ThisIsAReallyLongWor
dThatShouldGetSplitU
p
I think you can start with something like that. Note that you will have to handle the special case when a word is more than the MAX_LINE_LENGTH.
package com.ekse.nothing;
public class LimitColumnSize {
private static String DATAS = "It was 1998 and the dot-com boom was in full effect. I was making websites as a 22 year old freelance programmer in NYC. I charged my first client $1,400. My second client paid $5,400. The next paid $24,000. I remember the exact amounts — they were the largest checks I’d seen up til that point.\n"
+ "Then I wrote a proposal for $340,000 to help an online grocery store with their website. I had 5 full time engineers at that point (all working from my apartment) but it was still a ton of dough. The client approved, but wanted me to sign a contract — everything had been handshakes up til then.\n"
+ "No prob. Sent the contract to my lawyer. She marked it up, sent it to the client. Then the client marked it up and sent it back to my lawyer. And so on, back and forth for almost a month. I was inexperienced and believed that this is just how business was done."
+ "Annoyed by my lawyering, the client eventually gave up and hired someone else.";
private static int MAX_LINE_LENGTH = 80;
private static char[] BREAKING_CHAR = {' ', ',', ';', '!', '?', ')', ']', '}'}; // Probably some others
public static void main(String[] args) {
String current = DATAS;
String result = "";
while (current.length() != 0) {
for (int i = (current.length() - 1) < MAX_LINE_LENGTH ? current.length() - 1 : MAX_LINE_LENGTH; i >= 0; i--) {
if (current.charAt(i) == '\n') {
result += current.substring(0, i);
current = current.substring(i + 1);
break;
} else if (isBreakingChar(current.charAt(i))) {
result += current.substring(0, i) + "\n";
current = current.substring(i + 1);
break;
} else if (i == 0 && (current.length() - 1) < MAX_LINE_LENGTH) {
result += current;
current = "";
} else {
// Line cannot be break, try to go to the right and find the next BREAKING_CHAR
}
}
}
System.out.println(result);
}
private static boolean isBreakingChar(char c) {
for (int i = 0; i < BREAKING_CHAR.length; ++i) {
if (c == BREAKING_CHAR[i]) {
return true;
}
}
return false;
}
}
If anybody is interested my final solution used Apache Commons WordUtils, thanks to Joni for pointing the WordUtils out to me.
private static String wrappify(String source, int lineLength, String eolMarker){
String[] lines = source.split(eolMarker);
StringBuffer wrappedStr = new StringBuffer();
for (String line : lines) {
if(line.length() <= lineLength){
wrappedStr.append(line + eolMarker);
}else{
wrappedStr.append(WordUtils.wrap(line, lineLength, eolMarker, true) + eolMarker);
}
}
return wrappedStr.replace(wrappedStr.lastIndexOf(eolMarker), wrappedStr.length(), "").toString();
}
When converting code from C++ to Java, what is an easy way to convert the std::string methods like find_last_of(), find_last_not_of, etc?
These C++ methods find an index of any of a set of characters.
Java's String class provides indexOf() and lastIndexOf(), but these find an index of a character or a string, not any of a set of characters.
For example, the code below finds the last character that is not ASCII whitespace.
size_t pos = myString.find_last_not_of( " \t\n\r" );
One option is to use Guava's CharMatcher class.
Here are tested conversions for each of the single-argument find_*_of() methods.
public int findFirstOf( String sequence, String str ) {
return CharMatcher.anyOf( str ).indexIn( sequence );
}
public int findFirstNotOf( String sequence, String str ) {
return CharMatcher.anyOf( str ).negate().indexIn( sequence );
}
public int findLastOf( String sequence, String str ) {
return CharMatcher.anyOf( str ).lastIndexIn( sequence );
}
public int findLastNotOf( String sequence, String str ) {
return CharMatcher.anyOf( str ).negate().lastIndexIn( sequence );
}
Other answers welcomed. [I couldn't find anything for find_last_not_of() in Java when searching on stackoverflow and elsewhere. And I missed CharMatcher the first time I searched through Guava for corresponding functionality. I'd like to document this easy conversion for future use.]
If you like regex, you can give the below equivalents a shot. This might not be the most efficient method, but certainly worth considering, if you don't want to use any 3rd party library (Given that, there are no equivalent methods in String class in Java).
P.S: - If you are comfortable with 3rd party library, then I wouldn't suggest using regex for this task, as this might soon become difficult to extend as per requirement.
So, this is just another option :
public int findFirstOf( String sequence, String str ) {
String regex = "^[^" + Pattern.quote(str) + "]*";
int index = sequence.length() - sequence.replaceAll(regex, "").length();
return index == sequence.length() ? -1 : index;
}
public int findFirstNotOf( String sequence, String str ) {
String regex = "^[" + Pattern.quote(str) + "]*";
int index = sequence.length() - sequence.replaceAll(regex, "").length();
return index == sequence.length() ? -1 : index;
}
public int findLastOf( String sequence, String str ) {
String regex = "[^" + Pattern.quote(str) + "]*$";
return sequence.replaceAll(regex, "").length() - 1;
}
public int findLastNotOf( String sequence, String str ) {
String regex = "[" + Pattern.quote(str) + "]*$";
return sequence.replaceAll(regex, "").length() - 1;
}
I haven't tested above methods. You can do the test, and compare the results with the corresponding method you have got, and see if this works. Please get back, if this doesn't work.
As far as 3rd party library is concerned, you also have Apache Commons, StringUtils class, with following methods:
StringUtils#indexOfAny()
StringUtils#indexOfAnyBut()
StringUtils#lastIndexOfAny()
static int findFirstNotOf(String searchIn, String searchFor, int searchFrom) {
boolean found;
char c;
int i;
for (i = searchFrom; i < searchIn.length(); i++) {
found = true;
c = searchIn.charAt(i);
System.out.printf("s='%s', idx=%d\n",c,searchFor.indexOf(c));
if (searchFor.indexOf(c) == -1) {
found = false;
}
if (!found) {
return i;
}
}
return i;
}
static int findLastNotOf(String searchIn, String searchFor, int searchFrom) {
boolean found;
char c;
int i;
for ( i = searchFrom; i>=0; i--) {
found = true;
c = searchIn.charAt(i);
System.out.printf("s='%s', idx=%d\n",c,searchFor.indexOf(c));
if (searchFor.indexOf(c) == -1)
found = false;
if (!found) return i;
}
return i;
}
public static void main(String[] args){
String str = "look for non-alphabetic characters...";
int found = findFirstNotOf(str,"abcdefghijklmnopqrstuvwxyz ",0);
if (found!=str.length()) {
System.out.print("The first non-alphabetic character is " + str.charAt(found));
System.out.print(" at position " + found + '\n');
}
found = findLastNotOf(str,"abcdefghijklmnopqrstuvwxyz ",str.length()-1);
if (found>=0) {
System.out.print("The last non-alphabetic character is " + str.charAt(found));
System.out.print(" at position " + found + '\n');
}
str = "Please, erase trailing white-spaces \n";
String whitespaces = " \t\f\n\r";
found = findLastNotOf(str,whitespaces,str.length()-1);
if (found!=str.length()-1)
str = str.substring(0,found+1);
else
str = ""; // str is all whitespace
System.out.printf('['+ str +"]\n");
}