Finding all Strings of Length - java

Given a class Password of all the passwords that can be written with only the lowercase letters of the English alphabet, I'd like to write an algorithm which recursively finds a password, by going over all of the possible passwords of the same length.
The class Password has a method public boolean isPassword(String st), which compares between a given password p and the string st and returns the boolean value of whether or not they're equal.
Let's call this method public static String findPassword(Password p, int length).
My idea was to do this in two recursive calls - one that goes on the length of p, and continuously adds characters from the alphabet with the method charAt(i) on the string alphabet="abcd.....z" until it gets a string at the same length as p (meaning length).
The second recursive call will go on the letters of the alphabet creating new strings by changing each time the letter that it adds to the previous string. For instance, given a string st of length L, we'll first add the letter a, then the letter b, and so on until we get to z, to move from strings of length L to length L+1.
My problem at the moment is translating some of these ideas into code, and I'd like to do this without any for loops.

If you did it as simple for loops you'd do this:
// For n=1
for (int i = 0; i < 26; i++)
System.out.println(alphabet.substring(i, i + 1));
// For n=2
for (int i = 0; i < 26; i++)
for (int j = 0; j < 26; j++)
System.out.println(alphabet.substring(i, i + 1) +
alphabet.substring(j, j + 1));
// For n=3
for (int i = 0; i < 26; i++)
for (int j = 0; j < 26; j++)
for (int k = 0; k < 26; k++)
System.out.println(alphabet.substring(i, i + 1) +
alphabet.substring(j, j + 1) +
alphabet.substring(k, k + 1));
And so on. That would generate the following for n=3:
aaa
aab
aac
...
aaz
aba
...
zzz
Now, since you can't hardcode number of nested loops for dynamic values of n, you use recursion, as you said, but only one recursive call as you progress from 1 to n.
This means the recursive method need to receive two parameters: The string so far, and the number of letter left to add.
When in the deepest recursive call, i.e. when no more letters needs to be added, print the result.
Here is pseudo-code:
method(String textSoFar, int lettersLeft) {
if (lettersLeft == 0)
print textSoFar
else
for each letter in alphabet:
method(textSoFar + letter, lettersLeft - 1)
}
You initiate the recursion by calling method("", n).
Remember, you can't return the strings, because you'll build lots of strings for increasing values of n:
26 strings for n=1
676 strings for n=2
17,576 strings for n=3
456,976 strings for n=4
11,881,376 strings for n=5
and progressively worse...

Related

Permutations of a set of data in Java

I have 10,000 items in a set whereby each must be made into triads.
I need an algorithm to efficiently find each triad.
For example:
{A,B,C,D,...}
1.AAA
2.AAB
3.AAC
4.AAD
...
all the way to ZZY, ZZZ.
The method I'm using is very inefficient, I created a nested forloop of 3 which iterates through an array, which has a run-time of O(N^3) and terrible on performance obvious. Which kind of algo and data structure would be better for this? Thank you
Function to print all permutations of K length from a set of n characters with
repetition of characters:
static void printKLengthPerm(char[] set, String prefix, int n, int k)
{
if (k == 0)
{
System.out.println(prefix);
return;
}
for (int i = 0; i < n; i++)
{
String newPrefix = prefix + set[i];
printKLengthPerm(set, newPrefix, n, k - 1);
}
}
Calling the function to print all permutations of 3 length from a set all capital english alphabets:
char[] set = new char[26];
for(int i = 0; i < 26; i++)
set[i] = (char)(i+65);
int n = set.length;
printKLengthPerm(set, "", n, 3);

Maximum repeating sequence instead of longest repeating sequence

I am trying to get the most repeated sequence of characters in a string.
For example :
Input:
s = "abccbaabccba"
Output:
2
I have used dynamic programming to figure out the repeating sequence, but this returns the longest repeating character sequence. For example:
Input:
s = "abcabcabcabc"
Output:
2
2(abcabc,abcabc) instead of 4(abc,abc,abc,abc)
Here is the part of the code where I'm filling the DP table and extracting repeating sequence. Can anyone suggest how I can get the most repeating sequence?
//Run through the string and fill the DP table.
char[] chars = s.toCharArray();
for(int i = 1; i <= length; i++){
for(int j = 1; j <= length; j++){
if( chars[i-1] == chars[j-1] && Math.abs(i-j) > table[i-1][j-1]){
table[i][j] = table[i-1][j-1] + 1;
if(table[i][j] > max_length_sub){
max_length_sub = table[i][j];
array_index = Math.min(i, j);
}
}else{
table[i][j] = 0;
}
}
}
//Check if there was a repeating sequence and return the number of times it occurred.
if( max_length_sub > 0 ){
String temp = s;
String subSeq = "";
for(int i = (array_index - max_length_sub); i< max_length_sub; i++){
subSeq = subSeq + s.charAt(i);
}
System.out.println( subSeq );
Pattern pattern = Pattern.compile(subSeq);
Matcher matcher = pattern.matcher(s);
int count = 0;
while (matcher.find())
count++;
// To find left overs - doesn't seem to matter
String[] splits = temp.split(subSeq);
if (splits.length == 0){
return count;
}else{
return 0;
}
}
Simple and dump, the the smallest sequence to be considered is a pair of characters (*):
loop over the whole String an get every consecutive pair of characters, like using a for and substring to get the characters;
count the occurrence of that pair in the String, create a method countOccurrences() using indexof(String, int) or regular expressions; and
store the greatest count, use one variable maxCount outside the loop and an if to check if the actual count is greater (or Math.max())
(*) if "abc" occurs 5 times, than "ab" (and "bc") will occur at least 5 times too - so it is enough to search just for "ab" and "bc", not need to check "abc"
Edit without leftovers, see comments, summary:
check if the first character is repeated over the whole string, if not
check if the 2 initial characters are repeated all over, if not
check if the 3 ...
at least 2 counters/loops needed: one for the number of characters to test, second for the position being tested. Some arithmetic could be used to improve performance: the length of the string must be divisible by the number of repeated characters without remainder.

Can't produce all permutations of a String (iteratively)

So I'm working on some Java exercises, and one that has caught my attention recently is trying to produce all permutations of a String using iteration. There are plenty of examples online - however, a lot of them seem very complex and I'm not able to follow.
I have tried using my own method, which when tested with a string of length 3 it works fine. The method is to (for each letter) keep moving a letter along the string, swapping it with whatever letter is in front of it. E.g.
index: 012
string: abc
(iteration 1) swap 'a' (index 0) with letter after it 'b' (index 0+1) : bac
(iteration 2) swap 'a' (index 1) with letter after it 'c' (index 1+1) : bca
(iteration 3) swap 'a' (index 2) with letter after it 'b' (index 0) : acb
current permutations: abc (original), bac, bca, acb
(iteration 3) swap 'b' (index 1) with letter after it 'c' (index 1+1) : acb
(iteration 4) swap 'b' (index 2) with letter after it 'a' (index 0) : bca
(iteration 5) swap 'b' (index 0) with letter after it 'c' (index 1) : cba
current permutations: abc (original), bac, bca, acb, acb, cba
...
This is how I implemented it in Java:
String str = "abc"; // string to permute
char[] letters = str.toCharArray(); // split string into char array
int setLength = factorial(letters.length); // amount of permutations = n!
HashSet<String> permutations = new HashSet<String>(); // store permutations in Set to avoid duplicates
permutations.add(str); // add original string to set
// algorithm as described above
for (int i = 0; i < setLength; i++) {
for (int j = 0; j < letters.length; j++) {
int k;
if (j == letters.length - 1) {
k = 0;
} else {
k = j + 1;
}
letters = swap(letters, j, k);
String perm = new String(letters);
permutations.add(perm);
}
}
The problem is if I input a string of length 4, I only end up with 12 permutations (4x3) - if I input a string of length 5, I only end up with 20 permutations (5x4).
Is there a simple modification I could make to this algorithm to get every possible permutation? Or does this particular method only work for strings of length 3?
Appreciate any feedback!
Suppose the input is "abcd". This is how your algorithm will work
bacd
bacd
bcad
bcda
If you observe carefully, "a" was getting positioned at all indexes and the following consecutive letter was getting replaced with "a". However, after your algorithm has produced "bacd" - it should be followed by "badc" also, which will be missing from your output.
For string of length 4, When you calculated the number of permutations as factorial, you understand that the first position can be occupied by 4 characters, followed by 3, 2 and 1. However, in your case when the first two positions are occupied by "ba" there are two possibilities for 3rd position, i.e. c and d. While your algorithm correctly finds "cd", it fails to find "dc" - because, the loop does not break the problem into further subproblems, i.e. "cd" has two permutations, respectively "cd" and "dc".
Thus, the difference in count of your permutations and actual answer will increase as the length of string increases.
To easily break problems into sub-problem and solve it, many algorithm uses recursion.
However, you could look into Generate list of all possible permutations of a string for good iterative answers.
Also, as the length of string grows, calculating number of permutation is not advisable.
While I do not know of a way to expand upon your current method of switching places (I've attempted this before to no luck), I do know of a fairly straightforward method of going about it
//simple method to set up permutate
private static void permutations(String s)
{
permutate(s, "");
}
//takes the string of chars to swap around (s) and the base of the string to add to
private static void permutate(String s, String base)
{
//nothing left to swap, just print out
if(s.length() <= 1)
System.out.println(base + s);
else
//loop through the string of chars to flip around
for(int i = 0; i < s.length(); i++)
//call with a smaller string of chars to flip (not including selected char), add selected char to base
permutate(s.substring(0, i) + s.substring(i + 1), base + s.charAt(i));
}
The goal with this recursion is to delegate as much processing as possible to something else, breaking the problem down bit by bit. It's easy to break down this problem by choosing a char to be first, then telling a function to figure out the rest. This can then be done for each char until they've all been chosen once

Finding number of sub strings between two giving chars

I need for my homework to write method that get two parameters, string and char, and it needs to return the number of strings that start with that char and end with that char.
Example:
For the string "abcbcabcacab" and the char 'c', the method will return 6.
(the sub strings are "cbc", "cabc", "cac", "cbcabc", "cabcac", "cbcabcac")
It needs to be as effectiveness as possible, and the only two method that I can use is charAt() and length().This is hard as hell and after 3 hours of trying, I'm asking you guys if there is someone who cal solve this or at least show me some clue.
The obvious solution is to check every symbol in input string and if equals to specified char, then try to find all possible substrings, starting from this point, like this:
long cnt = 0;
for (int i = 0; i < (s.length() - 1); i++)
if (s.charAt(i) == c)
for (int j = (i + 1); j < s.length(); j++)
if (s.charAt(j) == c)
cnt++;
return cnt;
this solution has complexity O(N^2)
but, number of substrings actually determined by number of occurrences of char in string, which appeared to be Triangular number
So, optimized O(N) solution is:
long cnt = -1;
for (int i = 0; i < s.length(); i++)
if (s.charAt(i) == c)
cnt++;
return (cnt * (cnt + 1)) >>> 1;
The simplest anwser is that you should use a loop.
Loop through the strings. Check if the current string starts with the given char and ends with the given char. If it doesn't just jump to the next one. if it does just loop with a counter from 1 to length minus the second last char.
You will reduce time by kicking out invalid string and you will be checking 2 chars less EVERY string ;)
I guess that's a quite fast way.
Example
// String definition bla String[] myArray
int count = 0;
for(int i = 0; i < myArray.length(); i++) {
if(myArray[i].charAt(0) == givenChar && myArray[i].charAt(myArray.length()-1)) {
for(int j = 1; j < myArray.length()-2;j++) {
if(myArray[i].charAt(j) == givenChar)
count ++;
}
}
}
That's the rough idea.
I am checking if the given String starts and ends with the givenChar.
If it does im iterating through the string checking for the givenChar again.
If it does exist i am counting 1 up.
I hope that might help your out ;)
Have a nice day!

Converting char array to int array without a loop in Java?

I need to get the binary representation for a range of numbers inside a matrix in order to perform some operations with another vector.
So let's say I will get the binary representation for 2^4 numbers, that's it from 0 to 15. I know I need a 16x4 matrix.
I've got this code:
int [][] a = new int[15][4];
for (int i = 0; i < a.length; i++) {
a[i] = String.format("%5s", Integer.toBinaryString(i)).replace(' ', '0').toCharArray();
}
So, being the array representation of the binary formatted number a char[], I can't just asign it to a[i].
If there any way to perform a cast without looping through the char array?
Not that I am aware of. There are some different ways you can do it, either looping through the integer representation of the binary string, and the taking num%10 and num/10 for every step, if you absolutely don't want a loop through the char array. However in this case it seems pretty straight forward to just loop through the char array. Anyways here is the solution, in the way you didn't want it I guess...
int [][] a = new int[16][4];
for (int i = 0; i < a.length; i++) {
char[] cArr = String.format("%4s", Integer.toBinaryString(i)).replace(' ', '0').toCharArray();
for(int j = 0; j < a[0].length; j++)
a[i][j] = Integer.parseInt(cArr[j]+"");
}
This is a simpler solution to what you are trying to accomplish...
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[0].length; j++) {
a[i][a[0].length - 1 - j] = (i & (1 << j)) != 0 ? 1 : 0;
}
}
Instead of converting an integer i to String and then replacing white spaces with zeros and then converting it to array, you:
Take i.
Take a binary number A with the only 1 at j-th position (other being zeros): A = (1 << j)
Perform conjunction (binary bit-wise multiplication) of your number and the number A. This is accomplished by: (i & A)
If there was non-zero bit at that position, after conjunction you will get A. If there was a zero bit, you will get 0.
If the result is not zero, i has non-zero bit in j-th position. Otherwise it has zero there.
The solution using bit-wise operations will be faster too.
I believe that one outer loop will still be required to iterate through char[][] rows.
int[] charArray2intArray(char[][] binary) {
int[] numbers = new int[binary.length];
int row = 0;
for (char[] number: binary) {
String bin = new String(number);
numbers[row++] = Integer.parseInt(bin, 2);
}
return numbers;
}

Categories

Resources