I'm struggling with this algorithm. It should work like this:
If I input f.e. 6880, my program should output 80 86 80 86 60 68 68.
As you can see, combinations are repeating. That's because it looks at every digit as it is a different object. In my program it's correct.
Here is my code:
public static Set<Integer> get2DCombinations(List<Integer> digits) {
Set<Integer> combinations = new TreeSet<>();
int t = 0;
for(Integer i : digits) {
for (Integer j : digits) {
t = i * 10 + j;
if (t / 10 >= 1) {
combinations.add(t);
}
}
}
return combinations;
}
It returns a specific set of combinations where all combinations have 2 digits.
It works perfectly, but only with 4-digit numbers. Of course, I can use one more for-each loops, but is there a way to automate it?
So if I input 6-digit number it should output all possible 3-digit combinations of its digits, and if I input 8-digit number, it should output all possible 4-digit combinations. Input numbers always have even amount of digits.
Could you please point out for me how to do so?
You need a recursive program that will generate all the combinations for your input. Here's a solution of mine. My method accepts a String as input (it's just shorted program and easier, you can adapt it to your needs):
public static Set<String> get2DCombinations(String input) {
return backtracking("", input, input.length() / 2) ;
}
public static Set<String> backtracking(String actual, String remaining, int length) {
if (actual.length() == length) {
return new HashSet<>(Arrays.asList(actual));
}
Set<String> result = new HashSet<>();
for(int i = 0; i < remaining.length(); i++) {
result.addAll(backtracking(actual + remaining.charAt(i), remaining.substring(0, i) + remaining.substring(i + 1), length));
}
return result;
}
And you call the method like so:
System.out.println(get2DCombinations(input));
Result:
[88, 68, 06, 80, 08, 60, 86]
As I mentioned in the comment, your are missing some of the combinations. This solution generates all of them.
Try calculating n / 2 first. So, if n is 6, then n / 2 = 3. Then you know before you start fining the combinations that you are looking for combinations of 3 digits.
Then you want to find the right algorithm to find the combinations. Part of problem solving is breaking down problems to smaller problems. That is what I did here.
I can not solve it for you, however, because it is better for you to solve yourself, and second, there details that you dind't provide so it is hard to give the right solution.
Related
I need to generate all palindromic numbers for a given number base (which should be able to be of size up to 10,000), in a given range. I need a efficient way to do it.
I stumbled upon this answer, which is related to base 10 directly. I'm trying to adapt it to work for "all" bases:
public static Set<String> allPalindromic(long limit, int base, char[] list) {
Set<String> result = new HashSet<String>();
for (long i = 0; i <= base-1 && i <= limit; i++) {
result.add(convert(i, base, list));
}
boolean cont = true;
for (long i = 1; cont; i++) {
StringBuffer rev = new StringBuffer("" + convert(i, base, list)).reverse();
cont = false;
for (char d : list) {
String n = "" + convert(i, base, list) + d + rev;
if (convertBack(n, base, list) <= limit) {
cont = true;
result.add(n);
}
}
}
return result;
}
convert() method converts a number to a string representation of that number in a given base using a list of chars for digits.
convertBack() converts back the string representation of a number to base 10.
When testing my method for base 10, it leaves out two-digit palindromes and then the next ones it leaves out are 1001,1111,1221... and so on.
I'm not sure why.
Here are the conversion methods if needed.
Turns out, this gets slower with my other code because of constant conversions since I need the all numbers in order and in decimal. I'll just stick to iterating over every integer and converting it to every base and then checking if its a palindrome.
I don't have enough reputation to comment, but if you are only missing even length palindromes, then most probably there is something wrong with your list. Most probably you have forgot to add an empty entry in list as to generate 1001, it should be like num(10) + empty("") + rev(01).
There is no so many appropriate chars for digits in all possible bases (like 0xDEADBEEF for hex, and I suppose that convert has some limit like 36), so forget about exotic digits, and use simple lists or arrays like [8888, 123, 5583] for digits in 10000-base.
Then convert limit into need base, store it.
Now generate symmetric arrays of odd and even length like
[175, 2, 175] or [13, 221, 221, 13]. If length is the same as limit length, compare array values and reject too high numbers.
You can also use limit array as starting and generate only palindromes with lesser values.
So my program is supposed to iterate over a list of numbers (0-113) and then print the numbers line by line. If the number is odd, that should be added next to the number, if the number is divisible by 5, that should be added next to the number and so on. So I have my 4 boolean methods done and they look like this:
public static boolean isDivisibleBy5(int n){
if (n%5 ==0){
return true;
}
return false ;
}
Next I have a method that I am required to use as per assignment requirements and it is as follows:
public static ArrayList<String>iterate()
So the definition with this method is where I am having problems. Right now what I have is this:
public static ArrayList<String>iterate(){
ArrayList<String> list = new ArrayList<String>();
for(int i=0;i<114;i++){
if (isOdd(i)){
list.add(i+" Is odd");
}
if(isDivisibleBy5(i)){
list.add(i+" hi five");
}
if(isDivisbleBy7(i)){
list.add(i+" wow");
}
if (isPrime(i)){
list.add(i+" prime");
}
}
for(String elem:list)
System.out.println(elem);
return list;
}
But unfortunately my output looks like this:
0 hi five
1 Is odd
1 prime
3 Is odd
3 wow
3 prime
5 Is odd
5 hi five
5 prime
7 Is odd
7 prime
9 Is odd
10 hi five
10 wow
11 Is odd
I need it to look like this:
0, hi five
1, Is Odd, prime
2
3, Is odd, wow, prime
4
5, Is Odd, hi five, prime
etc.
So my question is basically how do I get all the conditions (when true) to add themselves to the same line with the corresponding number and also have the numbers that don't meet the conditions print on their lines as well, like 2 and 4 and 6.
I've been stuck on this question for awhile and I feel like there is a crucial piece of java that I am not thinking of that is required here. String Builder maybe? I'm not sure. Any help is appreciated. Even if you can just point me to a concept to look up and learn more of.
Thanks
EDIT:
I am seeing a lot of responses about building the string first and then adding to it. I believe this was the concept that I was not thinking of that has held me back so I will read up and practice implementing that. Thanks again for the quick responses. When I get it working I will come back here and up-vote anyone who helped.
You need to compose the string first and then add it only once:
public static ArrayList<String>iterate(){
ArrayList<String> list = new ArrayList<String>();
for(int i=0;i<114;i++){
String toAdd = String.valueOf(i);
if (isOdd(i)){
toAdd += ", Is odd";
}
if(isDivisibleBy5(i)){
toAdd += ", hi five";
}
if(isDivisbleBy7(i)){
toAdd += ", wow";
}
if (isPrime(i)){
toAdd += ", prime";
}
list.add(toAdd);
}
for(String elem:list)
System.out.println(elem);
return list;
}
So from what I see you're using list.add() and its adding a row every time you call it. Instead of using list.add() in every if statement, why don't you just add everything to a sting and then use list.add(string) to add it to your list?
Something like this:
public static ArrayList<String>iterate(){
String line =""; //creates line
ArrayList<String> list = new ArrayList<String>();
for(int i=0;i<114;i++){
line += i;
if (isOdd(i)){
line +=", Is odd";
}
if(isDivisibleBy5(i)){
line += ", high five"
}
...
list.add(line);
This question already has answers here:
Memory efficient power set algorithm
(5 answers)
Closed 8 years ago.
I'm trying to find every possible anagram of a string in Java - By this I mean that if I have a 4 character long word I want all the possible 3 character long words derived from it, all the 2 character long and all the 1 character long. The most straightforward way I tought of is to use two nested for loops and iterare over the string. This is my code as of now:
private ArrayList<String> subsets(String word){
ArrayList<String> s = new ArrayList<String>();
int length = word.length();
for (int c=0; c<length; c++){
for (int i=0; i<length-c; i++){
String sub = word.substring(c, c+i+1);
System.out.println(sub);
//if (!s.contains(sub) && sub!=null)
s.add(sub);
}
}
//java.util.Collections.sort(s, new MyComparator());
//System.out.println(s.toString());
return s;
}
My problem is that it works for 3 letter words, fun yelds this result (Don't mind the ordering, the word is processed so that I have a string with the letters in alphabetical order):
f
fn
fnu
n
nu
u
But when I try 4 letter words, it leaves something out, as in catq gives me:
a
ac
acq
acqt
c
cq
cqt
q
qt
t
i.e., I don't see the 3 character long word act - which is the one I'm looking for when testing this method. I can't understand what the problem is, and it's most likely a logical error I'm making when creating the substrings. If anyone can help me out, please don't give me the code for it but rather the reasoning behind your solution. This is a piece of coursework and I need to come up with the code on my own.
EDIT: to clear something out, for me acq, qca, caq, aqc, cqa, qac, etc. are the same thing - To make it even clearer, what happens is that the string gets sorted in alphabetical order, so all those permutations should come up as one unique result, acq. So, I don't need all the permutations of a string, but rather, given a 4 character long string, all the 3 character long ones that I can derive from it - that means taking out one character at a time and returning that string as a result, doing that for every character in the original string.
I hope I have made my problem a bit clearer
It's working fine, you just misspelled "caqt" as "acqt" in your tests/input.
(The issue is probably that you're sorting your input. If you want substrings, you have to leave the input unsorted.)
After your edits: see Generating all permutations of a given string Then just sort the individual letters, and put them in a set.
Ok, as you've already devised your own solution, I'll give you my take on it. Firstly, consider how big your result list is going to be. You're essentially taking each letter in turn, and either including it or not. 2 possibilities for each letter, gives you 2^n total results, where n is the number of letters. This of course includes the case where you don't use any letter, and end up with an empty string.
Next, if you enumerate every possibility with a 0 for 'include this letter' and a 1 for don't include it, taking your 'fnu' example you end up with:
000 - ''
001 - 'u'
010 - 'n'
011 - 'nu'
100 - 'f'
101 - 'fu' (no offense intended)
110 - 'fn'
111 - 'fnu'.
Clearly, these are just binary numbers, and you can derive a function that given any number from 0-7 and the three letter input, will calculate the corresponding subset.
It's fairly easy to do in java.. don't have a java compiler to hand, but this should be approximately correct:
public string getSubSet(string input, int index) {
// Should check that index >=0 and < 2^input.length here.
// Should also check that input.length <= 31.
string returnValue = "";
for (int i = 0; i < input.length; i++) {
if (i & (1 << i) != 0) // 1 << i is the equivalent of 2^i
returnValue += input[i];
}
return returnValue;
}
Then, if you need to you can just do a loop that calls this function, like this:
for (i = 1; i < (1 << input.length); i++)
getSubSet(input, i); // this doesn't do anything, but you can add it to a list, or output it as desired.
Note I started from 1 instead of 0- this is because the result at index 0 will be the empty string. Incidentally, this actually does the least significant bit first, so your output list would be 'f', 'n', 'fn', 'u', 'fu', 'nu', 'fnu', but the order didn't seem important.
This is the method I came up with, seems like it's working
private void subsets(String word, ArrayList<String> subset){
if(word.length() == 1){
subset.add(word);
return;
}
else {
String firstChar = word.substring(0,1);
word = word.substring(1);
subsets(word, subset);
int size = subset.size();
for (int i = 0; i < size; i++){
String temp = firstChar + subset.get(i);
subset.add(temp);
}
subset.add(firstChar);
return;
}
}
What I do is check if the word is bigger than one character, otherwise I'll add the character alone to the ArrayList and start the recursive process. If it is bigger, I save the first character and make a recursive call with the rest of the String. What happens is that the whole string gets sliced in characters saved in the recursive stack, until I hit the point where my word has become of length 1, only one character remaining.
When that happens, as I said at the start, the character gets added to the List, now the recursion starts and it looks at the size of the array, in the first iteration is 1, and then with a for loop adds the character saved in the stack for the previous call concatenated with every element in the ArrayList. Then it adds the character on its own and unwinds the recursion again.
I.E., with the word funthis happens:
f saved
List empty
recursive call(un)
-
u saved
List empty
recursive call(n)
-
n.length == 1
List = [n]
return
-
list.size=1
temp = u + list[0]
List = [n, un]
add the character saved in the stack on its own
List = [n, un, u]
return
-
list.size=3
temp = f + list[0]
List = [n, un, u, fn]
temp = f + list[1]
List = [n, un, u, fn, fun]
temp = f + list[2]
List = [n, un, u, fn, fun, fu]
add the character saved in the stack on its own
List = [n, un, u, fn, fun, fu, f]
return
I have been as clear as possible, I hope this clarifies what was my initial problem and how to solve it.
This is working code:
public static void main(String[] args) {
String input = "abcde";
Set<String> returnList = permutations(input);
System.out.println(returnList);
}
private static Set<String> permutations(String input) {
if (input.length() == 1) {
Set<String> a = new TreeSet<>();
a.add(input);
return a;
}
Set<String> returnSet = new TreeSet<>();
for (int i = 0; i < input.length(); i++) {
String prefix = input.substring(i, i + 1);
Set<String> permutations = permutations(input.substring(i + 1));
returnSet.add(prefix);
returnSet.addAll(permutations);
Iterator<String> it = permutations.iterator();
while (it.hasNext()) {
returnSet.add(prefix + it.next());
}
}
return returnSet;
}
I'm having a little difficulty figuring the best way to go about about generating combinations for specific letters recursively.
Presently, I have a method which would changes a String and alters certains characters to create a single substitution of a word.
However, this isn't going to satisfy for the different combinations for the word. For example, if I have the word kjng commonly mistaken printer characters such as:
[j=>i, i=>j, v=>u, u=>v, s=>f, f=>s, uu=>w, vv=>w] (map lookup, "=>" this is symbolic for key, value representation to make it extra clear)
Based on this method, the word would then become king. That's fine for a word with only one possibility. However along comes murdir which should generate the following:
murdir
mvrdjr
mvrdir
murdjr
A little advice on this would be great, presently I'm unsure of how best to go manage this scenario. For instance, how to keep track of the changes, do it in chunks of characters (1, then 2, then 3, etc).
One changes a word at some position with some rule. And then recurses further. If the new word was already found stop for that case.
So basically you iterate of wordIndex and ruleIndex. Recursive formulation is easiest, and can later be changed to iterative. You could make two level of recursion: walk rules, walk inside word.
Okay, in java:
public class Solver {
public static void main(String[] args) {
System.out.println("Solver");
Solver solver = new Solver("j=>i", "i=>j", "v=>u", "u=>v", "s=>f",
"f=>s", "uu=>w", "vv=>w");
//Set<String> words = solver.determineAllWords("murdir");
Set<String> words = solver.determineAllWords("gigi");
words.forEach(System.out::println);
System.out.println("Done");
}
static class Rule {
String from;
String to;
public Rule(String from, String to) {
this.from = from;
this.to = to;
}
}
private final Rule[] rules;
public Solver(String... tofroms) {
this.rules = new Rule[tofroms.length];
for (int i = 0; i < rules.length; ++i) {
String[] tofrom = tofroms[i].split("=>", 2);
rules[i] = new Rule(tofrom[0], tofrom[1]);
}
}
public Set<String> determineAllWords(String word) {
Set<String> solutionWords = new TreeSet<String>(); // Could be a field too.
solutionWords.add(word);
int ruleIndex = 0;
int wordIndex = 0;
solveTryingRules(solutionWords, word, wordIndex, ruleIndex);
return solutionWords;
}
private void solveTryingRules(Set<String> solutionWords,
String word, int wordIndex, int ruleIndex) {
if (ruleIndex >= rules.length) {
return;
}
Rule rule = rules[ruleIndex];
int wordIndexFound = word.indexOf(rule.from, wordIndex);
if (wordIndexFound == -1) {
// Next rule:
solveTryingRules(solutionWords, word, 0, ruleIndex + 1);
} else {
// Keep at same rule,
// Not applying rule to found word position:
solveTryingRules(solutionWords, word, wordIndexFound + 1, ruleIndex);
// Applying rule to found word position:
String nextWord = word.substring(0, wordIndexFound)
+ rule.to
+ word.substring(wordIndexFound + rule.from.length());
boolean added = solutionWords.add(nextWord);
if (added) {
solveTryingRules(solutionWords, nextWord, 0, 0);
}
}
}
}
If you need to do it recursively, how about this? This is python-like pseudocode.
#
# make a list of locations of all possible typos
#
s = [] # list
for i in range(0, len(source)):
if source[i] might be typo:
s.append(i)
#
# and to the recursion to find all combinations
#
print do_recurse(source, s)
#
# method that returns the correct char corresponding to the typo
#
def correction(char):
# you should implement
#
# the actual recursion method
#
def do_recurse(str, locations):
'''
return the list of all combinations
'''
if len(locations) <= 0:
return []
ret = []
for loc in locations:
# do the recursion with the string before the modification
r = do_recurse(str, locations[1:])
ret.extend( r )
# do the recursion with the modified string
str[loc] = correction(str[loc])
r = do_recurse(str, locations[1:])
ret.extend( r )
return ret
If your problem is just tracking the changes and you want to be sure you generated all the combination but none of them twice, all you need is to find an ordering of the set of all the possible combinations.
I'd map your list of possible replacements to a sequence of bits, like this:
j=>i ~ bit 0
i=>j ~ bit 1
v=>u ~ bit 2
u=>v ~ bit 3
s=>f ~ bit 4
f=>s ~ bit 5
uu=>w ~ bit 6
vv=>w ~ bit 7
76543210
00101011 means you replace j=>i, i=>j, u=>v, f=>s
11000001 means you replace j=>i, uu=>w, vv=>w
Then implement some kind of binary counting (0, 1, 10, 11, 100, 101, 110, 111, 1000, 1001, 1010, 1011, 1100, ...) and generate the combinations based on the number.
I do not mean they have to be literally bits of a single long/integer variable, but the idea of ordering is this. Of course if you do not have more then 64 replacements then one single long variable is good:
String input = ...
List<...> replacements = ...
List<String> combinations = new ArrayList<>();
for (long count = 0; count < ...; count++) {
String output = input;
for (bit = 0; bit < 64; bit++) {
if ((count & (1L << bit)) != 0) { // the bit is set
// replace the characters based on replacements.get(bit)
// output = ...
}
}
combinations.add(output);
}
If you want to have it working for more unlimited number of replacements (> 64), you may use the same idea of ordering the set of all the combination and implement based on the ideas from Variable Number of Nested For Loops.
I want to know how to generate all words using java from specified characters and length
String first[]={"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"};
String second[]={"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"};
String ch ="";
String total[];
for(int i = 0;i<26;i++) {
for(int j = 0;j<26;j++) {
ch+=first[i]+first[j];
System.out.println(ch);
}
}
I get only 576 words only by this program, but the 26! words is 4.03291461 × 10^26
How to write the program in java?
public class Words {
static char[] alphabet = "abcdefghijklmnopqrstuvwxyz".toCharArray();
static void generate(StringBuilder sb, int n) {
if (n == sb.length()) {
System.out.println(sb.toString());
return;
}
for (char letter : alphabet) {
sb.setCharAt(n, letter);
generate(sb, n + 1);
}
}
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
for (int length = 2; length <= 5; length++) {
sb.setLength(length);
generate(sb, 0);
}
}
}
This generates all 2-letters, 3-letters, 4-letters, and 5-letters "words". It uses a standard recursive algorithm.
See also
Given an array of integers [x0 x1 x2], how do you calculate all possible permutations from [0 0 0] to [x0 x1 x2]?
On a more mathematical note, people often confuse what the term "permutation" means. Yes, there are 26! permutations of the 26 letters a-z -- that's A LOT of strings, but this does not include aa, ab, etc. It includes all strings where the 26 letters each appear exactly once.
Consider what you're doing:
you're looping through the first array once, and looping through the second once for each iteration through that loop.
That's going to yield you a total of 26^2 results, or 676 (not 576).
And the way you're constructing the output is very specific, check what you get and you'll notice a highly explicit pattern in there.
The second array of course is never used at all, so completely superfluous.
The solution is to write out on paper how you'd go about it were you to attempt it by hand, then attempt to translate that into code.
For one you're not going to want to have only words of a specific length (which you get) or specific patterns of letters (which you also get).
but the 26! words is 4.03291461 × 1026
how to write the program in java
You don't write that program in Java or any other language. It would be pointless because it would literally take billions of years to finish.
But the number is also completely wrong for your intended result in the comments. 26! is the number of permutations, i.e. the different ways to order 26 elements without repetition. The number of words would be 26^n, where n is the length.
Here's my solution. It's kind of quick, so don't be too hard on the optimization.
public static void printWords(int length) {
if (length < 1)
throw new IllegalArgumentException();
printWordsRec("", length);
}
private static void printWordsRec(String base, int length) {
for (char c = 'a'; c <= 'z'; c++) {
if (length == 1) {
System.out.println(base + c);
}
else {
printWordsRec(base + c, length - 1);
}
}
}