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

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

Related

How do i optimize this Java code for CyclicShift (Hackerearth question)?

I have written a solution for Cyclic shift question on Hackerearth.
You can find this question on Hackerearth -> Codemonk -> Arrays & String -> Cyclic shift.
This solution gives TLE for large testcases. How do i optimize this code.
It seems like Java does not handle strings efficiently. Same code in Python gets accepted.
import java.io.*;
import java.util.*;
class TestClass
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
while(T-- > 0){
int N; int K;
N = sc.nextInt();
K = sc.nextInt();
String input = sc.next();
String B = "";
String inter = input;
int d = 0;
int period = -1;
for(int i = 0; i < N;i++){
if (B.compareTo(inter) < 0){
B = inter;
d = i;
}else if (B.compareTo(inter) == 0){
period = i - d;
break;
}
inter = inter.substring(1, inter.length()) + inter.substring(0, 1);
}
if(period == -1){
System.out.println(d + (K - 1L ) * N);
}else{
System.out.println(d + ((K - 1L) * period));
}
}
}
}
I tried fast IO, it did not help.
Please give me the Optimized Solution.
As suggested by maraca. Following solution does gets accepted.
import java.io.*;
import java.util.*;
class TestClass
{
static int compare(LinkedList<Character> A, LinkedList<Character> B){
Iterator<Character> i = A.iterator();
Iterator<Character> j = B.iterator();
if(A.size() == 0){ return -1;}
while (i.hasNext()) { // we know they have same length
char c = i.next();
char d = j.next();
if (c < d)
return -1;
else if (c > d)
return 1;
}
return 0;
}
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
while(T-- > 0){
int N; int K;
N = sc.nextInt();
K = sc.nextInt();
String input = sc.next();
LinkedList<Character> B = new LinkedList<>();
int d = 0;
int period = -1;
LinkedList<Character> inter = new LinkedList<>();
for(char c: input.toCharArray()){inter.add(c);}
for(int i = 0; i < N;i++){
if (compare(B, inter) < 0){
B = new LinkedList<>(inter);
d = i;
}else if (compare(B, inter) == 0){
period = i - d;
break;
}
inter.add(inter.removeFirst());
}
if(period == -1){
System.out.println(d + (K - 1L ) * N);
}else{
System.out.println(d + ((K - 1L) * period));
}
}
}
}
Strings are immutable in Java. You could try to use LinkedList:
LinkdedList<Character> inter = new LinkedList<>(Arrays.stream(inter)
.boxed()
.collect(Collectors.toList()));
Alternatively:
LinkdedList<Character> inter = new LinkedList<>();
for (char c : input.toCharArray())
inter.add(c);
Then the shift becomes:
inter.add(inter.removeFirst());
And the comparison can be done as follows:
private int compare(List<Character> a, List<Character> b) {
Iterator<Character> i = a.iterator();
Iterator<Character> j = b.iterator();
while (i.hasNext()) { // we know they have same length
char c = i.next();
char d = j.next();
if (c < d)
return -1;
else if (c > d)
return 1;
}
return 0;
}
my solution
import java.io.*;
import java.util.*;
class TestClass
{
static int compare(LinkedList<Character> A, LinkedList<Character> B){
Iterator<Character> i = A.iterator();
Iterator<Character> j = B.iterator();
if(A.size() == 0){ return -1;}
while (i.hasNext()) { // we know they have same length
char c = i.next();
char d = j.next();
if (c < d)
return -1;
else if (c > d)
return 1;
}
return 0;
}
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
while(T-- > 0){
int N; int K;
N = sc.nextInt();
K = sc.nextInt();
String input = sc.next();
LinkedList<Character> B = new LinkedList<>();
int d = 0;
int period = -1;
LinkedList<Character> inter = new LinkedList<>();
for(char c: input.toCharArray()){inter.add(c);}
for(int i = 0; i < N;i++){
if (compare(B, inter) < 0){
B = new LinkedList<>(inter);
d = i;
}else if (compare(B, inter) == 0){
period = i - d;
break;
}
inter.add(inter.removeFirst());
}
if(period == -1){
System.out.println(d + (K - 1L ) * N);
}else{
System.out.println(d + ((K - 1L) * period));
}
}
}
}

Rearrange words in string in alphabetical order

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;
}
}
}

Each substring of a certian length of a binary substring should have at least one '1' character

You have been given a binary string containing only the characters '1' and '0'.
Calculate how many characters of the string need to be changed in order to make the binary string such that each of its substrings of at least a certain length contains at least one "1" character.
I came to think of the following idea but it fails for many testcases:
public static int minimumMoves(String s, int d) {
int n = s.length();
int i=0, answer = 0;
while(i<n)
{
boolean hasOne = false;
int j=i;
while(j<n && j<i+d)
{
if(s.charAt(j) == '1')
{
hasOne = true;
break;
}
j++;
}
if(!hasOne) {
answer++;
i += d;
}
else i++;
}
return answer;
}
Also my algorithm runs on O(|s|2) time. Can anyone suggest ideas on O(|s|) time?
Just throwing off an idea:
return s.split("(?<=\\G.{" + String.valueof(d) + "})").stream().filter(str -> str.contains("1")).count()
You just need to break ensure there is no run of d zeros.
public static int minimumMoves(String s, int d) {
int result = 0;
int runLength = 0;
for(char c: s.toCharArray()) {
if (c == '0') {
runLength += 1;
if (runLength == d) { // we need to break this run
result += 1;
runLength = 0;
}
} else {
runLength = 0;
}
}
return result;
}
I used the sliding window technique and Deque to solve this. This is my accepted solution:
public static int minimumMoves(String s, int d) {
int n = s.length();
Deque<Character> dq = new LinkedList<>();
int count = 0, answer = 0;
for(int i=0; i<d; i++)
{
if(s.charAt(i) == '1') count++;
dq.addLast(s.charAt(i));
}
if(count == 0) {
answer++;
count++;
dq.removeLast();
dq.addLast('1');
}
int i=d;
while(i<n)
{
if(dq.getFirst() == '1') count--;
dq.removeFirst();
if(s.charAt(i) == '1') count++;
dq.addLast(s.charAt(i));
if(count == 0)
{
answer++;
dq.removeLast();
dq.addLast('1');
count++;
}
i++;
}
return answer;
}
You just need to use a sliding window and a count of 1s so far at each index. Use a sliding window of d and if you don't see any ones so far, update the last index of that window with 1 and increment the result.
Code below:
public static int minimumMoves(String s, int d) {
int n = s.length();
int[] count = new int[n+1];
int res = 0;
for ( int i = 1; i <= d; i++ ) {
if ( s.charAt(i-1) == '1') count[i] = count[i-1]+1;
else count[i] = count[i-1];
}
if ( count[d] == 0 ) {
res++;
count[d] = 1;
}
for ( int i = d+1; i <= n; i++ ) {
if ( s.charAt(i-1) == '0' ) {
count[i] = count[i-1];
int ones = count[i] - count[i-d];
if ( ones == 0 ) {
count[i] = count[i-1] + 1;
res++;
}
} else {
count[i] = count[i-1] + 1;
}
}
return res;
}
Thought of another implementation you can do for this by working from the maximum possible changes (assumes at start that all values are '0' in String), reduce it when it finds a '1' value, and then jump to the next substring start. This allows it to run in O(n) and Ω(n/m) (n = String length, m = Substring length).
public static int minimumMoves(String s, int d)
{
char[] a = s.toCharArray();
//Total possible changes (not counting tail)
if(a.length < d)
return 0;
int t = (int) a.length / d;
//Total possible changes (counting tail)
//int t = (int) Math.ceil((double) a.length / (double) d);
for(int i = 0; i < a.length; i++)
{
if(a[i] == '1')
{
t--;
//Calculate index for start of next substring
i = (i / d + 1) * d - 1;
}
}
return t;
}

Iterating through a character array in Java - improving algorithm

I'm trying to iterate through my array to produce all possible combinations of the given char array.
If the length I specify is 4 then I want it to iterate through all combinations of the chars in the array up to a length of 4.
It would look something like this:
char[] charArray = "abcdefghijklmnopqrstuvwxyz".toCharArray();
Output of method I want:
a,
b,
c,
...,
x,
y,
z,
aa,
ab,
ac,
...,
ax,
ay,
az,
ba,
bb,
bc,
...,
bx,
by,
bz,
ca,
cb,
cc,
...
zzzx,
zzzy,
zzzz
Here's some code:
cs = charArray;
cg = new char[4]; // 4 up to 4 characters to guess
int indexOfCharset = 0; // should I be using all these?
int indexOfCurrentGuess = 0;
int positionInString = 0;
public void incrementNew() {
// 1 DIGIT guesses
if (cg.length == 0) {
if (indexOfCharset == cs.length) {
cg = new char[cg.length + 1];
} else {
cg[positionInString] = nextChar();
}
}
// 2 DIGIT guesses
else if (cg.length == 1) {
if (cg[0] == cs.length && cg[1] == cs.length) {
cg = new char[cg.length + 1];
} else {
... Something goes here <-
cg[positionInString] = nextChar();
}
}
System.out.println("cg[0]=" + cg[0]);
}
public char nextChar() {
char nextChar;
if (indexOfCharset < cs.length) {
nextChar = cs[indexOfCharset];
} else {
indexOfCharset = 0;
nextChar = cs[indexOfCharset];
}
indexOfCharset++;
//System.out.println("nextChar = " + nextChar);
return nextChar;
}
The only way I can think of doing it is using lots of IF statements - is there an algorithm or way to do it neater? If not then any suggestions on how to deal with two or more characters?
EDIT:
I want it to work for any unsorted char arrays not just a-z.
All the implementations I've found only work for sorted arrays..
You could try this:
static char[] letters = "abcdefghijklmnopqrstuvwxyz".toCharArray();
static void getChars(char[] lastChars, int pos, int length) {
for (char c : letters) {
char[] newChars = lastChars.clone();
newChars[pos] = c; // if you have "aa" for example and the current length is 4. If c = "a", newChars is now "aaa"
if (pos + 1 < length) { // as your lenths is 4 and you still have only 3 letters, getChars adds the missing ones
getChars(newChars, pos + 1, length);
} else {
System.out.println(newChars);
}
}
}
public static void main(String[] args) {
int maxLength = 4;
for (int length = 1; length <= maxLength; length++) {
for (char c : letters) {
if (length > 1) {
char[] chars = new char[length];
chars[0] = c;
getChars(chars, 1, length);
} else {
System.out.println(c);
}
}
}
}

How to write an "all these numbers are different" condition in Java?

OK, I have this problem to solve but I can’t program it in Java correctly. See the picture below, you’ll see a 6 pointed star were every point and intersection of lines is a letter.
The assignment is to position the numbers 1 to 12 in such a way that the sum of all lines of four balls is 26 and the sum of all the 6 points of the star is 26 as well.
This comes down to:
(A+C+F+H==26)
(A+D+G+K==26)
(B+C+D+E==26)
(B+F+I+L==26)
(E+G+J+L==26)
(H+I+J+K==26)
(A+B+E+H+K+L==26)
So I started programming a program that would loop through all options brute forcing a solution. The loop is working, however, it now shows solutions where one number is used more than once, which is not allowed. How can I make it in the code that it also checks whether all variables are different or not?
if ((A!= B != C != D != E != F != G != H != I != J != K != L)
I tried the above, but it doesn't work, because it says:
incomparable types: boolean and int.
How can I make a check within 1 or a small statement for whether or not all the numbers are different?
(instead of making a nested 12*12 statement which checks every variable combination)
This is my code so far:
public class code {
public static void main(String[] args){
for(int A = 1; A < 13; A++){
for(int B = 1; B < 13; B++){
for(int C = 1; C < 13; C++){
for(int D = 1; D < 13; D++){
for(int E = 1; E < 13; E++){
for(int F = 1; F < 13; F++){
for(int G = 1; G < 13; G++){
for(int H = 1; H < 13; H++){
for(int I = 1; I < 13; I++){
for(int J = 1; J < 13; J++){
for(int K = 1; K < 13; K++){
for(int L = 1; L < 13; L++){
if ((A+C+F+H==26) && (A+D+G+K==26) && (B+C+D+E==26) && (B+F+I+L==26) && (E+G+J+L==26) && (H+I+J+K==26) && (A+B+E+H+K+L==26)){
if ((A= C != D != E != F != G != H != I != J != K != L)){
System.out.println("A: " + A);
System.out.println("B: " + B);
System.out.println("C: " + C);
System.out.println("D: " + D);
System.out.println("E: " + E);
System.out.println("F: " + F);
System.out.println("G: " + G);
System.out.println("H: " + H);
System.out.println("I: " + I);
System.out.println("J: " + J);
System.out.println("K: " + K);
System.out.println("L: " + L);
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
If I get it correctly, you want to check if all A to L are unique. So just put them in a set and find the size of the set:
if ((new HashSet<Integer>(
Arrays.asList(A, B, C, D, E, F, G, H, I, J, K, L)))
.size() == 12) {
//do your stuff
}
I strongly advise using recursion instead, which would vastly simplify the code. Do something like this:
function generate(set used, array list):
if list.size() == 12:
if list matches criteria:
yield list as solution
else:
for next = 1; next < 13; next++:
if next not in used:
used.add(next)
generate(used, list + next)
used.remove(next)
However, to answer you question directly: You can throw all the values into a set and check that it's size is equal to the number of items you threw in. This works because a set will count duplicates as one.
Before looking for a good solution for you, I would like to help with the error you get.
if ((A= C != D != E != F != G != H != I != J != K != L)){
This line does not makes much sense. The first thing the compiler will check is:
if (A=C)
You probably wanted to code if (A!=C), but let's consider what you really type. A=C is an attribution, so A will receive C value.
Then, the compiler will go on. After attributing C's value to A, it will check the comparison:
if (A=C != D)
This will compare A's value to D, which will result in a boolean -- let's say that the result is false.
The next comparison would be:
if (false != E)
At this point, there is a comparison between a boolean and an int, hence the error incomparable types: boolean and int..
Well, as you need to check wheter your numbers are unique, a nice solution would be the one proposed by #abhin4v.
Your nested loops will execute 12^12 = 8.91610045E12 IF-Statements, many of them invalid because of wrong combinations of numbers. You need permutations of 1,2,3,..,12 as candidates of your bruteforcing approach. The number of permutations of 12 Elements is 12!= 479 001 600, so the bruteforcing will be much faster I guess. With only generating valid permutations you don't need any check for valid combinations.
Here is some sample code, the code in nextPerm() is copied and modified from Permutation Generator :
import java.util.Arrays;
public class Graph26 {
private static final int A = 0;
private static final int B = 1;
private static final int C = 2;
private static final int D = 3;
private static final int E = 4;
private static final int F = 5;
private static final int G = 6;
private static final int H = 7;
private static final int I = 8;
private static final int J = 9;
private static final int K = 10;
private static final int L = 11;
private final static boolean rule1(final int[] n) {
return n[A] + n[C] + n[F] + n[H] == 26;
}
private final static boolean rule2(final int[] n) {
return n[A] + n[D] + n[G] + n[K] == 26;
}
private final static boolean rule3(final int[] n) {
return n[H] + n[I] + n[J] + n[K] == 26;
}
private final static boolean rule4(final int[] n) {
return n[B] + n[C] + n[D] + n[E] == 26;
}
private final static boolean rule5(final int[] n) {
return n[B] + n[F] + n[I] + n[L] == 26;
}
private final static boolean rule6(final int[] n) {
return n[E] + n[G] + n[J] + n[L] == 26;
}
private final static boolean rule7(final int[] n) {
return n[A] + n[B] + n[E] + n[H] + n[K] + n[L] == 26;
}
private final static boolean isValid(final int[] nodes) {
return rule1(nodes) && rule2(nodes) && rule3(nodes) && rule4(nodes)
&& rule5(nodes) && rule6(nodes) && rule7(nodes);
}
class Permutation {
private final int[] o;
private boolean perms = true;
public boolean hasPerms() {
return perms;
}
Permutation(final int[] obj) {
o = obj.clone();
}
private int[] nextPerm() {
int temp;
int j = o.length - 2;
while (o[j] > o[j + 1]) {
j--;
if (j < 0) {
perms = false;
break;
}
}
if (perms) {
int k = o.length - 1;
while (o[j] > o[k]) {
k--;
}
temp = o[k];
o[k] = o[j];
o[j] = temp;
int r = o.length - 1;
int s = j + 1;
while (r > s) {
temp = o[s];
o[s] = o[r];
o[r] = temp;
r--;
s++;
}
}
return o.clone();
}
}
public static void main(final String[] args) {
int[] nodes = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
final Graph26 graph = new Graph26();
final Permutation p = graph.new Permutation(nodes);
int i = 0;
while (p.hasPerms()) {
if (isValid(nodes)) {
System.out.println(Arrays.toString(nodes));
}
i++;
nodes = p.nextPerm();
}
System.out.println(i);
}
}

Categories