Smartly building pair elements in different lists - java

I am building a mind game, it's hard to explain so I put an example.
I have a list of words (it can be infinite):
String myList[] = {"chair", "house", "ocean", "plane", "dog", "TV", "grass", "money" etc....}
Now the tricky part, I need to build 4 lists of pair index/word (every list has the same size) randomly but that fit these rule:
if I chose a number, the word that match this number only appears in 2 lists.
for example this would be correct:
List1:
1/chair
2/house
3/plane
4/grass
List2
1/chair
2/dog
3/plane
4/TV
List3:
1/ocean
2/house
3/money
4/TV
List4
1/ocean
2/dog
3/money
4/grass
For example:
If I pick number 3, then list 3 and list 4 match the word 'money', list 1 and 2 match the word 'plane'. There always must be 2 matching lists (never less, never more). They should be build from a huge array of words randomly, so you can't guess which list will be matching when you pick a number.
I tried to do it with a nice simple recursive algorithm. But I badly failed.

My initial approach to this problem would be to
Select a random word in the universe
Assign the selected word to two lists that
are different and
are not full
Store the random word in a set of closed words in case it is selected again
Rinse and repeat until all lists are full

Something like this should do the trick (you can change the provided words and the respective listSize accordingly). The number of words should be dividable by the listSize in order to fill up all lists.
public static void main(String[] args) {
String[] words = new String[] { "chair", "house", "ocean", "plane",
"dog", "TV", "grass", "money" };
// valid list sizes for 8 words: 1, 2, 4, 8
int listSize = 4;
List<String[]> result = distributeRandomly(words, listSize);
for (String[] resultList : result) {
for (int index = 0; index < listSize; index++) {
System.out.println((index + 1) + "/" + resultList[index]);
}
System.out.println();
}
}
private static List<String[]> distributeRandomly(String[] words, int listSize) {
// each word goes into 2 lists, so how many lists do we need?
int listCount = words.length * 2 / listSize;
if (listCount * listSize != words.length * 2) {
throw new IllegalArgumentException("Number of words"
+ " must be a multiple of the size of the individual lists!");
}
// initialize result lists (here arrays) in fitting size
List<String[]> listsToFill = new ArrayList<String[]>(listCount);
for (int index = 0; index < listCount; index++) {
listsToFill.add(new String[listSize]);
}
// be sure to randomly pick the given words by shuffling them
List<String> shuffledWords = new ArrayList<String>(Arrays.asList(words));
Collections.shuffle(shuffledWords);
List<String[]> result = new ArrayList<String[]>(listCount);
int maxWordPosition = listSize - 1;
// distribute words
for (String word : shuffledWords) {
// word is supposed to be inserted in two lists at the same index
int wordPosition = -1;
// iterate result lists
Iterator<String[]> listIterator = listsToFill.iterator();
while (listIterator.hasNext()) {
String[] list = listIterator.next();
if (wordPosition == -1) {
// look out for the first list with an empty slot
for (int index = 0; index < listSize; index++) {
if (list[index] == null) {
// found empty slot at this index
wordPosition = index;
// insert word here (first list)
list[wordPosition] = word;
if (wordPosition == maxWordPosition) {
// the list is full, no more empty slots here
listIterator.remove();
result.add(list);
}
break;
}
}
} else if (list[wordPosition] == null) {
// found second list with an empty slot at the same index
list[wordPosition] = word;
if (wordPosition == maxWordPosition) {
// the list is full, no more empty slots here
listIterator.remove();
result.add(list);
}
// we are done with this word
break;
}
}
// shuffle result lists again, to ensure randomness
Collections.shuffle(listsToFill);
}
return result;
}
This produces (for example) the following output:
1/grass
2/TV
3/plane
4/ocean
1/grass
2/dog
3/money
4/chair
1/house
2/dog
3/money
4/ocean
1/house
2/TV
3/plane
4/chair

Related

Java: Iterate inconsistent list object

I'm trying to display array list indexing from a inconstant size of array from an object. How do iterate an arraylist that have inconsistent of size within to prevent IndexOutOfBoundsException.
public static void main(String[] args) {
Hello b = new Hello();
System.out.println("test 1 =" +b.Apple().get(0));
System.out.println("test 2 =" +b.Apple().get(1));
System.out.println("test 3 =" +b.Apple().get(2));
}
Hello.java file which return result of inconsistent index list
public ArrayList<Integer> Apple(){
ArrayList<Integer> values = new ArrayList<Integer>();
rs = db.getSM().executeQuery("SELECT a, b, count(*) AS rowCount from table");
while(rs.next()) {
values.add(rs.getInt("count"));
}
return values;
Expected result
First run, it only have 2 element. so it will print
test 1 = 23
test 2 = 13
test 3 = 0
Second run, it will have 3 element. so it will print
test 1 = 23
test 2 = 10
test 3 = 3
Sample solutions if you can omit the test 3 = 0 mention when there are only two elements :
for(int index=0; index<yourList.size(); index++) {
Object element=yourList.get(index);
// do something with the element (and its index if needed)
}
for(Object element : yourList) {
//do something with the element
}
Iterator<Object> it = yourList.iterator();
while (it.hasNext()) {
Object element = it.next();
//do something with your element
}
yourList.forEach(element -> /* do something with your element */);
Apart from the first solution providing an index, all these solutions are functionally equivalent.
Don't use Object as I did for the element type, you should obviously use the type of your elements instead.
To produce your current output the first solution seems the most adequate since it provides an index :
ArrayList<Integer> yourList = b.Apple();
for (int index=0; index < yourList.size(); index++) {
System.out.printf("test %d = %d", index + 1, yourList.get(index));
}
(printf takes a string template and a list of parameters for this template ; here %d represents numbers, the first occurence is replaced by the 1-based index and the second by the list element's value)
If you don't want to omit the test 3 = 0 output, I think Federico klez Culloca's suggestion to create a generator is best, but since I'm not familiar with them I'll instead provide a solution that adds zeroes to the list until it reaches the target size :
ArrayList<Integer> yourList = b.Apple();
int desiredSize=3;
int missingZeroes = desiredSize - yourList.size();
for(int addedZeroes=0; addedZeroes < missingZeroes; addedZeroes++) {
yourList.add(0);
}
//then proceed with the above List traversal solutions.

Array of Strings into an ArrayList of Arraylist [duplicate]

This question already has answers here:
Create ArrayList from array
(42 answers)
Closed 6 years ago.
I would like to convert an Array of Strings into an ArrayList of ArrayList, where the inner ArrayList has a dynamic number of elements. Who can help ? Thanks in advance
String[] sentences = {"hello","how are you","i am fine","and you ?","thank you"}
//Output with number of elements = 2
["hello","how are you"]
["i am fine","and you ?"]
["thank you"]
//Output with number of elements = 3
["hello","how are you","i am fine"]
["and you ?","thank you"]
public static void main(String[] args) {
String[] sentences = {"hello", "how are you", "i am fine", "and you ?", "thank you"};
System.out.println(split(2,sentences));
System.out.println(split(3,sentences));
}
public static List<List<String>> split(int numberOfElements, String[] sentences) {
List<List<String>> lists = new ArrayList<List<String>>();
int index = 0;
for (String sentence : sentences) {
if (index % numberOfElements == 0) {
lists.add(new ArrayList<String>());
}
lists.get(index / numberOfElements).add(sentences[index]);
index++;
}
return lists;
}
Output:
[[hello, how are you], [i am fine, and you ?], [thank you]]
[[hello, how are you, i am fine], [and you ?, thank you]]
public static void main(String[] args) {
String[] sentences = { "hello", "how are you", "i am fine", "and you ?", "thank you" };
List<List<String>> convertIntoList = convertIntoList(sentences, 2);
System.out.println(convertIntoList);
convertIntoList = convertIntoList(sentences, 3);
System.out.println(convertIntoList);
}
private static List<List<String>> convertIntoList(String[] sentences, int nbElement) {
List<List<String>> listOfListTarget = new ArrayList<List<String>>();
int currentIndex = 0;
while (currentIndex < sentences.length) {
int nextIndex = currentIndex + nbElement;
if (nextIndex > sentences.length) {
nextIndex = sentences.length;
}
final String[] copyOfRange = Arrays.copyOfRange(sentences, currentIndex, nextIndex);
List<String> subList = new ArrayList<String>();
subList.addAll(Arrays.asList(copyOfRange));
listOfListTarget.add(subList);
currentIndex+=nbElement;
}
return listOfListTarget;
}
Is this is a homework?
So you have an array of strings, and you want to create a List> with that, with each inner List containing at most x number of elements.
To get x number of elements and put them in a List, you can do a simple for loop.
String[] myStringArray = { ... };
List<String> myListOfString = new ArrayList<>();
for(int i=0; i<x; i++) {
myListOfString.add(myStringArray[i]);
}
So for example if you have these values
String[] myStringArray = {"a", "b", "c", "d", "e"};
x = 2;
You'll get the following list using the above loop:
["a", "b"]
Great! But we need to get all the contents of the myStringArray! How do we do that? Then let's do the first step, we iterate through all the contents of the array. We can do that like this.
int i=0;
while(i < myStringArray.length) {
System.out.println(myStringArray[i]);
i++;
}
Which will output:
a
b
c
d
e
This doesn't solve the problem... but at least we know how to iterate the whole thing. The next step is to get x of them. Sounds simple right? So basically we need to create a list of x from the contents. Maybe we can use the logic we created a few examples back to solve the problem.
// Create list of list of string here
int i = 0;
while(i < myStringArray.length) {
// Create list of string here
for(int j=0; j<x; j++) {
// Add myStringArray[j] to list of string here
}
// Add the list of string to the list of list of string here
i++;
}
Easy right? No. This gives the following lists:
["a", "b"]
["a", "b"]
["a", "b"]
["a", "b"]
["a", "b"]
Why? In the first loop, we are iterating up to how many is in the array. In the second loop, we are adding element 0 and 1 to a list. Obviously it wouldn't work. The second loop needs to be aware that it should not add previously added elements, and at the same time the first loop needs to be aware of what the second loop is doing. So you might think, maybe we can use the int i to indicate where the second loop should start?
int i = 0;
while(i<myStringArray.length) {
while(i<x) {
// add myStringArray[i];
i++;
}
i++;
}
Unfortunately, using the same values as previous, this will only give the following list
["a", "b"]
Because i is iterating through the whole array. So when it goes from 0 to length, whatever the value of i is used on the second array. When it loops again, i becomes 1, so the start of the second loop is at 1.
We need a separate variable to do the counting, while still keeping in mind where we currently are in the second loop.
int i = 0;
while(i<myStringArray.length) {
int count = 0;
while(count < x) {
// Add myStringArray[count+i] to list of string
count++;
}
// Add to list of list of string
i += count + 1; // Need to be aware of how much we have processed
}
This will do what we want, but unfortunately we can get in trouble at certain values. Say x is 10 and myStringArray is only of length 2. This will throw an exception because when it reaches the point of count+i = 3, that index doesn't exist anymore. The second loop also needs to be aware of how much is still remaining.
Finally we'll have the following code
int i = 0;
while(i<myStringArray.length) {
int count = 0;
while(count < x && count+i < myStringArray.length) {
// Add myStringArray[count+i] to list of string
}
// Add to list of list of string
i += count; // Need to be aware of how much we have processed
}
Which will give
["a", "b"]
["c", "d"]
["e"]
Edit: Next time try to put some code that you tried something.

Split an Arraylist into multiple variable length Arraylists

I have two ArrayLists. The first list contains some x number of elements these elements are again ArrayLists. The second list contains only integer values.
Second list size is always less than first list size Example of first list is: [[TC1,TC1_1],[,TC1_2],[TC2,TC2_1],[TC3,TC3_1][,TC3_2],[TC4,TC4_1][,TC4_2][,TC4_3],[TC5,TC5_1],[TC6,TC6_1]]
Example of second list is [0,2,3,5,8,9].This second Araylist elements points to 1st arraylist where the 1st element of individual ArrayList elements of first arraylist is not empty
Now the requirement is 1st list should be split into 6 lists where 6 is 2nd list size. Output should be as below.
Of the 6 new lists 1st list would contain elements of main list from 0th to 1st index. The 2nd list would contain elements of main list from 3rd index. The 3rd list would contain elements of main list from 4th to 5th index and so on..finally output will be as below
`[[[TC1,TC1_1],[,TC1_2]]
[[TC2,TC2_1]]
[[TC3,TC3_1][,TC3_2]]
[[TC4,TC4_1][,TC4_2][,TC4_3]]
[[TC5,TC5_1]]
[[TC6,TC6_1]]]
private ArrayList getTCsIncludingSubTcs(ArrayList TCIndexes,ArrayList alTCs) {
//List tempSubList=new ArrayList();
ArrayList finalTCS=new ArrayList();
for(int j=0;j<TCIndexes.size();j++){
int TCIndex=(int)TCIndexes.get(j);
if(j==0 && TCIndexes.size()==1){
//List tempSubList=new ArrayList(alTCs.subList(TCIndex,(int)alTCs.size()));
List tempSubList=getSubArrayList(TCIndex,(int)alTCs.size(),alTCs);
finalTCS.add(tempSubList);
break;
}
int nextTCIndex=j+1;
System.out.println(nextTCIndex);
if(j==TCIndexes.size()-1){
List tempSubList=getSubArrayList(TCIndex,(int)alTCs.size(),alTCs);
finalTCS.add(tempSubList);
break;
}
List tempSubList=getSubArrayList(TCIndex,(int)alTCs.size(),alTCs);
finalTCS.add(tempSubList);
System.out.println("finalTCS :"+finalTCS);
}
System.out.println("fc size"+finalTCS.size());
return finalTCS;
}
Try this code.
public class Test {
private List<List<String>> getTcsIncludingSubTcs(ArrayList<Integer> tcIndexes,ArrayList<String> alTcs) {
List<List<String>> finalTcs=new ArrayList<>();
List<String> temp = new ArrayList<>();
int size = tcIndexes.size();
int i= alTcs.size();
int k = 0;
for(int j=0; j<alTcs.size(); j++){
if(( j != 0 && j % size == 0 && i >= size))
{
temp = new ArrayList<>();
k++;
}
i--;
temp.add(alTcs.get(j));
if(finalTcs.contains(temp))
finalTcs.remove(k);
finalTcs.add(k, temp);
}
return finalTcs;
}
public static void main (String arg[])
{
ArrayList<String> data1 = new ArrayList<>();
data1.add("TC1");
data1.add("TC2");
data1.add("TC3");
data1.add("TC4");
data1.add("TC5");
data1.add("TC6");
data1.add("TC7");
data1.add("TC8");
data1.add("TC9");
data1.add("TC10");
ArrayList<Integer> data2 = new ArrayList<>();
data2.add(0);
data2.add(3);
data2.add(6);
Test t = new Test();
List<List<String>> list = t.getTcsIncludingSubTcs(data2, data1);
for(List<String> l : list)
System.out.println(l);
}
}
Output:
[TC1, TC2, TC3]
[TC4, TC5, TC6]
[TC7, TC8, TC9, TC10]
One more solution is ,
we have source list and start index list.Using these two lists generate end index list.Now use start index list and end index list to generate the required final output

Creating permutations by selecting from arrays

I have a 2D array that stores different letters that correspond to what you would see on a phone keypad.
char [][] convert =
{ {},
{'A','B','C'},
{'D','E','F'},
{'G','H','I'},
{'J','K','L'},
{'M','N','O'},
{'P','R','S'},
{'T','U','V'},
{'W','X','Y'}
};
If I want to find all the possible permutations of a 5 letter word that takes 1 letter each from the first 5 rows of the 2D array, how would I do that? I am thinking about recursion but it's just confusing me.
To make this problem easier to understand, here's an example:
A 3 letter word takes its first letter from row 1, {'A','B','C'}, its second letter from row 3, {'G','H','I'}, and its third letter from row 6, {'P','R','S'}. There would be in total 27 possible outcomes: AGP AGR AGS AHP AHR AHS AIP AIR AIS BGP BGR BGS BHP BHR BHS BIP BIR BIS CGP CGR CGS CHP CHR CHS CIP CIR CIS.
The first thing to observe is that if you are making words by selecting one of 3 characters from each of 5 rows, you will end with 35 = 243 words in total. Regardless of how you implement the program, it must end up building each of those 243 words.
Recursion is a good implementation strategy because it makes it clear that you're selecting one of the three characters in the first row, and for each of those choices you go on to select one of the three characters in the second row, and so on.
In the Java program below, the first version of makeWord is a recursive function that selects a character in the row indexed by currentRowIndex and appends that character to wordBuffer. If this is the last row, the word is complete and it gets appended to a list of words. Otherwise, the function calls itself to work on row currentRowIndex + 1.
Notice that the current state of wordBuffer carries through to the recursive call. Only after returning from the recursive call do we delete the last character from wordBuffer.
The second version of makeWord lets you pass an array of row indices that specify which rows you want to select characters from. For example, to select characters from rows 1, 3, and 6, you would call:
permuter.makeWord(new int[]{ 1, 3, 6 }, 0);
You can substitute that call in the main method instead of the current line, which causes a word to be built with characters from rows 1 through 5:
permuter.makeWord(1, 5);
If you take a close look at the makeWord methods, you'll see that the first one doesn't recurse when the string is complete, while the second one recurses once and then returns early because position == indices.length. The latter approach is slightly less efficient because it costs one more recursive call, but you may find that it expresses the concept of recursion more clearly. It's a matter of taste.
import java.util.*;
public class PermuteCharacters {
char[][] rows = {
{},
{'A','B','C'},
{'D','E','F'},
{'G','H','I'},
{'J','K','L'},
{'M','N','O'},
{'P','R','S'},
{'T','U','V'},
{'W','X','Y'}
};
StringBuffer wordBuffer = new StringBuffer();
ArrayList<String> words = new ArrayList<String>();
void makeWord(int currentRowIndex, int endRowIndex) {
char[] row = rows[currentRowIndex];
for (int i = 0; i < row.length; ++i) {
wordBuffer.append(row[i]);
if (currentRowIndex == endRowIndex) {
words.add(wordBuffer.toString());
} else {
makeWord(currentRowIndex + 1, endRowIndex);
}
wordBuffer.deleteCharAt(wordBuffer.length() - 1);
}
}
void makeWord(int[] indices, int position) {
if (position == indices.length) {
words.add(wordBuffer.toString());
return;
}
char[] row = rows[indices[position]];
for (int i = 0; i < row.length; ++i) {
wordBuffer.append(row[i]);
makeWord(indices, position + 1);
wordBuffer.deleteCharAt(wordBuffer.length() - 1);
}
}
void displayWords() {
if (words.size() != 0) {
System.out.print(words.get(0));
for (int i = 1; i < words.size(); ++i) {
System.out.print(" " + words.get(i));
}
System.out.println();
}
System.out.println(words.size() + " words");
}
public static void main(String[] args) {
PermuteCharacters permuter = new PermuteCharacters();
permuter.makeWord(1, 5);
permuter.displayWords();
}
}
Try this, if you can use Java8
static Stream<String> stream(char[] chars) {
return new String(chars).chars().mapToObj(c -> Character.toString((char)c));
}
public static void main(String[] args) {
char [][] convert =
{ {},
{'A','B','C'},
{'D','E','F'},
{'G','H','I'},
{'J','K','L'},
{'M','N','O'},
{'P','R','S'},
{'T','U','V'},
{'W','X','Y'}
};
stream(convert[1])
.flatMap(s -> stream(convert[2]).map(t -> s + t))
.flatMap(s -> stream(convert[3]).map(t -> s + t))
.flatMap(s -> stream(convert[4]).map(t -> s + t))
.flatMap(s -> stream(convert[5]).map(t -> s + t))
.forEach(x -> System.out.println(x));
}
You can also write recursive version.
static Stream<String> permutation(char[][] convert, int row) {
return row == 1
? stream(convert[1])
: permutation(convert, row - 1)
.flatMap(s -> stream(convert[row]).map(t -> s + t));
}
And call this.
permutation(convert, 5)
.forEach(x -> System.out.println(x));
This can be solved using dynamic programming approach.
Take the first two rows and combine all the strings in the arrays. That will give you a resultant array of size m*n. Where m is the size of the first array and n is the size of the second array. In your case it is 9. Then assign the resultant array to the first array and assign the third array to the second array. Repeat it till the fifth array. That will give you all possible strings from the first five arrays.
public static String[] getAllCombinations(String array[][], int l) {
String a[] = array[0];
String temp[]=null;
for(int i=1;i<l;i++) {
int z=0;
String b[] = array[i];
temp = new String[a.length*b.length];
for(String x:a) {
for(String y:b) {
temp[z] = ""+x+y;
z++;
}
}
a = temp;
}
System.out.println(temp.length);
return temp;
}
This function should do it.
Here is one possible solution.
You first define the sequence of keys to be pressed. For example, if you want to take one letter each from the first five rows of the array, the sequence would be (1, 2, 3, 4, 5) (since the first row is empty). If you want to spell "stack", the sequence would be (6, 7, 1, 1, 4).
Then you loop through the sequence. In each step, you get the array of chars that correspond to this position of the sequence. Then you generate all the words that result from all the combinations so far, which are all the words from the previous step combined with all the chars of the current step.
Finally, the result of the last step is the final result that contains all the possible words.
char [][] convert = {
{}, // 0
{'A','B','C'}, // 1
{'D','E','F'}, // 2
{'G','H','I'}, // 3
{'J','K','L'}, // 4
{'M','N','O'}, // 5
{'P','R','S'}, // 6
{'T','U','V'}, // 7
{'W','X','Y'} // 8
};
// Sequence of keys to be pressed. In this case the pressed keys are
// [ABC], [DEF], [GHI]
int[] sequence = new int[] {1, 2, 3};
// List for storing the results of each level.
List<List<String>> results = new ArrayList<>();
for(int i=0; i<sequence.length; i++){
// Results of this level
List<String> words = new ArrayList<>();
results.add(words);
List<String> prevLevelWords;
if(i==0){
prevLevelWords = Collections.singletonList("");
} else {
prevLevelWords = results.get(i-1);
}
char[] thisLevelChars = convert[sequence[i]];
if(thisLevelChars.length == 0){
words.addAll(prevLevelWords);
} else {
for(String word : prevLevelWords){
for(char ch : convert[sequence[i]]){
words.add(word + ch);
}
}
}
}
List<String> finalResult = results.get(sequence.length-1);
for(String word : finalResult) {
System.out.println(word);
}
Run it
Here's an alternate solution using Java 8 streams for your interest.
public class Combiner {
private List<String> combos = new ArrayList<>();
public Stream<String> stream() {
return combos.stream();
}
public void accept(char[] values) {
if (combos.isEmpty()) {
for (char value : values) {
combos.add(String.valueOf(value));
}
} else {
Combiner other = new Combiner();
other.accept(values);
combine(other);
}
}
public Combiner combine(Combiner other) {
combos = stream()
.flatMap(v1 -> other.stream().map(v2 -> v1 + v2))
.collect(Collectors.toList());
return this;
}
}
Essentially this is a collector that takes each element in the stream and adds a new combination for every concatenation of the items in the element and the existing combinations.
And here's some sample code showing how to use it:
public static void main(String[] args) {
char[][] vals = {{'a', 'b'}, {'c'}, {'d', 'e'}, {'f', 'g', 'h'}};
Arrays.stream(vals).parallel()
.collect(Combiner::new, Combiner::accept, Combiner::combine)
.stream().forEach(System.out::println);
}
The parallel isn't strictly necessary: it's just to show that for massive numbers of combinations the stream can be split across processors and then combined.
The code is a lot simpler for other types of data that can be naturally streamed. Unfortunately there's no Arrays.stream(char[]) so the traditional iteration makes the code a bit clearer. You can use something ugly like converting to string then an IntStream and then to Stream<Character> but frankly that's a lot of work to avoid iterating over the array :-)

Find longest strings

I have a large string like "wall hall to wall hall fall be", and I want to print longest strings. Then i want to know how many times all longest strings Is repeated?
For exampele,longest strings are:
wall Is repeated 2
hall Is repeated 2
fall Is repeated 1
This is my code:
public void bigesttstring(String str){
String[] wordsArray=str.split(" ");
int n= str.trim().split("\\s+").length;
int maxsize=0;
String maxWord="";
for(int i=0;i<wordsArray.length;i++){
if(wordsArray[i].length()>maxsize){
maxWord=wordsArray[i];
maxsize=wordsArray[i].length();
}
}
System.out.println("Max sized word is "+maxWord+" with size "+maxsize);
}
But this code only prints "wall".
for count repeated String(i mean "maxWord"),this code write:
int count=0;
for(int i=0;i<wordsArray.length;i++){
if(maxWord.equals(wordsArray[i])){
count++;
}
}
and for display other longest strings i have this code:
int k=0;
for(int i=0;i<wordsArray.length;i++){
if(maxWord.equals(wordsArray[i])){
continue;
}
if(maxsize==wordsArray[i].length()){
k++;
}
}
String[] other=new String[k];
int o=0;
for(int i=0;i<wordsArray.length;i++){
if(maxWord.equals(wordsArray[i])){
continue;
}
if(maxsize==wordsArray[i].length()){
other[o]=wordsArray[i];
o++;
}
}
I allowed to use this functions:
char char At(int i);
int ComoareTo(String another string);
boolean endsWith(String suffix);
int indexof();
int indexof(String str);
String substring();
char[] toCharArray();
String lowercase();
And want another code like this for shortest strings.
You have written
if(wordsArray[i].length()>maxsize)
For wall, hall and fall, it is only true for first wall. That's why you are getting wall and size 4.
Here you are not considering that the longest string length may be same for different string. You will have to store the longest string in an array and if condition should be
if(wordsArray[i].length()>=maxsize)
you will consider = and > case seperately. Since in the case of > you will have to delete all the string in array.
You need to change it to equal because currently if the words is the same length as the current largest word it will ignore it. Also if you want it to have the biggest words. You need to store them in an array. I implemented it here.
package OtherPeoplesCode;
public class string {
public static void main(String[] args) {
bigeststring("wall hall to wall hall fall be");
}
public static void bigeststring(String str){
String[] wordsArray=str.split(" ");
String[] biggestWordsArray = new String[wordsArray.length];
int x = 0;
int n= str.trim().split("\\s+").length;
int maxsize=0;
String maxWord="";
for(int i=0;i<wordsArray.length;i++){
if(wordsArray[i].length()>maxsize){
maxWord=wordsArray[i];
maxsize=wordsArray[i].length();
for(int y = 0; y <= biggestWordsArray.length -1; y++){
biggestWordsArray[y] = "";
}
}
else if(maxsize==wordsArray[i].length()){
biggestWordsArray[x] = wordsArray[i];
x++;
}
}
if(biggestWordsArray[0].equals("")){
System.out.println("Max sized word is "+maxWord+" with size "+maxsize);
}
else if(!(biggestWordsArray[0].equals(""))){
System.out.println("TIE!");
for(int y = 0; y <= biggestWordsArray.length -1; y++){
if(!(biggestWordsArray[y].equals(""))){
System.out.print("Word #" + y + " is ");
System.out.println(biggestWordsArray[y]);
}
}
}
}
}
EDIT: This is the working code, sorry about the delay.
Using Map is possibly the most straight-forward and easy way to do. However if you said your teacher don't allow you to use that, may you tell us what is allowed? So that we don't end up wasting time suggesting different methods and end up none of them is acceptable because your teacher doesn't allow.
One most brute force way that I can suggest you to try is (lots of place for optimization, but I think you may want the easiest way):
loop through the list of words, and find out the length of the longest word and number of words with such length
Create a new array with "number of word" you found in 1. Loop through the original word list again, for each word with length == maxWordLength, put that in the new array IF it is not already existed in it (a simple check by a loop.
Now you have a list that contains all DISTINCT words that are "longest", with some possible null at the end. In order to display them in a format like "word : numOfOccurence", you can do something like
loop through result array until you hit null. For each word in the result array, have a loop in the original word list to count its occurence. Then you can print out the message as you want
in psuedo code:
String[] wordList = ....;
int maxLen = 0;
int maxLenOccurence = 0;
foreach word in wordList {
if word is longer then maxLen {
maxLen = word's length
maxLenOccurence = 1;
}
else if word's length is equals to maxLen {
maxLenOccurence ++
}
}
// 2,3
String[] maxLenWordList = new String[maxLenOccurence];
foreach word in wordList {
else if word's length is equals to maxLen {
for i = 0 to maxLenWordList length {
if (maxLenWordList[i] == word)
break
if (maxLenWordList[i] == null
maxLenWordList[i] = word
}
}
//4
foreach maxLenWord in maxLenWordList {
count = 0
foreach word in wordList {
if maxLenWord == word
count ++
}
display "Max sized word is "+ maxLenWord + " with size " + count
}
Another way doesn't involve other data structure is:
Have the word list
Sort the word list first by length then by the literal value
First element of the result list is the longest one, and string with same value become adjacent. You can do a loop print out all matching and its count (do some thinking by yourself here. Shouldn't be that hard)
Also you can use this;
String[] allLongestStrings(String[] inputArray) {
List<String> list = new ArrayList<String>();
int max = 0;
for (int i = 0; i < inputArray.length; i++) {
StringBuilder s = new StringBuilder(inputArray[i]);
int n = s.length();
if (n > max) {
max = n;
}
}
for (int i = 0; i < inputArray.length; i++) {
StringBuilder s = new StringBuilder(inputArray[i]);
int n = s.length();
if (n == max) {
list.add(s.toString());
}
}
return list.toArray(new String[list.size()]);
}

Categories

Resources