I searched a code for permutation in java:
public class MainClass {
public static void main(String args[]) {
permuteString("", "String");
}
public static void permuteString(String beginningString, String endingString) {
if (endingString.length() <= 1)
System.out.println(beginningString + endingString);
else
for (int i = 0; i < endingString.length(); i++) {
try {
String newString = endingString.substring(0, i) + endingString.substring(i + 1);
permuteString(beginningString + endingString.charAt(i), newString);
} catch (StringIndexOutOfBoundsException exception) {
exception.printStackTrace();
}
}
}
}
I can't understand it even though I know it was only a basic code. I want someone to explain it to me to make it clearer. Thank you guys
One can construct a permutation, by picking items from a bag repeatedly and thus constructing a sequence. For a string, the bag is a collection of characters. We can use a String to represent this.
If we thus want to construct a random permutated string, we first look if the bag is empty. In the above code, the bag is the endingString and the emptiness check is done with:
if (endingString.length() <= 1)
System.out.println(beginningString + endingString);
As you can see the check does not look whether the bag is completely empty: from the moment the string has only one character (one element), it is evidently we will pick that one. So we pick it and print it after the sequence we've already constructed.
Problem: a problem with this approach is that if we want to list the permutations of the empty string (there is exactly one: the empty string), one will get errors.
Now we need the iterative case. Remember that beginningString stores the sequence we've constructed up till now and endingString stores the list of characters we still can pick from. Now a way to pick is to select a valid index i in the endingString. The character at that index is then picked.
We update the sequence (beginningString by simply appending the character that was placed at i, thus:
beginningString + endingString.charAt(i)
In order to update the bag, it means that the bag now contains all the characters before the index, and the ones after the index. This is formalized as:
String newString = endingString.substring(0, i) + endingString.substring(i + 1);
newString is here the new bag. We can then do the recursive call to pick the next item from the bag. So for a given index i, in order to pick and call recursively, the code reads:
String newString = endingString.substring(0, i) + endingString.substring(i + 1);
permuteString(beginningString + endingString.charAt(i), newString);
Now since we wish to enumerate over all possible permutations, we loop over all possible indices for i. Since we do this recursively as a consequence, we will enumerate all permutations.
Related
All I really need to know is if the function I am using is recursive or if the method simply doesnt get called within itself.
In my code, I have a helper function to reverse the second word and I put a toLowerCase in order to be able to compare words even if there are any random capitals.
Is this recursion or is it just a function that compares the two?
import java.util.Scanner;
public class isReverse {
public static void main(String[] args) {
isReverse rev = new isReverse();
Scanner in = new Scanner(System.in);
System.out.println("Please enter a word: ");
String a = in.nextLine();
System.out.println("Please Enter a second word to compare: ");
String b = in.nextLine();
System.out.println(rev.isReverse(a, b));
}
String rev = "";
public boolean isReverse(String wordA, String wordB){
String fword = wordA.replaceAll("\\s+", "").toLowerCase();
String clean2 = wordB.replaceAll("\\s+", "").toLowerCase();
String reverse = revString(clean2);
if(fword.length() == 0){
return false;
}
if (fword.equals(reverse)){
return true;
}
if (!reverse.equals(fword)){
return false;
}
else
return isReverse(fword,reverse);
}
public String revString(String sequence) {
String input = sequence;
StringBuilder order = new StringBuilder();
order.append(input);
order = order.reverse();
rev = order.toString();
return rev;
}
}
As far as your question is concerned, your code is not behaving like a recursive function because your code is not entering into the last else condition. For recursion to work you need to have:
a base case(if there is no base case the recursion will go on forever)
a recursive case(this is where you kind of reduce the original problem)
But my comment about your code:
If you're doing the actual reverse logic you don't need to use recursion just to check if the original string and the reverse string are the same. These is purely an algorithm problem so here is the way to solve the problem:
If the length of the given input is 1 then the reverse is the same.
else:
check the first and last chars of the string, if they are equal, then you need to remove those two chars and check if the rest of the string is a palindrome. This is the actual recursive step.
else the string is not a palindrome.
Technically? Well, you are calling a method from within itself, so, technically, yeah.
Pragmatically? No. The recursive call part will never be invoked.
Your code does this: I have 2 words. If the words are equal to each other, stop and do something. if they are not equal to each other, stop and do something. Otherwise, recurse.
And that's where it falls apart: It'll never recurse - either the words are equal, or they are not.
The general idea behind a recursive function is three-fold:
The method (java-ese for 'function') calls itself.
Upon each call to itself, the parameters passed are progressing to an end state - they become smaller or trend towards a stop value such as 0.
There are edge cases where the function does not call itself, and returns instead (the answer for the smallest/zero-est inputs does not require recursion and is trivial).
You're missing the #2 part here. Presumably, this is what you'd want for a recursive approach. Forget about revString, delete that entirely. Do this instead:
If both inputs are completely empty, return true (That's the #3 - edge cases part).
If one of the two inputs is empty but the other one is not, false. (Still working on #3)
If the first character of the input string is NOT equal to the last character of the output string, false. (Still #3).
Now lop the first char off of the first input and the last off of the latter (Working on #2 now - by shortening the strings we're inevitably progressing towards an end no matter what)
now call ourself, with these new lopped-down strings (That'll be #1).
That would be a recursive approach to the problem. It's more complicated than for loops, but, then, recursive functions often are.
Actually this is not a recursing. All you need is just:
Check that both string have the same length
Iteratively check letters from 0 to n from the first string and from n to 0 from the second string. If they equal, then go to the next iteration (recutsion) or return fail otherqwise.
// here do not check signature of the public method
public static boolean isReverse(String one, String two) {
return isReverse(one, 0, two, two.length() - 1);
}
// support method has two additional counters to check letters to be equal
private static boolean isReverse(String one, int i, String two, int j) {
if (i == one.length())
return j == -1;
if (j == two.length())
return i == -1;
// if not equal, then strings are not equal
if (one.charAt(i) != two.charAt(j))
return false;
// go to the next recursion to check next letters
return isReverse(one, i + 1, two, j - 1);
}
I've read in other posts, that instead of writing just System.out.println(finalPressedKey);
you should write System.out.println(Arrays.toString((finalPressedKey)); because otherwise it will just return the location where the String is saved (as far as I understood it).
public static String PressedKey[] = new String[2000];
public static String[][] finalPressedKey = {{ "", "", "", "", "", "", "", "", "", "", "", "" }}; // 12
public static String FPK3;
public static void upcounter(KeyEvent e) {
for (int x = 0; x < PressedKey.length; x++) {
if (PressedKey[x] != null && PressedKey[x + counter] != null) {
//FPK counter is supposed to be a line, and counter is where the words are supposed to be saved
finalPressedKey[FPKcounter][counter] =
finalPressedKey[FPKcounter] + PressedKey[x + counter];
System.out.println(Arrays.toString(finalPressedKey));
}
}
Whenever I Press a Button, it should be saved in my PressedKey Array, and finalPressedKey is supposed to contain itself, and PressedKey (also , only the last element of the array is supposed to be printed), but instead it just prints [[Ljava.lang.String;#76f42c4b]
I also tried using Arrays.deepToString(); but it gives me the same output as with Arrays.toString();
Thanks for your help!
A String[][] is not a 2-d array. It is an array of String[]. The difference is subtle but important.
The method Arrays.toString() takes an array, iterates through its elements, calls toString() on all of them, and adds a prefix, suffix, and delimiters. Since you give it a String[][] (an array of String[]), it will do the following:
Iterate through the elements (each of them a String[])
call toString() on each element - giving the default toString() value of an array - i.e. its memory address (not really but for this purpose it doesn't matter)
concatenate
Luckily for you, there is an easier way - just use Arrays.deepToString(). This behaves as you would expect.
I did not understand the whole code, but following statement is very suspicious:
finalPressedKey[FPKcounter][counter] =
finalPressedKey[FPKcounter] + PressedKey[x + counter];
since it is adding an array (finalPressedKey[...]) to a string (PressedKey[...]), which will result in that strange text - the standard textual representation of an array (returned by toString). (from a mathematical point of view, it's strange to have 2 indexes )2D_ before the assignment and only one on the right side (1D) for same matrix)
I'm not sure, since we cannot see what counteris, but I believe you wanted something like:
finalPressedKey[FPKcounter][counter] =
finalPressedKey[FPKcounter][counter] + PressedKey[x + counter];
that is, an additional [counter] on second line.
This can also be written as
finalPressedKey[FPKcounter][counter] += PressedKey[x + counter];
If you only want to store lines of strings, a normal String[] is good for you
finalPressedKey[FPKcounter] += PressedKey[x + counter];
even though I wouldn't recomment doing this, no matter what you're trying to accomplish, since this will create a new String object each time a key is pressed.
Maybe ask the question differently and tell us what you're trying to do. I guess String arrays might not be the way to go.
You have to print the elements of your array with
for(int i = 0; i<finalPressedKey[0].length; i++){
for(int j=0; j<finalPressedKey[1].length; j++){
System.out.println(finalPressedKey[i][j]);
}
}
if I understand it correctly.
So the goal is to look for patterns like "zip" and "zap" in the string, starting with 'z' and ending with 'p'. Then, for all such strings, delete the middle letter.
What I had in mind was that I use a for loop to check each letter of the string and once it reaches a 'z', it gets the indexOf('p') and puts that and everything in the middle into an ArrayList, while deleting itself from the original string so that indexOf('p') can be found.
How can I do that?
This is my code so far:
package Homework;
import java.util.Scanner;
import java.util.ArrayList;
import java.util.List;
public class ZipZap {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
List < String > list = new ArrayList < String > ();
System.out.print("Write a sentence with no spaces:");
String sen = in .next();
int len = sen.length();
int p1 = sen.indexOf('p');
String word = null;
String idk = null;
for (int i = 0; i < len; i++) {
if (sen.charAt(i) == 'z') {
word = sen.substring(i, p1 + 1);
list.add(word);
idk = sen.replace(word, "");
i = 0;
}
}
}
}
use this , here i am using "\bz.p\b" pattern for finding any word that contains starting char with z and end with p anything can be in between
String s ="Write a sentence with no zip and zap spaces:";
s=s.replaceAll("\\bz.p\\b", "zp");
System.out.println(s);
output:
Write a sentence with no zp and zp spaces:
or it can be
s.replaceAll("z\\w+p", "zp");
here you can check you string
https://regex101.com/r/aKaNTJ/2
I think you’re saying that input zipzapityzoop, for example, should be changed to zpzpityzp with i, a and oo going into list. Please correct me if I misunderstood your intention.
You are on the way and seem to understand the basics. The issues I see are minor, but of course you want to fix them:
As #RicharsSchwartz mentions, to find all strings like zip, zap and zoop, you need to find p after every z you find. When you have found z at index i, you may use sen.indexOf('p', i + 1) to find a p after the z (the second argument causes the search to begin at that index).
Every time you have found a z, you are setting i back to 0, this starting over from the beginning of the string. No need to do that, and this way your program will never stop.
sen.substring(i, p1+1) takes out all of zip when I understood you only wanted i. You need to adjust the arguments to substring().
Your use of sen.replace(word, "") will replace all occurences of word. So once you fix your program to take out a from zap, zappa will become zpp (not zppa), and azap will be zp. There is no easy way to remove just one specific occurrence of a substring from a String. I think the solution is to use the StringBuilder class. It has a delete method that will remove the part between two specified indices, which is what you need.
Finally you are assigning the changed string to a different variable idk, but then you continue to search sen. This is like assigning zpzapityzoop, zipzpityzoop and zipzapityzp to idk in turn, but never zpzpityzp. However, if you use a StringBuilder as I just suggested, just use the same StringBuilder all the way through and you will be fine.
Following code written in Java
public static void main (String [] args) throws Exception
{
ordListe ol = new ordListe();
ol.lesBok("navn.text");
ol.leggTilOrd("hello");
ol.leggTilOrd("Hello");
Is my main method. This is about reading from file and adding to a arraylist(dictionary). ''Hello'' and "hello" is supposed to be the same word, and in the code under, it should increase the count of that word.
for (int i = 0; i < ordListe.size(); i++)
{
if (ordListe.toString().contains(s))
{
if (ordListe.get(i).toString().equalsIgnoreCase(s))
{
ord.oekAntall();
System.out.println("'" + s + "' That word is found and there are " + ord.hentAntall() + " of that word now in dictionary.");
break;
}
}
else
{
Ord ny = new Ord(s);
ordListe.add(ny);
System.out.println("'" + s + "' This word is added. " + ny.hentAntall() + " of this word in dictionary.");
break;
}
}
So this is a part of my code. From the main method I add words like ol.leggTilOrd("hello"); leggTilOrd is my method where the code right above is taken from. This is the part of the code that adds words to the dictionary/arrayList and checks if inputwords already exists. I have no problem with anything else than the specific if (ordListe.get(i).toString().equalsIgnoreCase(s)) part. If a word exist in the arrayList, I'm supposed to increase the count of that word. If not, I add the word in the arraylist (ordListe). The problem is that even if I add ol.leggTilOrd("hello") or ol.leggTilOrd("Hello"); with capital 'H', I can't get to recognize it as the same word even if I use the statements above. How do I do this, any other possibilites? This is my last possible effort, after many attempts earlier.
If there are anything questionable above, just tell me.
Change both strings to lower case before comparing and then comapare..it will help you and is easier!!! Use toLower function and then compare
The problem is this line:
if (ordListe.toString().contains(s))
Because 1) you do not compare the lowercase or uppercase versions of the two strings and 2) you probably not overrided toString so it returns the items in the list as you probably expect. Put this function in your ordListe class assuming that your ordliste extends arraylist:
public boolean containsIgnoreCase(String item) {
for(int i = 0; i < size(); i++) {
if (get(i).toString().equalsIgnoreCase(item)) {
return true;
}
}
return false;
}
Now you can call containsIgnoreCase to determinate if there is a specific item in the list ignoring the case
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
EDITED
I have this kind of string
"A-B-C-D"
"B-C-A"
"D-A"
"B-A-D"
"D-A-B-C"
Now my problem is if the user input has a value of "A-C" or "C-A" the numbers 1,2,5 will be my output because the those numbers has a value "A-C" if for example the user has a input value of either of this three "A-B-D","B-A-D","A-D-B" the the output will be 1,4,5. hope it clears the question
Note:
the search sequence depends on user input and i want it to be more efficient because I have 10 thousand of data I don't want to use as much loop as possible.
This might change based on you needs to have the String in the exact pattern you have it or not, but REALLY simply...
public class Simple {
public static void main(String[] args) {
System.out.println("1. " + matches("A-B-C-D"));
System.out.println("2. " + matches("B-C-A"));
System.out.println("3. " + matches("D-A"));
System.out.println("4. " + matches("B-A-D"));
System.out.println("5. " + matches("D-A-B-C"));
}
public static boolean matches(String value) {
return value.contains("A") && value.contains("C");
}
}
Which outputs
1. true
2. true
3. false
4. false
5. true
Extended example using variable matchers
So, the basic idea is to provide some kind of list of values to be matched against. This example simply uses a String varargs (or String array), but it wouldn't be hard to make it use something like List
public class Simple {
public static void main(String[] args) {
String[] match = new String[]{"A", "D", "C"};
System.out.println("1. " + matches("A-B-C-D", match));
System.out.println("2. " + matches("B-C-A", match));
System.out.println("3. " + matches("D-A", match));
System.out.println("4. " + matches("B-A-D", match));
System.out.println("5. " + matches("D-A-B-C", match));
}
public static boolean matches(String value, String... matches) {
boolean doesMatch = true;
for (String match : matches) {
if (!value.contains(match)) {
doesMatch = false;
break;
}
}
return doesMatch;
}
}
This outputs...
1. true
2. false
3. false
4. false
5. true
Use an array and go through each index and see if it contains "C-A" or "A-C" then if it does print the number.
String stringArray[] = {"A-B-C-D", "B-C-A", "D-A", "B-A-D", "D-A-B-C"};
for(int i = 0; i < stringArray.length; i++) {
String pattern = ".*C-.*A.*";
String pattern2 = ".*A-.*C.*";
if(stringArray[i].matches(pattern) || stringArray[i].matches(pattern2))
System.out.println(i + 1);
}
Edit: This applies to an older version of the OP that was unclear about finding the sequence in order; and so this searches for sequences in order, which isn't correct now.
There are many options. Below I outline one approach that tokenizes the strings first, and another that uses a simple regex generated from the input string.
Approach 1: Parsing Strings
Start by parsing each String into an array of substrings, that will make this all easier to work with. You may want to parse each of the strings when you originally read them instead of every time you need to:
String myString = "A-B-C-D";
String[] sequence = myString.split("-");
Next, consider using an List<String> instead of a String[], because it will make the rest of this a bit easier (you'll see). So, instead of the above:
String myString = "A-B-C-D";
List<String> sequence = Arrays.asList(myString.split("-"));
Now the problem becomes checking if two of these arrays match:
public static boolean containsSequence (List<String> searchIn, List<String> searchFor) {
}
You need to check both directions, but you can simply reverse the array and reduce this problem further to just checking the forward direction (there are certainly ways to do this and avoid the copy but they can get complicated and it's only worth it if you have high performance requirements):
public static boolean containsSequence (List<String> searchIn, List<String> searchFor) {
// first check forward
if (containsSequenceForward(searchIn, searchFor))
return true;
// now check in reverse
List<String> reversedSearchFor = new ArrayList<String>(searchFor);
Collections.reverse(reversedSearchFor);
return containsSequenceForward(searchIn, reversedSearchFor);
}
public static boolean containsSequenceForward (List<String> searchIn, List<String> searchFor) {
}
// usage example:
public static void example () {
List<String> searchIn = Arrays.asList("D-A-B-C".split("-"));
List<String> searchFor = Arrays.asList("A-C".split("-"));
boolean contained = containsSequence(searchIn, searchFor);
}
Now you just need to implement containsSequenceForward. I'd like you to do this yourself, but I will provide an algorithm as a hint:
Start at the beginning of searchIn and searchFor.
Go through searchIn one element at a time.
When you find the current element of searchFor in searchIn, advance searchFor to next element.
If you hit the end of searchFor you've found the sequence.
If you hit the end of searchIn but not searchFor, then the sequence doesn't match.
Now you have the ability to check if one sequence contains another in any order. To apply it to your entire collection, I recommend preparsing all of the strings into a List<String> once at the start, then you can go through each of those using the above algorithm.
There are many alternative options. For example, you could use indexOf on searchIn to find the each element in searchFor and make sure the indices are in increasing order.
Approach 2: Regular Expressions
Another option here is to use a regular expression to find the search sequence in the source string. You can build the regular expression dynamically from the search sequence quite easily:
String searchIn = "D-C-B-A";
String searchFor = "C-A";
String searchForPattern = searchFor.replace("-", ".*"); // yields "C.*A"
if (searchIn.matches(".*" + searchForPattern + ".*"))
/* then it matches forwards */;
Then to match in reverse, if the forward match fails, you can just reverse searchFor and repeat:
String searchForReverse = new StringBuilder(searchFor).reverse().toString();
String searchForReversePattern = searchForReverse.replace("-", ".*"); // yields "A.*C"
if (searchIn.matches(".*" + searchForReversePattern + ".*"))
/* then it matches backwards */;
Note that this particular regex solution assumes that each element is only one character long.
Also both of the above approaches assume case-sensitive matches -- to make the first case-insensitive I would just convert the strings to lowercase before parsing. For the second you can use a case-insensitive regex.
Hope that helps. Work it out on a piece of paper if you have to.
The general take home point here is it helps to reduce these problems to their smallest components first.
Call this function on every string you wish to check. If it returns true, add that string to your result set.
boolean matches(String s, char[] chars) {
for(char c : chars) {
if (s.indexOf(c) == -1) {
return false;
}
}
return true;
}