I am working on below interview question where I need to print out alphabet and numbers using two threads. One prints alphabets (a,b,c...z) and other prints numbers(1,2,3....26). Now I have to implement it in such a way that the output should be:
a
1
b
2
...
...
z
26
So I came up with below code one without synchronization but for some reason it is not printing last alphabet which is z
class Output {
private static final int MAX = 26;
private static int count = 1;
private static final Queue<Character> queue = new LinkedList<>(Arrays.asList(new Character[] {
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}));
private boolean isAlphabet = true;
public void printAlphabet() {
while (true) {
if (count > MAX)
break;
if (!isAlphabet) {
System.err.println(Thread.currentThread().getName() + " : " + queue.remove());
isAlphabet = true;
}
}
}
public void printNumber() {
while (true) {
if (count > MAX)
break;
if (isAlphabet) {
System.err.println(Thread.currentThread().getName() + " : " + count++);
isAlphabet = false;
}
}
}
}
public class PrintAlphabetNumber {
public static void main(String[] args) {
Output p = new Output();
Thread t1 = new Thread(() -> p.printAlphabet());
t1.setName("Alphabet");
Thread t2 = new Thread(() -> p.printNumber());
t2.setName("Number");
t1.start();
t2.start();
}
}
Is there any issue in my above code? Also from synchronization perspective, does it look good or not?
for some reason it is not printing last alphabet which is z
You abort when count > MAX, which is true after the last number.
After the last number, you're supposed to print the last letter, but now count > MAX so it's already stopping.
from synchronization perspective, does it look good or not?
No, this does not look good.
You are using a spinlock. This is very inefficient as both loops use 100% CPU constantly, whether they have work to do or not. It's also not guaranteed to work with non-volatile lock variables.
The classic Java solution would use wait()/notify().
like they said this is not good code for doing this, but the issue with this code is that you got the if condition backwards.
public void printAlphabet() {
while (true) {
if (count > MAX)
break;
if (isAlphabet) {// this was !isAlphabet
System.err.println(Thread.currentThread().getName() + " : " + queue.remove());
isAlphabet = false;//also here
}
}
}
public void printNumber() {
while (true) {
if (count > MAX)
break;
if (!isAlphabet) {// this was isAlphabet
System.err.println(Thread.currentThread().getName() + " : " + count++);
isAlphabet = true;//also here
}
}
}
Related
Is it possible to use insertion sort algorithm to sort the vowels at the beginning of a string?
I tried a lot but I don't get it , has somebody a hint how it could be implemented or should I use an other sort algorithm?
static char[] text = "thisIsAString".toCharArray();
static void instertionSort() {
for (int i = 0; i < text.length; i++) {
char h = text[i];
int j = i - 1;
while ((j >= 0) && Character.toLowerCase(text[j]) > Character.toLowerCase(h)) {
text[j+1] = text[j];
j = j - 1;
}
text[j+1] = h;
}
}
Example: "thisIsAString" -> "AiiIghnrssStt"
You can use insertion sort for this (just like every other sort-algorithm, they are all equal. Only the time they take for sorting the field is different, but the result is always the same).
The problem in your algorithm is that you don't check whether the compared characters are vowels or upper/lower case.
This code should work:
public class StringSorter {
private static final String vowels = "aeiou";
public static void main(String[] args) {
char[] string = "thisIsAString".toCharArray();
char[] test2 = "thisIsAStringaAabBs".toCharArray();
System.out.println("unsorted: " + new String(string));
insertionSort(string);
System.out.println("sorted: " + new String(string));
System.out.println();
System.out.println("unsorted: " + new String(test2));
insertionSort(test2);
System.out.println("sorted: " + new String(test2));
}
public static void insertionSort(char[] string) {
for (int i = 1; i < string.length; i++) {
char h = string[i];
int j = i;
while ((j > 0) && isBefore(string[j - 1], h)) {
string[j] = string[j - 1];
j = j - 1;
}
string[j] = h;
}
}
private static boolean isBefore(char a, char b) {
String lowA = Character.toString(Character.toLowerCase(a));
String lowB = Character.toString(Character.toLowerCase(b));
if (vowels.contains(lowA)) {
if (vowels.contains(lowB)) {
//both are vowels
return chooseLowerCaseFirst(a, b);
}
else {
//only a is a vowel
return false;
}
}
else if (vowels.contains(lowB)) {
//only b is a vowel
return true;
}
else {
//none is a vowel
return chooseLowerCaseFirst(a, b);
}
}
private static boolean chooseLowerCaseFirst(char a, char b) {
String lowA = Character.toString(Character.toLowerCase(a));
String lowB = Character.toString(Character.toLowerCase(b));
if (lowA.equals(lowB)) {
//both are the same character
if (Character.isLowerCase(a)) {
if (Character.isLowerCase(b)) {
//both are lower case
return Character.toLowerCase(a) > Character.toLowerCase(b);
}
else {
//only a is lower case
return false;
}
}
else if (Character.isLowerCase(b)) {
//only b is lower case
return true;
}
else {
//both are upper case
return Character.toLowerCase(a) > Character.toLowerCase(b);
}
}
else {
//different characters
return Character.toLowerCase(a) > Character.toLowerCase(b);
}
}
}
The output that is generated is:
unsorted: thisIsAString
sorted: AiiIghnrssStt
unsorted: thisIsAStringaAabBs
sorted: aaAAiiIbBghnrsssStt
If you are considering other methods too, from Java 8 you can do it by mixing streams and comparators.
import java.util.*;
import java.util.stream.Collectors;
public class Main {
private static List<Character> order = new ArrayList<>(Arrays.asList('a', 'A', 'e', 'E', 'i', 'I', 'o', 'O', 'u', 'U', 'b', 'B', 'c', 'C', 'd', 'D', 'f', 'F', 'g', 'G', 'h', 'H', 'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N', 'p', 'P', 'q', 'Q', 'r', 'R', 's', 'S', 't', 'T', 'v', 'V', 'w', 'W', 'x', 'X', 'y', 'Y', 'z', 'Z'));
public static void main(String[] args) {
String example = "thisIsAString";
List<Character> cl = example.chars().mapToObj(c -> (char) c).collect(Collectors.toList());
List<Character> ls = cl.stream().sorted(Comparator.comparingInt(order::indexOf)).collect(Collectors.toCollection(ArrayList::new));
StringBuilder result = new StringBuilder();
for (Character c : ls) result.append(c);
System.out.println(result);
}
}
import java.util.Scanner;
import java.lang.*;
public class testing {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
char[] engArray = {'A','B','C','D','E','F','G','H','I'};
String stringEngArray = String.valueOf(engArray);
System.out.println("Text input");
String input2 = input.nextLine().toUpperCase();
int inputedOffset = 4;
char[] finalArray = inpute2.toCharArray();
for (int i = 0; i < inputedText.length(); i++) {
int arrayPosition = inpute2.indexOf(inputedText.charAt(i));
int engPosition = stringEngArray.indexOf(inputedText.charAt(i));
int test = (arrayPosition % inputedOffset);
int newTest = engPosition+test;
finalArray[i] = engArray[newTest];
}
String output = new String(finalArray);
System.out.println(output);
}
}
I am trying to change the inputted by user text in order to accomplish some basic encryption.
When i enter abcd or tesla or world the output works as expected and is changing to aceg to tfuoa to wptod
The problem occurs when i am entering aaaa or aabbcc or generally when a letter is repeated on the text. At the second time the for loop finds the same letter it just uses the array position of the 1st read similar letter.
Any idea?
This happens because inputedText.indexOf(inputedText.charAt(i));, this is what's causing it to return the same index, since it will just grab the first occurance of a which will be the same for every a character.
You're trying to get the array position, but why are you doing it this way when the arrayposition is already the variable i?
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
char[] engArray = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
String stringEngArray = String.valueOf(engArray);
System.out.println("Text input");
String inputedText = input.nextLine().toUpperCase();
int inputedOffset = 4;
char[] finalArray = inputedText.toCharArray();
for (int i = 0; i < inputedText.length(); i++) {
int engPosition = stringEngArray.indexOf(inputedText.charAt(i));
int test = (i % inputedOffset);
int newTest = engPosition + test;
finalArray[i] = engArray[newTest];
}
String output = new String(finalArray);
System.out.println(output);
}
You are using indexOf() to get the arrayposition. This will always return the position of the first occurrence of that character in the string.
You can simply use i as the arrayposition.
I'm trying to print the alphabet in order using threads. I got the letters printing but I'm having trouble getting them in the right order.
So I'm getting something like B,A,D,C
Is there a way to enforce the order of execution? I want thread 1 to go then wait, then thread 2, etc and then loop around again
Here is what I have:
public class Letters {
public static void main(String[] args) {
char[] arr1 = new char[]{'A', 'E', 'I', 'M', 'Q', 'U', 'Y'};
char[] arr2 = new char[]{'B', 'F', 'J', 'N', 'R', 'V', 'Z'};
char[] arr3 = new char[]{'C', 'G', 'K', 'O', 'S', 'W'};
char[] arr4 = new char[]{'D', 'H', 'L', 'P', 'T', 'X'};
mythread c1 = new mythread(arr1);
mythread c2 = new mythread(arr2);
mythread c3 = new mythread(arr3);
mythread c4 = new mythread(arr4);
Thread t1 = new Thread (c1);
Thread t2 = new Thread (c2);
Thread t3 = new Thread (c3);
Thread t4 = new Thread (c4);
t1.start();
t2.start();
t3.start();
t4.start();
}
static class mythread extends Thread{
char arr []; //= {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
mythread () {};
mythread (char [] x) {
this.arr = x; // .arrcopy didn't work
}
public void run () {
try {
printletters(arr);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized void printletters(char [] arr) throws InterruptedException {
int q = 0;
for(int count = 0 ; count < arr.length; count++) {
System.out.println(arr[count]);
wait(10);
q++;
if(q >= 4) {
notifyAll();
q = 0;
}
}
}
}
To offer something other than what is already in the comments, here is a basic way to ensure that your threads run in order and will demonstrate one way to create custom synchronizers. A synchronizer is a means of controlling execution between threads.
There are many ways to solve this problem. For simplicity, 4 synchronization objects will be used. Each thread will 'block' on it's predecessor thread, print a letter, and when complete 'signal' its successor thread. The blocking and signalling is achieved by the synchronizer.
Here is the Synchronizer:
public class TSync {
private final Lock lock = new ReentrantLock();
private final Condition previousThreadDone = lock.newCondition();
private boolean ready = false; // Guarded by lock
public void waitForPreviousThread() throws InterruptedException {
lock.lock();
try {
while (!ready)
previousThreadDone.await();
ready = false;
} finally {
lock.unlock();
}
}
public void signalNextThread() {
lock.lock();
try {
ready = true;
previousThreadDone.signal();
} finally {
lock.unlock();
}
}
}
And now your Letters class which now uses the TSync class to co-ordinate the execution flow:
public class Letters {
public static void main(String[] args) {
char[] arr1 = new char[] { 'A', 'E', 'I', 'M', 'Q', 'U', 'Y' };
char[] arr2 = new char[] { 'B', 'F', 'J', 'N', 'R', 'V', 'Z' };
char[] arr3 = new char[] { 'C', 'G', 'K', 'O', 'S', 'W' };
char[] arr4 = new char[] { 'D', 'H', 'L', 'P', 'T', 'X' };
TSync sync1 = new TSync();
TSync sync2 = new TSync();
TSync sync3 = new TSync();
TSync sync4 = new TSync();
Mythread c1 = new Mythread(arr1, sync1, sync2);
Mythread c2 = new Mythread(arr2, sync2, sync3);
Mythread c3 = new Mythread(arr3, sync3, sync4);
Mythread c4 = new Mythread(arr4, sync4, sync1);
Thread t1 = new Thread(c1);
Thread t2 = new Thread(c2);
Thread t3 = new Thread(c3);
Thread t4 = new Thread(c4);
t1.start();
t2.start();
t3.start();
t4.start();
System.out.println("Signalling Thread 1 is ready to work");
sync1.signalNextThread();
}
}
class Mythread extends Thread {
private final char[] arr;
private final TSync waitOnSync;
private final TSync signalSync;
public Mythread(char[] arr, TSync waitOnSync, TSync signalSync) {
super();
this.arr = arr;
this.waitOnSync = waitOnSync;
this.signalSync = signalSync;
}
#Override
public void run() {
boolean isInterrupted = false;
for (int i=0; i<arr.length && !isInterrupted; i++) {
try {
waitOnSync.waitForPreviousThread();
System.out.println(arr[i]);
signalSync.signalNextThread();
} catch (InterruptedException e) {
isInterrupted = true;
}
}
}
}
Now the alphabet will print in order (i.e. the synchronizers have ensured that each thread will run in the order you wish).
This question already has answers here:
Java recursion phone number letters
(5 answers)
Closed 7 years ago.
I know this question has been asked a hundred times but I am looking for a solution that does not involve any String functions or external classes.
I have written a few classes that actually work but they all use String.substring or String.replace, Arraylists etc. which is not allowed in my situation.
I have been on this for more than a week now and I can't seem to get any progress.
I just can't put String methods in a very big loop or something.
Any ideas?
Here is what I have written up until now.
public class Oldie {
public static void main(String[] args) {
char[][] array = {
{ '0' }, { '1' }, { 'A', 'B', 'C' }, { 'D', 'E', 'F' },
{ 'G', 'H', 'I' }, { 'J', 'K', 'L' }, { 'M', 'N', 'O' },
{ 'P', 'Q', 'R', 'S' }, { 'T', 'U', 'V' }, { 'W', 'X', 'Y', 'Z' }
};
String num = "222";
int[] number = new int[num.length()];
char[] permutations = new char[num.length()];
for (int i = 0; i < num.length(); i++) {
number[i] = Character.getNumericValue(num.charAt(i));
}
char First, Second, Third;
for (char i = array[number[0]][0]; i <= array[number[0]][array[number[0]].length - 1]; i++) {
First = i;
for (char j = array[number[1]][0]; j <= array[number[1]][array[number[1]].length - 1]; j++) {
Second = j;
for (char k = array[number[2]][0]; k <= array[number[2]][array[number[2]].length - 1]; k++) {
Third = k;
System.out.println("" + First + "" + Second + "" + Third);
}
}
}
}
}
It would be better if I could do it in a base type solution with redix etc.
I am not quite sure, what you mean with your loops, but when you fix it, this should be another solution without saving the String (right now this throws an "java.lang.ArrayIndexOutOfBoundsException" since i dont right understand, what you want to accomplish with your for-loops). This code should be more considered as an hint how to solve your problem and not the full solution! This also kind of saves old Strings. Instead you could also delete the last char of the String at the end of each for-loop:
public class Oldie {
char[][] array = {
{ '0' }, { '1' }, { 'A', 'B', 'C' }, { 'D', 'E', 'F' },
{ 'G', 'H', 'I' }, { 'J', 'K', 'L' }, { 'M', 'N', 'O' },
{ 'P', 'Q', 'R', 'S' }, { 'T', 'U', 'V' }, { 'W', 'X', 'Y', 'Z' }
};
String num = "222";
String savedPerm;
int[] number = new int[num.length()];
public static void main(String[] args) {
Oldie oldie = new Oldie();
oldie.givePerm(0);
}
Oldie(){
for (int i = 0; i < num.length(); i++) {
number[i] = Character.getNumericValue(num.charAt(i));
}
}
private void givePerm(int position){
String oldSavedPerm=savedPerm;
// if(array.length!=number.length){
// System.out.println("Different length!");
// System.out.println(array.length+";"+number.length);
// return;
// }
for (char c = array[number[position]][0]; c <= array[number[position]][array[number[position]].length - 1]; c++) {
savedPerm=c+oldSavedPerm;
if(position<array.length-1)
givePerm(position+1);
else
System.out.println(savedPerm);
}
}
}
Here is my approach on your problem.
char[][] array = {
{ '0' }, { '1' }, { 'A', 'B', 'C' }, { 'D', 'E', 'F' },
{ 'G', 'H', 'I' }, { 'J', 'K', 'L' }, { 'M', 'N', 'O' },
{ 'P', 'Q', 'R', 'S' }, { 'T', 'U', 'V' }, { 'W', 'X', 'Y', 'Z' }
};
String num = "123";
// creates an combination Array
// for 123 this is {{1},{ABC},{DEF}}
char[][] combinationArr = new char[num.length()][];
for(int ix = 0; ix < num.length(); ix++)
combinationArr[ix] = array[Character.getNumericValue(num.charAt(ix))];
// now print all permutations of combination Array
// ics holds the actual index at each position
int[] ics = new int[num.length()];
boolean end = false;
while(!end){ // while there are combinations left
// print the actual combination
for(int i = 0; i < combinationArr.length; i++)
System.out.print(combinationArr[i][ics[i]]);
System.out.println();
// increases one index, starting with the last one.
// If there is no char left it starts again at 0
// and the index before will get increased.
// If the first one could not get increased
// we have all combinations.
for(int i = ics.length - 1; i >= 0; i--){
ics[i]++;
if(ics[i] == combinationArr[i].length)
if(i == 0) end = true;
else ics[i] = 0;
else break;
}
}
Here is what actually worked for me!! Thanks to ctst!
public class Oldie {
private static char[][] array = { { '0' }, { '1' }, { 'A', 'B', 'C' }, { 'D', 'E', 'F' },
{ 'G', 'H', 'I' }, { 'J', 'K', 'L' }, { 'M', 'N', 'O' },
{ 'P', 'Q', 'R', 'S' }, { 'T', 'U', 'V' }, { 'W', 'X', 'Y', 'Z' } };
private static String num = "2222";
private static char[] savedPerm = new char[num.length];
private static int[] number = new int[num.length()];
public static void main(String[] args) {
for (int i = 0; i < num.length(); i++) {
number[i] = Character.getNumericValue(num.charAt(i));
}
givePerm(0);
}
private static void givePerm(int position) {
for (char c = array[number[position]][0]; c <= array[number[position]][array[number[position]].length - 1]; c++) {
savedPerm[position] = c;
if (position < number.length - 1)
givePerm(position + 1);
else{
for(char text: savedPerm){
System.out.print(""+text);
}
System.out.println();
}
}
}
}
I would suggest you to make a recursive method:
private String givePerm(String givenPerm, char[][] array, int position, int[] number){
if(array.length!=number.length)
return null;
for (char c = array[number[position]][0]; c <= array[number[position]][array[number[position]].length - 1]; c++) {
String permString;
if(position<array.length-1)
permString = givePerm(c+givenPerm, array, position+1);
else
permString = ""+c;
return permString;
}
}
Using recursion, you can call the permutations method and keep on reducing the the number of input digits, by grabbing the head digit and passing the tail into the next call.
public class Oldie {
private static final char[][] KEYS = {
{ '0' },
{ '1' }, { 'A','B','C' }, { 'D','E','F' },
{ 'G','H','I' }, { 'J','K','L' }, { 'M','N','O' },
{ 'P','Q','R','S' }, { 'T','U','V' }, { 'W','X','Y','Z' }
};
public static void main(String[] args) {
try {
permutations("222");
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
public static void permutations(String inputNumber) throws IllegalArgumentException {
permutations(toDigitArray(inputNumber), "");
}
private static void permutations(int[] inputDigits, String outputLetters) throws IllegalArgumentException {
int headDigit = inputDigits[0];
int[] tailDigits = tail(inputDigits);
char[] letters = KEYS[headDigit];
for (int i = 0; i < letters.length; i++) {
char letter = letters[i];
String result = outputLetters + letter;
if (tailDigits.length == 0) {
System.out.println(result);
} else {
permutations(tailDigits, result);
}
}
}
private static int[] toDigitArray(String str) throws IllegalArgumentException {
return toDigitArray(str.toCharArray());
}
private static int[] toDigitArray(char[] arr) throws IllegalArgumentException {
int[] intArr = new int[arr.length];
for (int i = 0; i < intArr.length; i++) {
if (!Character.isDigit(arr[i])) {
throw new IllegalArgumentException("Character is not a valid digit");
}
intArr[i] = Character.digit(arr[i], 10);
}
return intArr;
}
private static int[] tail(int[] arr) {
int[] dest = new int[arr.length - 1];
System.arraycopy(arr, 1, dest, 0, dest.length);
return dest;
}
}
Output
AAA
AAB
AAC
ABA
ABB
ABC
ACA
ACB
ACC
BAA
BAB
BAC
BBA
BBB
BBC
BCA
BCB
BCC
CAA
CAB
CAC
CBA
CBB
CBC
CCA
CCB
CCC
i am trying to solve this question
https://www.hackerrank.com/challenges/pangrams
and here's my code
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
public class Pangram {
public static String alltrim(String s)
{ String s1="";
int i,j,k=0;
for(i=0;i<s.length();i++)
{
char ch=s.charAt(i);
if(ch!=' ')
break;
}
for(j=s.length()-1;j>=0;j--)
{
char ch=s.charAt(j);
if(ch!=' ')
break;
}
for(k=i;k<j+1;k++)
s1 = s1 + s.charAt(k);
return s1;
}
public static void main(String[] args)
{
Scanner reader = new Scanner(System.in);
String input = reader.nextLine();String s,s1;
s = input.toLowerCase();
s1 = alltrim(s);
if( check(s1) )
System.out.println("pangram");
else
System.out.println("not pangram");
}
public static boolean check(String input)
{
int [] count = new int[26];
for( int i = 0; i < input.length(); i++ )
{
char ch = input.charAt(i);
count[ch-'a']++;
}
for( int cnt:count )
{
if( cnt ==0 )
return false;
}
return true;
}
}
i always get this error
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -65
at Pangram.check(Pangram.java:46)
at Pangram.main(Pangram.java:35)
i am trying to find out where the problem is but i coudn't ... can anyone help me?
Here's one way
public static void main(final String[] args) throws IOException {
Scanner reader = new Scanner(System.in);
String line = reader.nextLine();
// Verify input argument length.
final char[] allCharacters = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
final TreeSet<Character> charactersPresent = new TreeSet<Character>();
// Parse the line into letters.
final char[] letters = line.toLowerCase().toCharArray();
// Keep a set of those that are present.
for (final char letter : letters) {
charactersPresent.add(letter);
}
// Print the letters present in the alphabet but not in the input.
final StringBuilder missingLettersBuilder = new StringBuilder();
for (final char character : allCharacters) {
if (!charactersPresent.contains(character)) {
missingLettersBuilder.append(character);
}
}
if (missingLettersBuilder.length() == 0) {
System.out.println("This is a PANGRAM");
} else {
System.out.println("Not a PANGRAM because it doesn't have "+missingLettersBuilder.toString());
}
}
The problem is in
count[ch-'a']++;
where ch is 6(as you entered) and you are subtracting '6'-'1' so its generating a value by subtracting the ASCII values and give
count[-43]++;
The java.lang.ArrayIndexOutOfBoundsException: -65 happen because you subtract a(97) to a space character which is represented by 32 in the ASCII table (32-97=-65).
Which mean that the problem is in your allTrim method which does not replace all spaces as you probably expected.
If you want to replace all spaces of your string, you can use the replaceAll method of String.
Discard the s1 = alltrim(s); line and replace it by s1 = s.replaceAll(" ", "");.
Now entering the input you gave me in comments
aaabbb ab abc mnop xyyx xaxbbbxx
Won't give any exception.
As for the other exception you had (out of bound -43), it is simply because you entered
6 aaabbb ab abc mnop xyyx xaxbbbxx
6 is represented by 54 in the ASCII table, 54-97 = 43. Looking at the requirement on the link you gave us, you should only compare alphabetical letter so I suppose this is a mistake.
Note that you can easily remove all number of a String, your replace line would become :
s1 = s.replaceAll(" ", "").replaceAll("\\d", "");
Now it would not give any error even when entering
6 aaabbb ab abc mnop xyyx xaxbbbxx