deleting an object from an array of objects in java - java

import java.util.StringTokenizer;
class Count {
int count;
String name;
void SetCount(int c, String n) {
this.count = c;
this.name = n;
}
void Show() {
System.out.print("Word= " + name);
System.out.print(" Count= " + count);
System.out.println();
}
}
class Contains2 extends Count {
public static void main(String args[]) {
String s = "Hello this program will repeat itself for this useless purpose and will not end until it repeats itself again and again and again so watch out";
int i, c2, j;
StringTokenizer st = new StringTokenizer(s, " ");
c2 = st.countTokens();
String[] test = new String[c2];
Count[] c = new Count[c2];
for (i = 0; i < c2; i++) {
c[i] = new Count();
}
i = 0;
while (st.hasMoreTokens()) {
String token = st.nextToken();
test[i] = token;
c[i].SetCount(0, test[i]);
i++;
}
for (i = 0; i < c2; i++) {
for (j = 0; j < c2; j++) {
if (c[i].name.equals(test[j]))
c[i].count += 1;
}
}
for (i = 0; i < c2; i++) {
c[i].Show();
}
}
}
so i made this small program to count the number every word was repeated in a paragraph. its working as planned but now i am getting duplicates of every word since i made separate objects for each and printing them all. so is there any way i could delete the duplicate words i mean deleting those objects based on their names. i can set them to null but it would still print them so i just wanna get rid of them or skip them somehow

You cannot adjust the size of a array once it's created. You could only create a new array with a different size and copy the non-null elements.
You could also set elements to null and just ignore those elements for printing...
for (i = 0; i < c2; i++) {
if (c[i] != null)
c[i].Show();
}
An alternative would be using a List, which allows you to remove elements.
Alternatively a Map<String, Integer> mapping from a word to the count could be used. In this case you don't even need the Count class:
String s = "Hello this program will repeat itself for this useless purpose and will not end until it repeats itself again and again and again so watch out";
StringTokenizer st = new StringTokenizer(s, " ");
Map<String, Integer> map = new HashMap<>();
while (st.hasMoreTokens()) {
map.merge(st.nextToken(), 1, Integer::sum);
}
for (Map.Entry<String, Integer> e : map.entrySet()) {
System.out.print("Word= " + e.getKey());
System.out.print(" Count= " + e.getValue());
System.out.println();
}

Related

Java How to print -1 if the given letter1 is not present

I would like to write a program that is taking letter position from two strings, string1 and string2, then it will check where in string2 we have the same letters used but also print number of indexes and if there is no letter that is in the first string just print -1 . For example I have first string = "reds" second one = "Hello world!", then my output should be:
r: 8, e: 1, d: 10, s: -1
Here is my code:
public static void main(String[] args){
String set1 = "reds";
String set2 = "Hello world!";
for(int i = 0; i < set1.length(); i++)
{
for(int j = 0; j < set2.length();j++)
{
char currentChar = set1.charAt(i);
char currentChar2 = set2.charAt(j);
if(currentChar == currentChar2)
{
System.out.println(currentChar+": "+j);
}
}
}
}
}
Another ways using String.indexOf
Classic for loop
String set1 = "reds";
String set2 = "Hello world!";
for(int i = 0; i < set1.length(); i++){
System.out.println(set1.charAt(i) + " : " + set2.indexOf(set1.charAt(i)));
}
or streams
set1.chars()
.mapToObj(c -> (char)c + " : " + set2.indexOf(c))
.forEach(System.out::println);
Note: if the chars apear more than once in the second string the first index of the chars is printed (use lastIndexOf if you want the last index)
public static void main(String[] args){
String set1 = "reds";
String set2 = "Hello world!";
for(int i = 0; i < set1.length(); i++) {
char currentChar = set1.charAt(i);
boolean found = false;
for(int j = 0; j < set2.length();j++) {
char currentChar2 = set2.charAt(j);
if(currentChar == currentChar2) {
System.out.println(currentChar+": "+j);
found = true;
}
}
if(!found) {
System.out.println(currentChar + ": -1");
}
}
}
It will print every position of the set1 characters into set2.
O(n + m) time complexity, where n and m are the sizes of set1 and set2
O(256) space complexity because of ASCII numbers
public static void main(String[] args){
String set1 = "reds";
String set2 = "Hello world!";
Map<Integer, List<Integer>> map = new HashMap<>(); // key = ascii value of the char, value = list of indexes
for(int i = 0; i < set2.length(); i++){
int key = set2.charAt(i);
if(!map.containsKey(key)){
map.put(key, new ArrayList<>());
}
List<Integer> indexesList = map.get(key);
indexesList.add(i);
map.put(key, indexesList);
}
for(int i = 0; i < set1.length(); i++){
int key = set1.charAt(i);
System.out.print(set1.charAt(i) + ": ");
if(!map.containsKey(key)){
System.out.println(-1);
}
else {
map.get(key).forEach(x-> System.out.print(x+ " "));
System.out.println(); // just for new line
}
}
}

find the occurrence of substrings in string given two list

Given two List sentence and List queries
I have two find the occurrence of queries in sentences.
Example,
"Pulkit likes StackOverflow and coding"
"Pulkit does not like Reddit"
"Pulkit like ice cream"
Queries
Pulkit coding
like
does
The function should return for the queries
sentence[0]
sentence[1], sentence[2]
sentence[1]
I solved this question already using HashMap but it is quadratic and I am wondering how to do it in linear time.
Solution
public static void findMatch(List<String> sentences, List<String> queries) {
// Write your code here
// Split the sentences into terms and map them by index
Map<Integer, Set<String>> sentencesSplit = new HashMap<>();
for (int j = 0; j < sentences.size(); j++) {
String[] splitSentence = sentences.get(j).split(" ");
Set<String> sentenceSet = new HashSet<>();
sentencesSplit.put(j, sentenceSet);
for (int i = 0; i < splitSentence.length; i++) {
sentenceSet.add(splitSentence[i]);
}
}
// Split the query into terms and map them by index
Map<Integer, String[]> queriesSplit = new HashMap<>();
for (int i = 0; i < queries.size(); i++) {
queriesSplit.put(i, queries.get(i).split(" "));
}
for (int i = 0; i < queries.size(); i++) {
String found = null;
for (int j = 0; j < sentences.size(); j++) {
String[] splitQuery = queriesSplit.get(i);
Set<String> sentenceStringList = sentencesSplit.get(j);
boolean notFound = false;
for (int k = 0; k < splitQuery.length; k++) {
if (!sentenceStringList.contains(splitQuery[k])) {
notFound = true;
break;
}
}
if (!notFound) {
if (found == null) {
found = "" + j;
} else {
found += " " + j;
}
}
}
if (found == null) {
found = "-1";
}
System.out.println(found);
}
}
My code is similar with human's thinking.
\b allows you to perform a "whole words only" search using a regular expression in the form of \bword\b.
Hope my code will help you.
public class MainClass {
public static void main(String [] args)
{
List<String> sentences = new ArrayList<String>();
sentences.add("Pulkit likes StackOverflow and coding");
sentences.add("Pulkit does not like Reddit");
sentences.add("Pulkit like ice cream");
List<String> queries = new ArrayList<String>();
queries.add("Pulkit coding");
queries.add("like");
queries.add("does");
findMatch(sentences, queries);
}
public static void findMatch(List<String> sentences, List<String> queries) {
for(String query : queries) {
System.out.print("]");
String match = ".*\\b" + query.replace(" ", "\\b.*") + "\\b.*";
for (int iSentence = 0; iSentence < sentences.size(); iSentence++) {
if(sentences.get(iSentence).matches(match)) {
System.out.print(" " + iSentence);
}
}
System.out.println("");
}
}
}
Console output:
] 0
] 1 2
] 1

Java: Print a unique character in a string

I'm writing a program that will print the unique character in a string (entered through a scanner). I've created a method that tries to accomplish this but I keep getting characters that are not repeats, instead of a character (or characters) that is unique to the string. I want the unique letters only.
Here's my code:
import java.util.Scanner;
public class Sameness{
public static void main (String[]args){
Scanner kb = new Scanner (System.in);
String word = "";
System.out.println("Enter a word: ");
word = kb.nextLine();
uniqueCharacters(word);
}
public static void uniqueCharacters(String test){
String temp = "";
for (int i = 0; i < test.length(); i++){
if (temp.indexOf(test.charAt(i)) == - 1){
temp = temp + test.charAt(i);
}
}
System.out.println(temp + " ");
}
}
And here's sample output with the above code:
Enter a word:
nreena
nrea
The expected output would be: ra
Based on your desired output, you have to replace a character that initially has been already added when it has a duplicated later, so:
public static void uniqueCharacters(String test){
String temp = "";
for (int i = 0; i < test.length(); i++){
char current = test.charAt(i);
if (temp.indexOf(current) < 0){
temp = temp + current;
} else {
temp = temp.replace(String.valueOf(current), "");
}
}
System.out.println(temp + " ");
}
How about applying the KISS principle:
public static void uniqueCharacters(String test) {
System.out.println(test.chars().distinct().mapToObj(c -> String.valueOf((char)c)).collect(Collectors.joining()));
}
The accepted answer will not pass all the test case for example
input -"aaabcdd"
desired output-"bc"
but the accepted answer will give -abc
because the character a present odd number of times.
Here I have used ConcurrentHasMap to store character and the number of occurrences of character then removed the character if the occurrences is more than one time.
import java.util.concurrent.ConcurrentHashMap;
public class RemoveConductive {
public static void main(String[] args) {
String s="aabcddkkbghff";
String[] cvrtar=s.trim().split("");
ConcurrentHashMap<String,Integer> hm=new ConcurrentHashMap<>();
for(int i=0;i<cvrtar.length;i++){
if(!hm.containsKey(cvrtar[i])){
hm.put(cvrtar[i],1);
}
else{
hm.put(cvrtar[i],hm.get(cvrtar[i])+1);
}
}
for(String ele:hm.keySet()){
if(hm.get(ele)>1){
hm.remove(ele);
}
}
for(String key:hm.keySet()){
System.out.print(key);
}
}
}
Though to approach a solution I would suggest you to try and use a better data structure and not just string. Yet, you can simply modify your logic to delete already existing duplicates using an else as follows :
public static void uniqueCharacters(String test) {
String temp = "";
for (int i = 0; i < test.length(); i++) {
char ch = test.charAt(i);
if (temp.indexOf(ch) == -1) {
temp = temp + ch;
} else {
temp.replace(String.valueOf(ch),""); // added this to your existing code
}
}
System.out.println(temp + " ");
}
This is an interview question. Find Out all the unique characters of a string.
Here is the complete solution. The code itself is self explanatory.
public class Test12 {
public static void main(String[] args) {
String a = "ProtijayiGiniGina";
allunique(a);
}
private static void allunique(String a) {
int[] count = new int[256];// taking count of characters
for (int i = 0; i < a.length(); i++) {
char ch = a.charAt(i);
count[ch]++;
}
for (int i = 0; i < a.length(); i++) {
char chh = a.charAt(i);
// character which has arrived only one time in the string will be printed out
if (count[chh] == 1) {
System.out.println("index => " + i + " and unique character => " + a.charAt(i));
}
}
}// unique
}
In Python :
def firstUniqChar(a):
count = [0] *256
for i in a: count[ord(i)] += 1
element = ""
for item in a:
if (count[ord(item)] == 1):
element = item;
break;
return element
a = "GiniGinaProtijayi";
print(firstUniqChar(a)) # output is P
public static String input = "10 5 5 10 6 6 2 3 1 3 4 5 3";
public static void uniqueValue (String numbers) {
String [] str = input.split(" ");
Set <String> unique = new HashSet <String> (Arrays.asList(str));
System.out.println(unique);
for (String value:unique) {
int count = 0;
for ( int i= 0; i<str.length; i++) {
if (value.equals(str[i])) {
count++;
}
}
System.out.println(value+"\t"+count);
}
}
public static void main(String [] args) {
uniqueValue(input);
}
Step1: To find the unique characters in a string, I have first taken the string from user.
Step2: Converted the input string to charArray using built in function in java.
Step3: Considered two HashSet (set1 for storing all characters even if it is getting repeated, set2 for storing only unique characters.
Step4 : Run for loop over the array and check that if particular character is not there in set1 then add it to both set1 and set2. if that particular character is already there in set1 then add it to set1 again but remove it from set2.( This else part is useful when particular character is getting repeated odd number of times).
Step5 : Now set2 will have only unique characters. Hence, just print that set2.
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
String str = input.next();
char arr[] = str.toCharArray();
HashSet<Character> set1=new HashSet<Character>();
HashSet<Character> set2=new HashSet<Character>();
for(char i:arr)
{
if(set1.contains(i))
{
set1.add(i);
set2.remove(i);
}
else
{
set1.add(i);
set2.add(i);
}
}
System.out.println(set2);
}
I would store all the characters of the string in an array that you will loop through to check if the current characters appears there more than once. If it doesn't, then add it to temp.
public static void uniqueCharacters(String test) {
String temp = "";
char[] array = test.toCharArray();
int count; //keep track of how many times the character exists in the string
outerloop: for (int i = 0; i < test.length(); i++) {
count = 0; //reset the count for every new letter
for(int j = 0; j < array.length; j++) {
if(test.charAt(i) == array[j])
count++;
if(count == 2){
count = 0;
continue outerloop; //move on to the next letter in the string; this will skip the next two lines below
}
}
temp += test.charAt(i);
System.out.println("Adding.");
}
System.out.println(temp);
}
I have added comments for some more detail.
import java.util.*;
import java.lang.*;
class Demo
{
public static void main(String[] args)
{
Scanner sc=new Scanner(System.in);
System.out.println("Enter String");
String s1=sc.nextLine();
try{
HashSet<Object> h=new HashSet<Object>();
for(int i=0;i<s1.length();i++)
{
h.add(s1.charAt(i));
}
Iterator<Object> itr=h.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
catch(Exception e)
{
System.out.println("error");
}
}
}
If you don't want to use additional space:
String abc="developer";
System.out.println("The unique characters are-");
for(int i=0;i<abc.length();i++)
{
for(int j=i+1;j<abc.length();j++)
{
if(abc.charAt(i)==abc.charAt(j))
abc=abc.replace(String.valueOf(abc.charAt(j))," ");
}
}
System.out.println(abc);
Time complexity O(n^2) and no space.
This String algorithm is used to print unique characters in a string.It runs in O(n) runtime where n is the length of the string.It supports ASCII characters only.
static String printUniqChar(String s) {
StringBuilder buildUniq = new StringBuilder();
boolean[] uniqCheck = new boolean[128];
for (int i = 0; i < s.length(); i++) {
if (!uniqCheck[s.charAt(i)]) {
uniqCheck[s.charAt(i)] = true;
if (uniqCheck[s.charAt(i)])
buildUniq.append(s.charAt(i));
}
}
public class UniqueCharactersInString {
public static void main(String []args){
String input = "aabbcc";
String output = uniqueString(input);
System.out.println(output);
}
public static String uniqueString(String s){
HashSet<Character> uniques = new HashSet<>();
uniques.add(s.charAt(0));
String out = "";
out += s.charAt(0);
for(int i =1; i < s.length(); i++){
if(!uniques.contains(s.charAt(i))){
uniques.add(s.charAt(i));
out += s.charAt(i);
}
}
return out;
}
}
What would be the inneficiencies of this answer? How does it compare to other answers?
Based on your desired output you can replace each character already present with a blank character.
public static void uniqueCharacters(String test){
String temp = "";
for(int i = 0; i < test.length(); i++){
if (temp.indexOf(test.charAt(i)) == - 1){
temp = temp + test.charAt(i);
} else {
temp.replace(String.valueOf(temp.charAt(i)), "");
}
}
System.out.println(temp + " ");
}
public void uniq(String inputString) {
String result = "";
int inputStringLen = inputStr.length();
int[] repeatedCharacters = new int[inputStringLen];
char inputTmpChar;
char tmpChar;
for (int i = 0; i < inputStringLen; i++) {
inputTmpChar = inputStr.charAt(i);
for (int j = 0; j < inputStringLen; j++) {
tmpChar = inputStr.charAt(j);
if (inputTmpChar == tmpChar)
repeatedCharacters[i]++;
}
}
for (int k = 0; k < inputStringLen; k++) {
inputTmpChar = inputStr.charAt(k);
if (repeatedCharacters[k] == 1)
result = result + inputTmpChar + " ";
}
System.out.println ("Unique characters: " + result);
}
In first for loop I count the number of times the character repeats in the string. In the second line I am looking for characters repetitive once.
how about this :)
for (int i=0; i< input.length();i++)
if(input.indexOf(input.charAt(i)) == input.lastIndexOf(input.charAt(i)))
System.out.println(input.charAt(i) + " is unique");
package extra;
public class TempClass {
public static void main(String[] args) {
// TODO Auto-generated method stub
String abcString="hsfj'pwue2hsu38bf74sa';fwe'rwe34hrfafnosdfoasq7433qweid";
char[] myCharArray=abcString.toCharArray();
TempClass mClass=new TempClass();
mClass.countUnique(myCharArray);
mClass.countEach(myCharArray);
}
/**
* This is the program to find unique characters in array.
* #add This is nice.
* */
public void countUnique(char[] myCharArray) {
int arrayLength=myCharArray.length;
System.out.println("Array Length is: "+arrayLength);
char[] uniqueValues=new char[myCharArray.length];
int uniqueValueIndex=0;
int count=0;
for(int i=0;i<arrayLength;i++) {
for(int j=0;j<arrayLength;j++) {
if (myCharArray[i]==myCharArray[j] && i!=j) {
count=count+1;
}
}
if (count==0) {
uniqueValues[uniqueValueIndex]=myCharArray[i];
uniqueValueIndex=uniqueValueIndex+1;
count=0;
}
count=0;
}
for(char a:uniqueValues) {
System.out.println(a);
}
}
/**
* This is the program to find count each characters in array.
* #add This is nice.
* */
public void countEach(char[] myCharArray) {
}
}
Here str will be your string to find the unique characters.
function getUniqueChars(str){
let uniqueChars = '';
for(let i = 0; i< str.length; i++){
for(let j= 0; j< str.length; j++) {
if(str.indexOf(str[i]) === str.lastIndexOf(str[j])) {
uniqueChars += str[i];
}
}
}
return uniqueChars;
}
public static void main(String[] args) {
String s = "aaabcdd";
char a[] = s.toCharArray();
List duplicates = new ArrayList();
List uniqueElements = new ArrayList();
for (int i = 0; i < a.length; i++) {
uniqueElements.add(a[i]);
for (int j = i + 1; j < a.length; j++) {
if (a[i] == a[j]) {
duplicates.add(a[i]);
break;
}
}
}
uniqueElements.removeAll(duplicates);
System.out.println(uniqueElements);
System.out.println("First Unique : "+uniqueElements.get(0));
}
Output :
[b, c]
First Unique : b
import java.util.*;
public class Sameness{
public static void main (String[]args){
Scanner kb = new Scanner (System.in);
String word = "";
System.out.println("Enter a word: ");
word = kb.nextLine();
uniqueCharacters(word);
}
public static void uniqueCharacters(String test){
for(int i=0;i<test.length();i++){
if(test.lastIndexOf(test.charAt(i))!=i)
test=test.replaceAll(String.valueOf(test.charAt(i)),"");
}
System.out.println(test);
}
}
public class Program02
{
public static void main(String[] args)
{
String inputString = "abhilasha";
for (int i = 0; i < inputString.length(); i++)
{
for (int j = i + 1; j < inputString.length(); j++)
{
if(inputString.toCharArray()[i] == inputString.toCharArray()[j])
{
inputString = inputString.replace(String.valueOf(inputString.charAt(j)), "");
}
}
}
System.out.println(inputString);
}
}

Want to count occurances of Strings in Java

So I have a .txt file which I am calling using
String[] data = loadStrings("data/data.txt");
The file is already sorted and essentially looks like:
Animal
Animal
Cat
Cat
Cat
Dog
I am looking to create an algorithm to count the sorted list in java, without using any libraries like Multisets or without the use of Maps/HashMaps. I have managed so far to get it print out the top occurring word like so:
ArrayList<String> words = new ArrayList();
int[] occurrence = new int[2000];
Arrays.sort(data);
for (int i = 0; i < data.length; i ++ ) {
words.add(data[i]); //Put each word into the words ArrayList
}
for(int i =0; i<data.length; i++) {
occurrence[i] =0;
for(int j=i+1; j<data.length; j++) {
if(data[i].equals(data[j])) {
occurrence[i] = occurrence[i]+1;
}
}
}
int max = 0;
String most_talked ="";
for(int i =0;i<data.length;i++) {
if(occurrence[i]>max) {
max = occurrence[i];
most_talked = data[i];
}
}
println("The most talked keyword is " + most_talked + " occuring " + max + " times.");
I want rather than just to get the highest occurring word perhaps the top 5 or top 10.
Hope that was clear enough. Thanks for reading
Since you said you dont want to use some kind of data structure i think that you can do something like this, but it is not performant.
I usually prefer to store index rather than values.
ArrayList<String> words = new ArrayList();
int[] occurrence = new int[2000];
Arrays.sort(data);
int nwords = 0;
occurrence[nwords]=1;
words.add(data[0]);
for (int i = 1; i < data.length; i ++ ) {
if(!data[i].equals(data[i-1])){ //if a new word is found
words.add(data[i]); //put it into the words ArrayList
nwords++; //increment the index
occurrence[nwords]=0; //initialize its occurrence counter
}
occurrence[nwords]++; //increment the occurrence counter
}
int max;
for(int k=0; k<5; k++){ //loop to find 5 times the most talked word
max = 0; //index of the most talked word
for(int i = 1; i<words.size(); i++) { //for every word
if(occurrence[i]>occurrence[max]) { //if it is more talked than max
max = i; //than it is the new most talked
}
}
println("The most talked keyword is " + words.get(max) + " occuring " + occurence[max] + " times.");
occurence[max]=0;
}
Every time I find the value with the higher occurence value, i set his occurrence counter to 0 and I reiterate again the array, this for 5 times.
If you cannot use Guava's Multiset, then you can implement an equivalent yourself. Basically, you just need to create a Map<String, Integer>, which keeps track of counts (value) per each word (key). This means changing this
ArrayList<String> words = new ArrayList<String>();
// ...
for (int i = 0; i < data.length; i ++ ) {
words.add(data[i]); //Put each word into the words ArrayList
}
into this:
Map<String, Integer> words = new HashMap<String>();
// ...
for (String word : data) {
Integer count = words.get(word);
words.put(word, (count != null : count.intValue() + 1 ? 1));
}
After you've filled the map, just sort it by the values.
If you cannot use a Map either, you can do the following:
First, create a wrapper class for your word counts:
public class WordCount implements Comparable<WordCount> {
private String word;
private int count;
public WordCount(String w, int c) {
this.word = w;
this.count = c;
}
public String getWord() {
return word;
}
public int getCount() {
return count;
}
public void incrementCount() {
count++;
}
#Override
public int compareTo(WordCount other) {
return this.count - other.count;
}
}
Then, change your code to store WordCount instances in your list (instead of Strings):
ArrayList<WordCount> words = new ArrayList<WordCount>();
// ...
for (String word : data) {
WordCount wc = new WordCount(word, 1);
boolean wordFound = false;
for (WordCount existing : words) {
if (existing.getWord().equals(wc.getWord())) {
existing.incrementCount();
wordFound = true;
break;
}
}
if (!wordFound) {
words.add(wc);
}
}
Finally, after populating the List, simply sort it using Collections.sort(). This is easy because the value objects implement Comparable:
Collections.sort(words, Collections.reverseOrder());
You could try something simple like this..
int count = 0;
for( int i = 0; i < words.size(); i++ ){
System.out.printf("%s: ", words.get( i ));
for( int j = 0; j < words.size(); j++ ) {
if( words.get( i ).equals( words.get( j ) ) )
count++;
}
System.out.printf( "%d\n", count );
}

Smart way to generate permutation and combination of String

String database[] = {'a', 'b', 'c'};
I would like to generate the following strings sequence, based on given database.
a
b
c
aa
ab
ac
ba
bb
bc
ca
cb
cc
aaa
...
I can only think of a pretty "dummy" solution.
public class JavaApplication21 {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
char[] database = {'a', 'b', 'c'};
String query = "a";
StringBuilder query_sb = new StringBuilder(query);
for (int a = 0; a < database.length; a++) {
query_sb.setCharAt(0, database[a]);
query = query_sb.toString();
System.out.println(query);
}
query = "aa";
query_sb = new StringBuilder(query);
for (int a = 0; a < database.length; a++) {
query_sb.setCharAt(0, database[a]);
for (int b = 0; b < database.length; b++) {
query_sb.setCharAt(1, database[b]);
query = query_sb.toString();
System.out.println(query);
}
}
query = "aaa";
query_sb = new StringBuilder(query);
for (int a = 0; a < database.length; a++) {
query_sb.setCharAt(0, database[a]);
for (int b = 0; b < database.length; b++) {
query_sb.setCharAt(1, database[b]);
for (int c = 0; c < database.length; c++) {
query_sb.setCharAt(2, database[c]);
query = query_sb.toString();
System.out.println(query);
}
}
}
}
}
The solution is pretty dumb. It is not scale-able in the sense that
What if I increase the size of database?
What if my final targeted print String length need to be N?
Is there any smart code, which can generate scale-able permutation and combination string in a really smart way?
You should check this answer: Getting every possible permutation of a string or combination including repeated characters in Java
To get this code:
public static String[] getAllLists(String[] elements, int lengthOfList)
{
//lists of length 1 are just the original elements
if(lengthOfList == 1) return elements;
else {
//initialize our returned list with the number of elements calculated above
String[] allLists = new String[(int)Math.pow(elements.length, lengthOfList)];
//the recursion--get all lists of length 3, length 2, all the way up to 1
String[] allSublists = getAllLists(elements, lengthOfList - 1);
//append the sublists to each element
int arrayIndex = 0;
for(int i = 0; i < elements.length; i++){
for(int j = 0; j < allSublists.length; j++){
//add the newly appended combination to the list
allLists[arrayIndex] = elements[i] + allSublists[j];
arrayIndex++;
}
}
return allLists;
}
}
public static void main(String[] args){
String[] database = {"a","b","c"};
for(int i=1; i<=database.length; i++){
String[] result = getAllLists(database, i);
for(int j=0; j<result.length; j++){
System.out.println(result[j]);
}
}
}
Although further improvement in memory could be made, since this solution generates all solution to memory first (the array), before we can print it. But the idea is the same, which is to use recursive algorithm.
This smells like counting in binary:
001
010
011
100
101
...
My first instinct would be to use a binary counter as a "bitmap" of characters to generate those the possible values. However, there are several wonderful answer to related questions here that suggest using recursion. See
How do I make this combinations/permutations method recursive?
Find out all combinations and permutations - Java
java string permutations and combinations lookup
http://www.programmerinterview.com/index.php/recursion/permutations-of-a-string/
Java implementation of your permutation generator:-
public class Permutations {
public static void permGen(char[] s,int i,int k,char[] buff) {
if(i<k) {
for(int j=0;j<s.length;j++) {
buff[i] = s[j];
permGen(s,i+1,k,buff);
}
}
else {
System.out.println(String.valueOf(buff));
}
}
public static void main(String[] args) {
char[] database = {'a', 'b', 'c'};
char[] buff = new char[database.length];
int k = database.length;
for(int i=1;i<=k;i++) {
permGen(database,0,i,buff);
}
}
}
Ok, so the best solution to permutations is recursion. Say you had n different letters in the string. That would produce n sub problems, one for each set of permutations starting with each unique letter. Create a method permutationsWithPrefix(String thePrefix, String theString) which will solve these individual problems. Create another method listPermutations(String theString) a implementation would be something like
void permutationsWithPrefix(String thePrefix, String theString) {
if ( !theString.length ) println(thePrefix + theString);
for(int i = 0; i < theString.length; i ++ ) {
char c = theString.charAt(i);
String workingOn = theString.subString(0, i) + theString.subString(i+1);
permutationsWithPrefix(prefix + c, workingOn);
}
}
void listPermutations(String theString) {
permutationsWithPrefix("", theString);
}
i came across this question as one of the interview question. Following is the solution that i have implemented for this problem using recursion.
public class PasswordCracker {
private List<String> doComputations(String inputString) {
List<String> totalList = new ArrayList<String>();
for (int i = 1; i <= inputString.length(); i++) {
totalList.addAll(getCombinationsPerLength(inputString, i));
}
return totalList;
}
private ArrayList<String> getCombinationsPerLength(
String inputString, int i) {
ArrayList<String> combinations = new ArrayList<String>();
if (i == 1) {
char [] charArray = inputString.toCharArray();
for (int j = 0; j < charArray.length; j++) {
combinations.add(((Character)charArray[j]).toString());
}
return combinations;
}
for (int j = 0; j < inputString.length(); j++) {
ArrayList<String> combs = getCombinationsPerLength(inputString, i-1);
for (String string : combs) {
combinations.add(inputString.charAt(j) + string);
}
}
return combinations;
}
public static void main(String args[]) {
String testString = "abc";
PasswordCracker crackerTest = new PasswordCracker();
System.out.println(crackerTest.doComputations(testString));
}
}
For anyone looking for non-recursive options, here is a sample for numeric permutations (can easily be adapted to char. numberOfAgents is the number of columns and the set of numbers is 0 to numberOfActions:
int numberOfAgents=5;
int numberOfActions = 8;
byte[][]combinations = new byte[(int)Math.pow(numberOfActions,numberOfAgents)][numberOfAgents];
// do each column separately
for (byte j = 0; j < numberOfAgents; j++) {
// for this column, repeat each option in the set 'reps' times
int reps = (int) Math.pow(numberOfActions, j);
// for each column, repeat the whole set of options until we reach the end
int counter=0;
while(counter<combinations.length) {
// for each option
for (byte i = 0; i < numberOfActions; i++) {
// save each option 'reps' times
for (int k = 0; k < reps; k++)
combinations[counter + i * reps + k][j] = i;
}
// increase counter by 'reps' times amount of actions
counter+=reps*numberOfActions;
}
}
// print
for(byte[] setOfActions : combinations) {
for (byte b : setOfActions)
System.out.print(b);
System.out.println();
}
// IF YOU NEED REPEATITION USE ARRAYLIST INSTEAD OF SET!!
import java.util.*;
public class Permutation {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
System.out.println("ENTER A STRING");
Set<String> se=find(in.nextLine());
System.out.println((se));
}
public static Set<String> find(String s)
{
Set<String> ss=new HashSet<String>();
if(s==null)
{
return null;
}
if(s.length()==0)
{
ss.add("");
}
else
{
char c=s.charAt(0);
String st=s.substring(1);
Set<String> qq=find(st);
for(String str:qq)
{
for(int i=0;i<=str.length();i++)
{
ss.add(comb(str,c,i));
}
}
}
return ss;
}
public static String comb(String s,char c,int i)
{
String start=s.substring(0,i);
String end=s.substring(i);
return start+c+end;
}
}
// IF YOU NEED REPEATITION USE ARRAYLIST INSTEAD OF SET!!

Categories

Resources