Rearrange words in string in alphabetical order - java

I'm trying to rearrange words in any given string (20 words or less). I'm having this issue because I can not get the last word in the string to print. I tried modifying the loop range, but I am not able to fix the issue.
public class ListString {
String[] list = new String[20];
int n = 0;
public void read() {
Scanner in = new Scanner(System.in);
System.out.println("Please enter the sentence");
String s = in.nextLine();
String temp = "";
for (int i = 0; i < s.length(); i++)
{
char ch = s.charAt(i);
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) // range from a to z
temp = temp + ch;
else
{
if (temp.length() > 0)
{
list[n] = temp;
n++;
temp = "";
}
}
}
}
public void print() {
System.out.print(list[0]);
for (int i = 0; i < n; i++)
System.out.print(" " + list[i]);
System.out.println(" ");
}
public void sort() {
for (int i = 0; i < n; i++) {
String key = list[i];
int j = i - 1;
while (j >= 0 && (list[j].compareToIgnoreCase(key) > 0))
{
list[j + 1] = list[j];
j = j - 1;
}
list[j + 1] = key;
}
}
}

That happens, when you hit end of the string and temp is not empty. To fix it you can add same if statement after loop:
for(int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
if((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
temp = temp + ch;
} else {
if(temp.length() > 0) {
list[n] = temp;
n++;
temp = "";
}
}
}
if(temp.length() > 0) {
list[n] = temp;
n++;
temp = "";
}
Also you would need to fix your output to not print first word twice:
public void print() {
for(int i = 0; i < n; i++) {
System.out.print(list[i] + " ");
}
System.out.println();
}
Output before fix:
a b c d e f g h i j k l m n o p q r s t
a a b c d e f g h i j k l m n o p q r s
Output after fix:
a b c d e f g h i j k l m n o p q r s t
a b c d e f g h i j k l m n o p q r s t
Update:
Also you can solve your problem in one line, using streams
public void read() {
Scanner in = new Scanner(System.in);
System.out.println("Please enter the sentence");
String s = in.nextLine();
String[] list = Arrays.stream(s.split(" ")).limit(20).sorted().toArray(String[]::new);
}
It splits input string by space character, takes first 20 words, sorts them and creates an array of them.
Output:
t s r q p o n m l k j i h g f e d c b a z z z z z
a b c d e f g h i j k l m n o p q r s t

You don't need to handle the end of the string explicitly: by using integer pointers to the start and end of words, you can do it as follows:
int start = 0;
while (start < s.length()) {
// Increment a start pointer until it points to the end of the string or the start of a word.
while (start < s.length() && !isLetter(s.charAt(start))) {
start++;
}
// Increment an end pointer until it points to the end of the string or a non-word character.
int end = start;
while (end < s.length() && isLetter(s.charAt(end))) {
end++;
}
if (start == end) {
// You reached the end of the string.
break;
}
// Grab the portion of the string between start and end, this is a word.
list[n++] = s.substring(start, end);
// Set up the start pointer to point to the end of this word, for the next iteration.
start = end;
}
where isLetter(char) is a method that checks if the argument is between A and Z (in either case).
I have seen a variation on this method which avoids the inner while loops: I don't like this as much, as I think it's less clear to read; but it doesn't have quite so much repetitive checking of the length (I think this code works, not tried it):
for (int start = 0, end = 0; start < s.length();) {
if (!isLetter(s.charAt(start))) {
start++;
end = start;
} else if (isLetter(s.charAt(end))) {
end++;
if (end >= s.length() || !isLetter(s.charAt(end))) {
list[n++] = s.substring(start, end);
start = end;
}
}
}

Related

JAVA // How do i make it case-insensitive?

import java.util.Random;
public class MergeSortEx {
public static void mergeSort(char[] array) {
sortArray(array, 0, array.length);
}
private static void sortArray(char[] array, int start, int end) {
if (end-start <2)
return;
int mid = (start + end) / 2;
sortArray(array, 0, mid);
sortArray(array, mid, end);
mergeArray(array, start, mid, end);
}
private static void mergeArray(char[] array, int start, int mid, int end) {
char[] temp = new char[end - start];
int t = 0, s = start, m = mid;
while (s < mid && m < end) {
if (array[s] < array[m])
temp[t++] = array[s++];
else
temp[t++] = array[m++];
}
while (s < mid) {
temp[t++] = array[s++];
}
while (m < end) {
temp[t++] = array[m++];
}
for(int i=start;i<end;i++) {
array[i]=temp[i-start];
}
}
public static void main(String[] args) {
char[] randomString = new char[20];
Random rnd = new Random();
for (int i = 0; i < 20; i++) {
if (i < 10)
randomString[i] = (char) (rnd.nextInt(6) + 'A');
else
randomString[i] = (char) (rnd.nextInt(6) + 'a');
}
System.out.println(randomString.length);
for (int i = 0; i < 20; i++)
System.out.print(randomString[i] + " ");
mergeSort(randomString);
System.out.println();
for (int i = 0; i < 20; i++)
System.out.print(randomString[i] + " ");
}
}
I used the translator.
It's a university algorithm assignment, Merge sort implemented successfully.
Now, capital letters come out first, and lowercase letters come out.
Can make the code case-insensitive?
I want the results to be like this.
ex) a A A B b C c c D d ...
plz help.
Instead of comparing using if (array[s] < array[m]) directly, convert the characters to uppercase before comparing, similar to what String.compareToIgnoreCase(...) does:
if (Character.toUpperCase(array[s]) < Character.toUpperCase(array[m]))
That is for sorting individual characters. For sorting String values, there are two ways to make a case-insensitive sort:
Use the predefined String.CASE_INSENSITIVE_ORDER Comparator.
stringList.sort(String.CASE_INSENSITIVE_ORDER);
Use a Collator:
Collator collator = Collator.getInstance(Locale.US);
stringList.sort(collator);
That will sort localized alphabets correctly, e.g. if you specified Locale.GERMANY, it would sort upper- and lower-case letters together, but will e.g. also sort Ð between D and E, and sort ß same as S.
Just replace:
while (s < mid && m < end) {
if (arr[s] < arr[m])
temp[t++] = arr[s++];
else
temp[t++] = arr[m++];
}
with
while (s < mid && m < end) {
if (Character.toLowerCase(arr[s]) < Character.toLowerCase(arr[m]))
temp[t++] = arr[s++];
else
temp[t++] = arr[m++];
}
If you want small letters come first like aAbbbBBBcCCCD then try following.
Instead of:
array[s] < array[m]
Use:
private static boolean charCompare(char a, char b) {
char ua = Character.toUpperCase(a);
char ub = Character.toUpperCase(b);
if(ua == ub) {
return a > b;
} else {
return ua < ub;
}
}
Output:
20
F E E A D A B C A E a e c f d f c a f e
a a A A A B c c C d D e e E E E f f f F

java.lang.StringIndexOutOfBoundsException: String index out of range: 45

I'm trying to make a program that takes in a string like: KKKKKKKKKKKKKBCCDDDDDDDDDDDDDDDKKKKKMNUUUGGGGG
And returns something like this: $K13BCC$D15$K5MNUUU$G5
Another example is XYZAAAAAAGGTCCCCCCTTTAAAAAAAAAAAAAAKK
Returns: XYZ*A6GGT*C6TTT*A14KK
But i get this StringIndexOutOfBoundsException when i try the first input, can anyone tell me why? Here's my code:
import java.util.Scanner;
class RunLengthEncoding {
public static void main(String[] args) {
Scanner h = new Scanner(System.in);
String s;
char g;
System.out.print("Enter input string: ");
s = h.next();
for (int d = 0; d < s.length(); d++){
if (!Character.isUpperCase(s.charAt(d))){
System.out.print("Bad input.");
return;
}
}
System.out.print("Enter flag character: ");
g = h.next().charAt(0);
if (g != '#' && g != '$' && g != '&' && g != '*'){
System.out.println("Bad input.");
return;
}
char c = s.charAt(0);
String encode = "";
for (int n = 0; n < s.length() - 1; n++){
int k = 0;
int j = 0;
while (k + n < s.length() && s.charAt(k + n) == c){
j++;
k++;
}
if (j > 3){
encode += g;
encode += c;
encode += j;
n += j - 1;
}
else {
encode += c;
}
c = s.charAt(n + 1);
}
System.out.println("Encoded: " + encode);
}
}
The reason that you are getting an out of bounds exception is because you are incrementing n outside of the for loop statement. You do this when you are doing n += j - 1;. This gives you an out of bounds exception because when you do c = s.charAt(n + 1);, n could be greater than or equal to the length of the string. As a general rule, you should not alter the value of the iteration variable in the for loop anywhere outside of the for loop. It makes the code harder to debug.
For anyone interested in the solution I made:
import java.util.Scanner;
public class RunLengthEncoding {
public static void main(String[] args){
Scanner h = new Scanner(System.in);
String s;
char g;
StringBuilder encode = new StringBuilder();
System.out.print("Enter input string: ");
s = h.next();
for (int d = 0; d < s.length(); d++) {
if (!Character.isUpperCase(s.charAt(d))) {
System.out.print("Bad input.");
return;
}
}
System.out.print("Enter flag character: ");
g = h.next().charAt(0);
if (g != '#' && g != '$' && g != '&' && g != '*') {
System.out.println("Bad input.");
return;
}
for (int n = 0; n < s.length(); n++) {
int k = 1;
while (n < s.length() - 1 && s.charAt(n) == s.charAt(n + 1)) {
k++;
n++;
}
if (k > 3) {
encode.append(g).append(s.charAt(n)).append(k);
}
else {
for (int c = 0; c < k; c++) {
encode.append(s.charAt(n));
}
}
}
System.out.print("Encoded: " + encode);
}
}

Longest String With Chars Palindrome

Problem description from school assignment
Longest String With Palindrome
I'm getting complexity O(N^2). How can I achieve O(N*log(N))**
My code
int maxL = 0;
for (int i = 0; i < S.length(); i++) {
String currentString = String.valueOf(S.charAt(i));
for (int j = i + 1; j < S.length(); j = j + 1) {
String jStr = String.valueOf(S.charAt(j));
if (currentString.contains(jStr)) {
currentString = currentString.replace(jStr, "");
int len = j - i + 1;
if (currentString.length() == 0 && maxL < len) {
maxL = len;
}
} else {
currentString = currentString + jStr;
}
}
}
return maxL;
This problem can be solved in O(n) time using O(n) space. The following algorithm uses a bit set to keep track of the unbalanced characters for the substrings starting at the beginning of the given string. It makes a single pass through the string and remembers the states it has already seen in a hash map. Whenever we see the same state a second time, we have found a valid password: just remove the old shorter substring from the beginning of the current substring.
private static int index(char c) {
if (c < '0') throw new IllegalArgumentException("illegal char");
if (c <= '9') return c - '0';
if (c < 'a') throw new IllegalArgumentException("illegal char");
if (c <= 'z') return c - 'a' + 10;
throw new IllegalArgumentException("illegal char");
}
private static int solution(String s) {
HashMap<BitSet, Integer> states = new HashMap<>();
int longest = 0;
BitSet state = new BitSet();
states.put((BitSet) state.clone(), 0);
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
state.flip(index(c));
Integer seenAt = states.get(state);
if (seenAt != null) {
int len = i - seenAt + 1;
if (len > longest) longest = len;
} else {
states.put((BitSet) state.clone(), i + 1);
}
}
return longest;
}

Making a hollow diamond with a word in it

What I need is a little modification to my code so that every part of my hollow diamond prints a letter of the word "HURRICANE"
My code is:
String st1 = "HURRICANE";
int a = 0;
for (int i = 5; i >= 1; i--) {
for (int j = 1; j <= 9; j++) {
if (j == i || (10 - i) == j) {
System.out.print(st1.charAt(a)); //needs change
} else {
System.out.print(' ');
}
}
System.out.println();
}
for (int i = 2; i <= 5; i++) {
for (int j = 1; j <= 9; j++) {
if (j == i || (10 - i) == j) {
System.out.print(st1.charAt(a)); //needs change
} else {
System.out.print(' ');
}
}
System.out.println();
}
The output comes out as:
H
H H
H H
H H
H H
H H
H H
H H
H
I need to modify my "charAt" statement a little so it comes out to be:
H
U U
R R
R R
I I
C C
A A
N N
E
How should I make my print statement?
It's worth noting that the example provided only works for Strings the same length as "HURRICANE". A superior solution would work for all strings.
Partial solution for you to complete, since I guess it's your coursework and I don't want you to copy / paste / fail exams :P
public static void main(String[] args) {
String st1 = "HURRICANE";
char[] st1CharArray = st1.toCharArray();
int maxSpaces = st1CharArray.length / 2 + 1;
for (int i = 0; i <= st1CharArray.length / 2; i++) {
if (i == 0) {
System.out.println(getSpacesString(maxSpaces) + st1CharArray[i]);
} else {
System.out.println(getSpacesString(maxSpaces - i)
+ st1CharArray[i] + getSpacesString(i * 2 - 1)
+ st1CharArray[i]);
}
}
// Loop from st1CharArray.length / 2 + 1 and get the second half done.
}
private static String getSpacesString(int numberOfSpaces) {
StringBuilder strBuilder = new StringBuilder();
for (int i = 0; i < numberOfSpaces; i++) {
strBuilder.append(" ");
}
return strBuilder.toString();
}
//: Playground - noun: a place where people can play
import UIKit
var name : String = "HURRICANE"
var dimensions : Int = name.count - 1
var k : Int = 0
for rows in 0...dimensions{
for columns in 0...dimensions{
k = abs( (dimensions/2) - rows )
if columns == k || columns == dimensions - k{
print(Array(name)[rows], terminator: "")
}
else{
print(" ", terminator: "" )
}
}
print("")
}
String st1 = "HURRICANE";
int a = 0;
for (int i = 5; i >= 1; i--) {
for (int j = 1; j <= 9; j++) {
if (j == i || (10 - i) == j) {
System.out.print(st1.charAt(5 - i));
} else {
System.out.print(' ');
}
}
System.out.println();
}
for (int i = 2; i <= 5; i++) {
for (int j = 1; j <= 9; j++) {
if (j == i || (10 - i) == j) {
System.out.print(st1.charAt(3 + i));
} else {
System.out.print(' ');
}
}
System.out.println();
}
Let's assume that a word has an odd number of characters, otherwise we get a crooked diamond.
Try it online!
public static void main(String[] args) {
String str = "abrahadabra";
int n = str.length() / 2;
for (int i = -n, ch = 0; i <= n && ch < str.length(); i++, ch++) {
for (int j = -n; j <= n; j++)
if (Math.abs(i) + Math.abs(j) == n)
System.out.print(str.charAt(ch));
else
System.out.print(" ");
System.out.println();
}
}
Output:
a
b b
r r
a a
h h
a a
d d
a a
b b
r r
a

Java: Count occurrence of letters in a String

I am trying to write a program that counts the occurrence of letters in a string. For example, if the user inputs "Java", it will display "j: 1 a: 2 v:1". However, there seems to be something wrong with my program, and when I input the word java this is what it shows "j: 0 a: 1 v: 0"
Scanner myScanner = new Scanner(System.in);
String s = myScanner.nextLine();
int i = 0;
int j = 0;
int cnt = 0;
int length = s.length();
char ch;
for (i = 0; i < length; i++) {
ch = s.charAt(i);
if (s.indexOf(ch) < i)
continue;
for (j = (i + 1); j < length; j++) {
if (s.charAt(j) == ch)
cnt++;
}
System.out.println(ch + ": " + cnt);
cnt = 0;
}
Your desired output:
Enter your String: Mascarena
M: 1
a: 3
s: 1
c: 1
r: 1
e: 1
n: 1
Error in your code:
for (j = (i + 1); j < length; j++) { //It is omitting the first letter and searches the remaining
if (s.charAt(j) == ch)
cnt++;
}
Rectified:
for (j = 0; j < length; j++) { //For a specific letter searches the whole string.
if (s.charAt(j) == ch)
cnt++;
}
Your 2nd for-loop is not searching the entire word for each letter.
For example, when searching for j it is only looking at ava because it starts at i + 1 which is
(0 + 1) = 1
this a in the string java as j would be index at 0. Change
for (j = (i + 1)..)
to
(j = 0..)
public static String numberOfOccurence(String data) {
String result = "";
while (!data.isEmpty()) {
result += String.valueOf(data.charAt(0))+ StringUtils.countOccurrencesOf(data, String.valueOf(data.charAt(0)));
data = data.replaceAll(String.valueOf(data.charAt(0)), "");
}
return result;
}
input: aabacbd
output: a3b2c1d1

Categories