I'm trying to insert a word into an alphabetically sorted array of words. the code below converts the array to an arraylist and inserts the word into the right place. However, if the word to be inserted has to go at the very end, it doesn't get inserted. For the last for loop, I tried setting the condition to <= aList.size () but i get an a ArrayList.rangeCheck and ArrayList.get exception. Any help would be appreciated.
import java.util.*;
public class insertSort {
public static void main(String args []) {
String [] sortedArray = new String [] {"aa", "ball", "dog", "zebra", "zzz"};
ArrayList <String> aList = new ArrayList <String> (); //create new arraylist
for (int i=0; i < sortedArray.length; i++){
String temp = sortedArray [i];
aList.add(temp);
}
System.out.println(aList);
String word = "zzzz";
for (int i =0; i < aList.size();i++) {
String temp = aList.get(i);
int comparisonResult = word.compareTo(temp) ;
if (comparisonResult < 0 | comparisonResult == 0) {
aList.add(i , word);
break;}
}
System.out.println(aList);
}
}
Use a boolean to record whether you successfully inserted the word ahead of any others, and if not, add it to the end of the array:
boolean wasInserted = false;
for (int i =0; i < aList.size();i++) {
String temp = aList.get(i);
int comparisonResult = word.compareTo(temp) ;
if (comparisonResult < 0 || comparisonResult == 0) {
aList.add(i , word);
wasInserted = true;
break;
}
}
if(!wasInserted) {
aList.add(word);
}
The for loop will only add the new word to the List if the word comes alphabetically before another word or if it equals another word in your list. In the case of
String word = "zzzz";
This does come alphabetically before another or equal another word so it is not added.
You need to add some sort of check to see if the work was added and if not, call
aList.add(word)
to add the new word to the end of the list.
Related
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);
}
I am a beginner-novice and I am trying to figure out why the logic for finding the largest word doesn't work.
Sometimes the output will result in the correct longest word, the first word, or more than one word.
Thanks!!
PS
I do not really care about the cases if two words of the same length, which I will work later once I figure out why this doesn't work. And once again please note I am a beginner/novice. Thanks
import java.util.Scanner;
import java.util.ArrayList;
public class Word
{
public static String word(String str)
{
int longestCount=0;
int count=0;
int newWord=0;
String theWord="";
ArrayList <String> longestWord= new ArrayList <String>();
for (int i=0; i <str.length(); i++)
{
if (str.substring(i,i+1).equals(" "))
{
if (longestCount<count)
{
longestCount=count;
theWord="";
theWord=""+str.substring(newWord,i);
newWord=i+1;
count=0;
}
}
else
{
count++;
}
}
longestWord.add(theWord);
String output="";
for (int i=0; i<longestWord.size();i++)
output+=longestWord.get(i);
return output;
}
public static void main ()
{
Scanner scan= new Scanner(System.in);
String words= scan.nextLine();
System.out.println(word(words));
}
}
You are over thinking it. Just loop through the array list once, whenever you see a longer word, store the word/or its index:
ArrayList <String> words= new ArrayList <String>();
String currLongest = words.get(0);
for (String s : words)
if(s.length() > currLongest.length())
currLongest = s;
If your words are being passed as a single String delimited by spaces, the procedure is the same. Just split them before looping:
String[] words = str.split(" ");
String currLongest = words.[0];
for (String s : words)
if(s.length() > currLongest.length())
currLongest = s;
Note that there is no need to store the longest word into a list because at any point of time, there should only be one longest word.
It'll be easier to chop up the string using split first. then you can simplify your codes to the following.
I have commented as much as I can in the code below
public static List<String> word(String str)
{
String[] choppedUpWord = str.split(" ");
int longestWordLength = 0; //we reset the longestWord if this is updated.
ArrayList <String> longestWord= new ArrayList <String>(); //the results
for(int i=0; i < choppedUpWord.length; i ++){
String theWord = choppedUpWord[i];
if(longestWordLength < theWord.length()){
//new longest word found !
longestWord.clear(); //remove the old entries
longestWord.add(theWord); // add the new word in
longestWordLength = theWord.length(); update with new length
}else if(longestWordLength == theWord.length()){
//same length as the longest word, do an appending.
longestWord.add(theWord); // add the new word in
}
}
return longestWord;
}
it returns a list instead of a String for the event when several words are the same length.
edit alternatively you can use a StringBuilder too.
public static String word(String str)
{
String[] choppedUpWord = str.split(" ");
int longestWordLength = 0; //we reset the longestWord if this is updated.
StringBuilder longestWord= new StringBuilder(); //the results
for(int i=0; i < choppedUpWord.length; i ++){
String theWord = choppedUpWord[i];
if(longestWordLength < theWord.length()){
//new longest word found !
longestWord.setLength(0); //remove the old entries
longestWord.append(theWord); // add the new word in
longestWordLength = theWord.length(); //update with new length
}else if(longestWordLength == theWord.length()){
//same length as the longest word, do an appending.
longestWord.append(" "); //add a spacing between each word (or any delimiter that you like)
longestWord.add(theWord); // add the new word in
}
}
return longestWord.toString();
}
Hi biologist here with a little bit of coding background. my goal is to be able to input a string of characters and the code to be able to tell me how many times they occur and at what location in the string.
so ill be entering a string and i want the location and abundance of sq and tq within the string. with the location being the first character e.g njnsqjjfl sq would be located at postition 4.
This is what ive come up with so far (probably very wrong)
string S = "...";
int counter =0;
for(int i=0; i<s.length; i++){
if(s.charAt (i) == 'sq')}
counter++;})
string S = "...";
int counter =0;
for(int i=0; i<s.length; i++){
if(s.charAt (i) == 'tq')}
counter++;})
any input will help, thankyou
So , you can have multiple occurrences of "sq" and "tq" in your code, so you can have 2 arraylists to save these two separately(or one to save them together).
ArrayList<Integer>sqLocation = new ArrayList<>();
ArrayList<Integer>tqLocation = new ArrayList<>();
for(int i =0;i<s.length()-1;i++){
if(s.charAt(i)=='s' && s.charAt(i+1)=='q'){
sqLocation.add(i);
}
else if(s.charAt(i)=='t' && s.charAt(i+1)=='q'){
tqLocation.add(i);
}
}
System.out.println("No. of times sq occurs = "+sqLocation.size());
System.out.println("Locations ="+sqLocation);
System.out.println("No. of times tq occurs = "+tqLocation.size());
System.out.println("Locations ="+tqLocation);
This can be achieved using regex. Your use case is to count occurrences and position of those occurrences. The method match returns an integer list which is position and count is size of list
Exmaple code
public class RegexTest {
public static List<Integer> match(String text, String regex) {
List<Integer> matchedPos = new ArrayList<>();
Matcher m = Pattern.compile("(?=(" + regex + "))").matcher(text);
while(m.find()) {
matchedPos.add(m.start());
}
return matchedPos;
}
public static void main(String[] args) {
System.out.println(match("sadfsagsqltrtwrttqsqsqsqsqsqs", "sq"));
System.out.println(match("sadfsagsqltrtwrttqksdfngjfngjntqtqtqtqtqtq", "tq"));
}
}
what you want is a HashMap <String, List <Integer>>
this will hold, the String that you are looking for e.g. sq or tq, and a List of the positions that they are at.
You want to loop around using String.indexOf see https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#indexOf(java.lang.String,%20int)
psuedocode being
String contents = "sadfsagsqltrtwrttqksdfngjfngjntqtqtqtqtqtq";
map.add (lookFor, new ArrayList ());
int index = 0;
while ((index = contents.indexOf (lookFor, index)) != -1) {
list = map.get (lookFor);
list.add (index);
}
You should use not charAt but substring to get a part of String.
int count(String s, String target) {
int counter = 0;
int tlen = target.length();
for (int i = tlen; i < s.length(); i++) {
if (s.substring(i - tlen, i).equals(target)) {
counter++;
}
}
return counter;
}
// in some method
count("...", "sq");
count("...", "tq");
I am trying to make a script that will take a set of Words (custom class), organize them alphabetically into an array by their text value (this part works). From here I was going to count how many terms ahead of it are the same as it, and that will be the frequency for all those similar terms. Then it continues to do this till each element in the array has been assigned a frequency. From here it re sorts the elements back into their original position provided a pre stored variable that holds their original element order. Here is the code:
public void setFrequencies() {
List<Word> dupeWordList;
dupeWordList = new ArrayList<>(wordList);
dupeWordList.removeAll(Collections.singleton(null));
Collections.sort(dupeWordList, (Word one, Word other) -> one.getValue().compareTo(other.getValue()));
int count;
int currElement;
for(currElement = 0; currElement < dupeWordList.size(); currElement++) {
count = 1;
Word tempWord = dupeWordList.get(currElement);
tempWord.setFrequency(count);
if(currElement+1 <= dupeWordList.size() - 1) {
Word nextWord = dupeWordList.get(currElement+1);
while(tempWord.getValue().equals(nextWord.getValue())) {
count++;
currElement++;
tempWord.setFrequency(count);
for(int e = 0; e < count - 1; e++) {
Word middleWord = new Word();
if(currElement-count+2+e < dupeWordList.size() - 1) {
middleWord = dupeWordList.get(currElement-count+2+e);
}
middleWord.setFrequency(count);
}
if(currElement+1 <= dupeWordList.size() - 1) {
nextWord = dupeWordList.get(currElement+1);
} else {
break;
}
}
break;
}
}
List<Word> reSortedList = new ArrayList<>(wordList);
Word fillWord = new Word();
fillWord.setFrequency(0);
fillWord.setValue(null);
Collections.fill(reSortedList, fillWord);
for(int i = 0; i < dupeWordList.size(); i++) {
Word word = dupeWordList.get(i);
int wordOrder = word.getOrigOrder();
reSortedList.set(wordOrder, word);
}
System.out.println(Arrays.toString(DebugFreq(reSortedList)));
setWordList(reSortedList);
}
public int[] DebugFreq(List<Word> rSL) {
int[] results = new int[rSL.size()];
for(int i=0; i < results.length; i++) {
results[i] = rSL.get(i).getFrequency();
}
return results;
}
As you can see I set up a little debug method at the bottom. When I run this method is shows that every word was given a frequency of 1. I cant see the issue in my code, nor does it get any errors. Keep in mind I have had it display the sorted dupeWordList and it does correctly alphabetize and their are consecutive duplicate elements in it so this should not be happening.
So If I understand you correctly.. below code would be your solution.
Okay You have a list which is having a strings (terms or words) which are sorted in alphabetical Order.
// Okay the below list is already sorted in alphabetical order.
List<String> dupeWordList = new ArrayList<>(wordList);
To count the Frequency of words in your list, Map<String, Integer> might help you as below.
//Take a Map with Integer as value and String as key.
Map<String,Integer> result = new HashMap<String,Integer> ();
//Iterate your List
for(String s : dupeWordList)
{
if(map.containskey(s))
{
map.put(s,map.get(s)+1);
// Please consider casting here.
}else
{
map.put(s,1);
}
}
Okay now we have a map which is having the frequency of your words or terms as value in your map.
Hope it helps.
I'm making this method remove() which takes a String word as argument, to delete from a global Array "words", but I keep getting a NullPointerException for some reason I cannot find, been stuck for hours.
Basically I check for if the word is in the first position, else if is in the last position, or else if it is in neither so I check all the array, and add the first half before the position of the word, and then add the second half after the position of the word in the array, as to skip it and "delete it". But I'm getting a NullPointerException in the for loop looking for the position of the word in the array. Code for the method is here:
public void remove(String a){
String[] temp_arr = new String[words.length-1]; // make array with 1 less length for deleted
if(words[0].equals(a)){ // if the word is the first in the array
for(int x=0, z=1; x<temp_arr.length; x++,z++)
temp_arr[x]=words[z];
words = temp_arr;
} else if(words[words.length-1].equals(a)){ // if the word is in the last position of the array
for(int x=0, z=0; x<temp_arr.length; x++,z++)
temp_arr[x] = words[z];
words = temp_arr;
} else{ // if the word is in neither first or last position of array
// THIS IS WHERE the exception is thrown, in this for loop, in the if(words[k].equals(a))
int k=0;
for (; k<words.length; k++){ // find the position of the word to delete
if (words[k].equals(a)) {
break;
}
}
for (int i = 0; i < k-1; i++){ // add first part of array before the word
temp_arr[i] = words[i];
}
for(int c = k, b = k+1; c< temp_arr.length; c++,b++){
temp_arr[c] = words[b];
}
words = temp_arr; // assign the new values to global array
}
}
Also, if theres any suggestions for good coding practice would be appreciated, thanks!
** I can only use Arrays as my data structure for this method.
Modify the condition like this
a.equals(words[0])
because you know the string value a. But dont know what value will come from array. So even null value comes from the array it does allow the null pointer exception.
I run your code and find a few errors, I correct somethings without changing the core idea:
} else { // if the word is in neither first or last position of array
// THIS IS WHERE the exception is thrown, in this for loop.
int k = -1;
for (int i = 0; i < words.length; i++) { // find the position of the word to delete
if (words[i].equals(a)) {
k=i;
break;
}
}
if(k<0)//if not exists
return;
for (int i = 0; i < k /*- 1*/; i++) { // add first part of array before the word
temp_arr[i] = words[i];
}
for (int i = k; i < temp_arr.length; i++) {
temp_arr[i] = words[i+1];
}
words = temp_arr; // assign the new values to global array
}
If the original array could't have null elements I would do like this:
public static String[] remove(String words[] , String a) {
int counter = 0;
for (int i = 0; i < words.length; i++) {
if( a.equals(words[i]) ){
words[i] = null;
counter++;
}
}
if(counter==0){
return words;
}
String[] words2 = new String[words.length - counter];
int i=0;
for (String string : words) {
if(string!=null){
words2[i++]=string;
}
}
return words2;
}
I would do that like this:
public void remove(String a) {
List<String> tmp = new ArrayList<String>();
for (String word : words) {
if ((word != null) && (word.equals(a))) {
continue;
}
tmp.add(word);
}
words = tmp.toArray(new String[]);
}
I have a question for you:
Why oh why are you using an array? You should always use a collection (eg a List) unless you absolutely have to use an array (which is rare indeed).
If it were a List, you wouldn't even need this method, because List has the remove() method that does all this for you!