Swapping string position in Arraylist java - java

I have a sentence: Humpty Dumpty sat on a wall.
I want the strings to swap positions such that : Dumpty Humpty on sat wall a.
So the code that I wrote is following :
import java.util.*;
public class Swap{
public static void main(String []args) {
ArrayList<String> sentence = new ArrayList<String>();
sentence.add("Humpty");
sentence.add("Dumpty");
sentence.add("sat");
sentence.add("on");
sentence.add("a");
sentence.add("wall");
int size = sentence.size() ; // for finding size of array list
int numb ;
if(size%2 == 0) {
numb = 1;
}
else {
numb = 0;
}
ArrayList<String> newSentence = new ArrayList<String>();
if(numb == 1) {
for(int i = 0; i <= size ; i = i+2) {
String item = sentence.get(i);
newSentence.add(i+1, item);
}
for(int i = 1; i<=size ; i = i+2) {
String item2 = sentence.get(i);
newSentence.add(i-1, item2);
}
System.out.println(newSentence);
}
else {
System.out.println(sentence);
}
}
}
The code is compiling correct but when I run it, its giving an error.
What i understand of this is that I am adding strings to the array list leaving positions in between. Like adding at position 3 without filling position 2 first. How do I overcome this problem ?

You're correct about your problem - you're trying to insert an element into index 1 before inserting an element at all (at index 0), and you get an IndexOutOfBoundsException.
If you want to use your existing code to achieve this task, simply have just one loop as such:
if(numb == 1) {
for(int i = 0; i < size-1 ; i = i+2) {
String item = sentence.get(i+1);
newSentence.add(i, item);
item = sentence.get(i);
newSentence.add(i+1, item);
}
}
If you want to be a bit more sophisticated a use Java's built-in functions, you can use swap:
for(int i = 0; i < size-1 ; i = i+2) {
Collections.swap(sentence, i, i+1);
}
System.out.println(sentence);

You can initilize newSentence using:
ArrayList<String> newSentence = new ArrayList<String>(Collections.nCopies(size, ""));
This will let you access/skip any position in between 0 and size. So you can keep your rest of the code as it is.
just remember all index are being populated with empty String here.

That is because:
for(int i = 0; i <= size ; i = i+2) {
String item = sentence.get(i);
newSentence.add(i+1, item);//Here you will face java.lang.IndexOutOfBoundsException
}
for(int i = 1; i<=size ; i = i+2) {
String item2 = sentence.get(i);
newSentence.add(i-1, item2);//Here you will face java.lang.IndexOutOfBoundsException
}
instead of this, try following code:
if(numb == 1) {
for(int i = 0; i < size-1 ; i +=2) {
Collections.swap(sentence, i, i+1);
}
}

Related

Java Insertion Sorting with ArrayLists of Strings

I have an assignment on sorting which requires me to sort a list of random words by putting letters that start with the same letter in a group/zones and sorting that group alphabetically. My code sorts the words but my problem is that some of the words have changed. For example instead of having an output as
angela
APPLE
Apple
apple
Baboon
Ball
Cat
cat
PINK
Pink
Steve
I would have an output of :
apple
apple
apple
apple
Ball
Ball
cat
cat
Pink
PINK
Steve
As you can see, some of the words have been changed and in some cases, words with a capital letter are turned into lower cases like "cat" and I can't seem to find where my mistake is.
This is my sorting code; my driver class just takes in the list of random words :
import java.util.ArrayList;
import java.util.Collections;
public class ZoneSort
{
ArrayList[] arrayOfZones;
ArrayList<String> words;
public ZoneSort(ArrayList<String> words)
{
arrayOfZones = new ArrayList [ 26 ];
for(int index = 0; index < 26;index++)
arrayOfZones [ index ] = new ArrayList();
this.words = words;
putWordsIntoZones();
}
private void putWordsIntoZones()
{
for(String word: words)
{
int index = Character.toLowerCase(word.charAt(0)) - 97;
ArrayList<String> zoneAtIndex = arrayOfZones[index];
zoneAtIndex.add(word);
}
}
public void sortTheArrayOfZones()
{
for(ArrayList<String> zone : arrayOfZones )
{
sortZone(zone);
}
}
private void sortZone(ArrayList<String> zone)
{
for(int i = 1; i < zone.size(); i++)
{
String key = zone.get(i);
int j = i-1;
while(j>=0 && key.compareTo(zone.get(j)) > 0)
{
String x = zone.get(j+1);
zone.set(j, x);
j--;
}
String x = zone.get(j+1);
x = key;
}
}
public void printArrayOfZones()
{
System.out.println("The sorted words are");
for(ArrayList<String> zone:arrayOfZones)
{
for(String word: zone)
{
System.out.println(word);
}
}
}
Reading your code and viewing your results, it seems that your code overwrites the values instead of swapping them. To fix this you need to take a look at the function sort.
I have modified your code so that instead of overwriting, you swap the two elements :
private void sortZone(ArrayList<String> zone){
for(int i = 1; i < zone.size(); i++){
String key = zone.get(i);
int j = i-1;
while(j>=0 && key.compareTo(zone.get(j)) > 0){
String x = zone.get(j+1);
zone.set(j+1,zone.get(j)); // line added
zone.set(j, x);
j--;
}
String x = zone.get(j+1);
x = key;
}
}
I hope this fixed your problem.
If I compare your sortZone implementation with a reference insertion sort implementation such as https://www.baeldung.com/java-insertion-sort
I see the following differences - see inline comments
for(int i = 1; i < zone.size(); i++)
{
String key = zone.get(i);
int j = i-1;
// The sort order is reversed.
// You've used "key > zone[j]" when it should be "key < zone[j]"
while(j>=0 && key.compareTo(zone.get(j)) < 0)
{
// This is copying items backwards, towards the beginning of the array.
// String x = zone.get(j+1);
// zone.set(j, x);
// It should be copying items forwards, towards the end, to make room for "key"
// Like this:
String x = zone.get(j);
zone.set(j+1, x);
j--;
}
// You should be setting zone[j+1] = "key" - this does not do it:
// String x = zone.get(j+1);
// x = key;
// This is how you set a value in a list:
zone.set(j+1, key);
}

Loop through multiple arraylists and get elements

public static void main(String[] args)
{
loadDependencies ld = new loadDependencies();
List<String> ls = ld.loadDependenciesFromPom();
getAvailableHigherVersions ah = new getAvailableHigherVersions();
List<List<String>> vl = ah.versionListOnly();
String previousVersion=null;
for ( int a=0; a<vl.size();a++) {
List<String> tmp = vl.get(a);
for(int i=0; i<ls.size();i++){
String firstE = ls.get(i);
for(int j=0;j<tmp.size();j++) {
if (i==0 && j==0){
//xu.versionUpdate(previousVersion, tmp.get(j));
//String previousVersiontt = ls.get(i);
System.out.println(firstE + "----" + tmp.get(j));
}
/*xu.versionUpdate(previousVersion, tmp.get(j));
previousVersion=tmp.get(j);*/
//System.out.println(previousVersion+"-"+tmp.get(j));
// previousVersion = tmp.get(j);
}
}
}
}
"ls" is a String list. It contains like this
[1,4,5,7]
"vl"is a List of string list. It contains like this
[[1.5,1.6,1.7],[4.1,4.2,4.3],[5.1,5.2],[7.1,7.4]]
what I need to do is first take the 1st element of ls list
1
then i need to get the first element in the vl list
[1.5,1.6,1.7]
then output should be
[1,1.5]
then the next output would be
[1.5,1.6]
likewise iterate through the array.
Then next take the 2nd element of ls
4
then it should go like 4,4.1 then 4.1,4.2 likewise until the ls is empty.
I tried above code but some times it iterate multiple times. Any hint to fix this issue?
So if I understood well, you want something like this:
for (int a = 0; a < ls.size(); a++)
{
// Get first element
String firstE = ls.get(a);
// Get corresponding vl elements
List<String> vls = vl.get(a);
// Now print the elements
// The first element of vl should be preceeded by the corresponding element in ls
// The others by the predecessor in the same array
for (int b = 0; b < vls.size(); b++)
{
System.out.print("[");
if (b == 0)
System.out.print(firstE);
else
System.out.print(vls.get(b - 1));
System.out.println(", " + vls.get(b) + "]");
}
}
for(int i=0;i<ls.size();i++){
List<String> tmp = vl.get(i);
System.out.println(ls.get(i)+" "+temp.get(0));
for(int j=1;j<tem.size()-1;j++){
System.out.println(temp.get(j)+" "+temp.get(j+1));
}
}
for ( int a=0; a<vl.size();a++) {
List<String> tmp = vl.get(a);
String firstE = ls.get(a);
for (int j = 0; j < tmp.size(); j++) {
if (j == 0) {
//xu.versionUpdate(previousVersion, tmp.get(j));
//String previousVersiontt = ls.get(i);
System.out.println(firstE + "----" + tmp.get(j));
}
/*xu.versionUpdate(previousVersion, tmp.get(j));
previousVersion=tmp.get(j);*/
//System.out.println(previousVersion+"-"+tmp.get(j));
// previousVersion = tmp.get(j);
}
}
}

Keeping the Value of an Array Outside the method

I am trying to keep the values of my array dates from the Unsorted method, so that it can be used to have another return value in a separate method, that being the Sorted method. I know there would be no trouble in this, but when running the program (which is done using a GUI) the array outside of the Unsorted method is only 1 item long, effectively losing all but one of its items.
I have reason to believe that this is because of the line
while((line = myFile.readLine()) != null){ ...
Because when i try to output the items of the array outside of the while loop in the Sorted function, it also returns only the last item of the array. There is no reason to use split.string here, as I know the Tokenizer will get the job done easily, and the project calls for using the Tokenizer. I would imagine that I could change the way the tokens are added to the array, but I have tried the add function, and it did not work, and when doing so I get "The Method add(String) is undefined for type string"
Here is the example text file(dates.txt):
20161001
20080912,20131120,19980927
20020202,hello
20120104
These dates are structured "yearmonthday" all with a length of 8. the hello is added to ensure that we check for the appropriate items in the text file.
Here is the code:
import java.util.StringTokenizer;
public class Project1{
public static TextFileInput myFile;
public static StringTokenizer myTokens;
public static String[] dates;
public static String line;
public String Unsorted(String date) {
myFile = new TextFileInput("dates.txt");
while((line = myFile.readLine()) != null){
myTokens = new StringTokenizer(line,",");
dates = new String[myTokens.countTokens()];
int i=0;
while (myTokens.hasMoreTokens()) {
dates[i]=myTokens.nextToken();
i++;
}
// prints any items that are not 8 chars long
for (int j = 0; j < dates.length; j++){
if (dates[j].length() < 8){
System.out.println(dates[j]);
}
}
// I changed the date += String.valueof.dates[i] + "/n"
// to System.out.println
for (int n = 0; n < dates.length; n++){
if (dates[n].length() == 8){
System.out.println(dates[n]);
}
}
}
return date;
}
// I changed the datesort += String.valueof.dates[i] + "/n"
// to System.out.println
public String Sorted(String datesort){
selectionSort(dates, dates.length);
for (int i = 0; i < dates.length; i++){
if (dates[i].length() == 8){
System.out.println(dates[i]);
}
}
return datesort;
}
private static void selectionSort(String array[], int length) {
for ( int i = 0; i < length - 1; i++ ) {
int indexLowest = i;
for ( int j = i + 1; j < length; j++ )
if ( array[j].compareTo(array[indexLowest]) < 0)
indexLowest = j;
if ( array[indexLowest] != array[i] ) {
String temp = array[indexLowest];
array[indexLowest] = array[i];
array[i] = temp;
}
}
}
}
The out of this program is :
hello
20161001
20080912
20131120
19980927
20020202
20120104
20120104
Yet it should be:
hello
20161001
20080912
20131120
19980927
20020202
20120104
19980927
20020202
20080912
20120104
20131120
20161001
thanks ahead of time, I apologize if I was unclear at all.

Looping through two separate if statements

The code below is a simplified version of a method I am working on for a java project. The method will sort through a list of items(two different categories), in this case 0,s and 1's. The code reads through an array of numbers stops at either 0 or 1 and then prints out both the 0 or one and the string of numbers following the 0 or 1. If a preceding string is a 1 or a zero then it will stop and switch to another if statement. However it only executes each statement once. However there is more in the array that it needs to read through and organize. I would like to set up some sort of loop so that it loops through the set of if statements until it has read through the entire array.
public class tester
{
public static void main(String[] args )
{
String flags[] = {"0","23","25","34","1","9","12","13","0","67","2","43"};
String array[] = new String[flags.length];
String zeros [] = new String[array.length];
String ones[] = new String[array.length];
int i,j,k,h;
int count = 0;
for (i = 0; i<flags.length; i++)
{
if (flags[i].equals("0"))
{
for (j=0; !flags[j].equals("1") ; j++)
{
count = j+1;
array[j] = flags[j];
zeros[j] = flags[j];
}
} else
if (flags[count].equals("1"))
{
j = 0;
for(k=count; !flags[k].equals("0");k++)
{
array[k] = flags[k];
j++;
ones[j-1] = flags[k];
}
}
}
for(i=0; i<zeros.length; i++)
{System.out.println(zeros[i]);}
System.out.println();
for(i=0; i<ones.length; i++)
{System.out.println(ones[i]);}
}
}
What it prints out now:
0
23
25
34
null
null
null
null
null
null
null
null
1
9
12
13
null
null
null
null
null
null
null
null
String flags[] = {"9","0","23","25","34","1","9","12","13","0","67","2","43"};
String array[] = new String[flags.length];
String zeros [] = new String[array.length];
String ones[] = new String[array.length];
int i;
boolean addingZeroes = false;
boolean addingOnes = false;
int zeroCount = 0;
int onesCount = 0;
for (i = 0; i<flags.length; i++) {
if (flags[i].equals("0")) {
zeros[zeroCount] = flags[i];
zeroCount++;
addingZeroes = true;
addingOnes = false;
} else if (flags[i].equals("1")) {
ones[onesCount] = flags[i];
onesCount++;
addingZeroes = false;
addingOnes = true;
} else if (addingZeroes) {
zeros[zeroCount] = flags[i];
zeroCount++;
} else if (addingOnes) {
ones[onesCount] = flags[i];
onesCount++;
}
}
for(i=0; i<zeroCount; i++) {
System.out.println(zeros[i]);
}
System.out.println();
for(i=0; i<onesCount; i++) {
System.out.println(ones[i]);
}
Hey, couple things were wrong. Basically, you need a little state machine where you need to know whether you are in the midst of storing the sequence after a 1 or a 0. I used the boolean values (eg addingZeroes) for that.
Then, you need to separately keep track of your element count (eg zeroCount) for each of the storage arrays. You might have 20 digits after a 0 and just 2 after a 1.
Finally, at the end, your length of your storage arrays is not what you want - you want the amount of values you ended up storing. That's why you got all those "nulls".
One other thing I noticed is that your j value is initialized always to 0 in the 0 block, so you would always be using the lowest values of the start array.

sub arraylist's size isn't correct

After hard searchig I still haven't found the proper answer for my question and there is it:
I have to write a java program that enters an array of strings and finds in it the largest sequence of equal elements. If several sequences have the same longest length, the program should print the leftmost of them. The input strings are given as a single line, separated by a space.
For example:
if the input is: "hi yes yes yes bye",
the output should be: "yes yes yes".
And there is my source code:
public static void main(String[] args) {
System.out.println("Please enter a sequence of strings separated by spaces:");
Scanner inputStringScanner = new Scanner(System.in);
String[] strings = inputStringScanner.nextLine().split(" ");
System.out.println(String.join(" ", strings));
ArrayList<ArrayList<String>> stringsSequencesCollection = new ArrayList<ArrayList<String>>();
ArrayList<String> stringsSequences = new ArrayList<String>();
stringsSequences.add(strings[0]);
for (int i = 1; i < strings.length; i++) {
if(strings[i].equals(strings[i - 1])) {
stringsSequences.add(strings[i]);
} else {
System.out.println(stringsSequences + " " + stringsSequences.size());
stringsSequencesCollection.add(stringsSequences);
stringsSequences.clear();
stringsSequences.add(strings[i]);
//ystem.out.println("\n" + stringsSequences);
}
if(i == strings.length - 1) {
stringsSequencesCollection.add(stringsSequences);
stringsSequences.clear();
System.out.println(stringsSequences + " " + stringsSequences.size());
}
}
System.out.println(stringsSequencesCollection.size());
System.out.println(stringsSequencesCollection.get(2).size());
System.out.println();
int maximalStringSequence = Integer.MIN_VALUE;
int index = 0;
ArrayList<String> currentStringSequence = new ArrayList<String>();
for (int i = 0; i < stringsSequencesCollection.size(); i++) {
currentStringSequence = stringsSequencesCollection.get(i);
System.out.println(stringsSequencesCollection.get(i).size());
if (stringsSequencesCollection.get(i).size() > maximalStringSequence) {
maximalStringSequence = stringsSequencesCollection.get(i).size();
index = i;
//System.out.println("\n" + index);
}
}
System.out.println(String.join(" ", stringsSequencesCollection.get(index)));
I think it should be work correct but there is a problem - the sub array list's count isn't correct: All the sub arrayList's size is 1 and for this reason the output is not correct. I don't understand what is the reason for this. If anybody can help me to fix the code I will be gratefull!
I think it is fairly straight forward just keep track of a max sequence length as you go through the array building sequences.
String input = "hi yes yes yes bye";
String sa[] = input.split(" ");
int maxseqlen = 1;
String last_sample = sa[0];
String longest_seq = last_sample;
int seqlen = 1;
String seq = last_sample;
for (int i = 1; i < sa.length; i++) {
String sample = sa[i];
if (sample.equals(last_sample)) {
seqlen++;
seq += " " + sample;
if (seqlen > maxseqlen) {
longest_seq = seq;
maxseqlen = seqlen;
}
} else {
seqlen = 1;
seq = sample;
}
last_sample = sample;
}
System.out.println("longest_seq = " + longest_seq);
Lots of issues.
First of all, when dealing with the last string of the list you are not actually printing it before clearing it. Should be:
if(i == strings.length - 1)
//...
System.out.println(stringsSequences + " " + stringsSequences.size());
stringsSequences.clear();
This is the error in the output.
Secondly, and most importantly, when you do stringsSequencesCollection.add you are adding an OBJECT, i.e. a reference to the collection. When after you do stringsSequences.clear(), you empty the collection you just added too (this is because it's not making a copy, but keeping a reference!). You can verify this by printing stringsSequencesCollection after the first loop finishes: it will contain 3 empty lists.
So how do we do this? First of all, we need a more appropriate data structure. We are going to use a Map that, for each string, contains the length of its longest sequence. Since we want to manage ties too, we'll also have another map that for each string stores the leftmost ending position of the longest sequence:
Map<String, Integer> lengths= new HashMap<>();
Map<String, Integer> indexes= new HashMap<>();
String[] split = input.split(" ");
lengths.put(split[0], 1);
indexes.put(split[0], 0);
int currentLength = 1;
int maxLength = 1;
for (int i = 1; i<split.length; i++) {
String s = split[i];
if (s.equals(split[i-1])) {
currentLength++;
}
else {
currentLength = 1;
}
int oldLength = lengths.getOrDefault(s, 0);
if (currentLength > oldLength) {
lengths.put(s, currentLength);
indexes.put(s, i);
}
maxLength = Math.max(maxLength, currentLength);
}
//At this point, youll have in lengths a map from string -> maxSeqLengt, and in indexes a map from string -> indexes for the leftmost ending index of the longest sequence. Now we need to reason on those!
Now we can just scan for the strings with the longest sequences:
//Find all strings with equal maximal length sequences
Set<String> longestStrings = new HashSet<>();
for (Map.Entry<String, Integer> e: lengths.entrySet()) {
if (e.value == maxLength) {
longestStrings.add(e.key);
}
}
//Of those, search the one with minimal index
int minIndex = input.length();
String bestString = null;
for (String s: longestStrings) {
int index = indexes.get(s);
if (index < minIndex) {
bestString = s;
}
}
System.out.println(bestString);
Below code results in output as you expected:
public static void main(String[] args) {
System.out.println("Please enter a sequence of strings separated by spaces:");
Scanner inputStringScanner = new Scanner(System.in);
String[] strings = inputStringScanner.nextLine().split(" ");
System.out.println(String.join(" ", strings));
List <ArrayList<String>> stringsSequencesCollection = new ArrayList<ArrayList<String>>();
List <String> stringsSequences = new ArrayList<String>();
//stringsSequences.add(strings[0]);
boolean flag = false;
for (int i = 1; i < strings.length; i++) {
if(strings[i].equals(strings[i - 1])) {
if(flag == false){
stringsSequences.add(strings[i]);
flag= true;
}
stringsSequences.add(strings[i]);
}
}
int maximalStringSequence = Integer.MIN_VALUE;
int index = 0;
List <String> currentStringSequence = new ArrayList<String>();
for (int i = 0; i < stringsSequencesCollection.size(); i++) {
currentStringSequence = stringsSequencesCollection.get(i);
System.out.println(stringsSequencesCollection.get(i).size());
if (stringsSequencesCollection.get(i).size() > maximalStringSequence) {
maximalStringSequence = stringsSequencesCollection.get(i).size();
index = i;
//System.out.println("\n" + index);
}
}
System.out.println(stringsSequences.toString());

Categories