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);
}
}
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
}
}
}
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.
This program is supposed to translate English into morse code, but every time i input a word I get English letters and numbers such as "\cf0" for hi. I am pretty sure the morse code array has the right values. Could it be a formatting problem? PLease help. thanks.
MorseCode class
public class MorseCode {
public static String decode(char[] alphabet, String[] morseCode, String originalMessage) {
char currentChar;
String getMorseChar;
String convertedString = " ";
for (int i = 0; i < originalMessage.length(); i++) {
convertedString = " ";
currentChar = originalMessage.charAt(i);
getMorseChar = convert(currentChar, alphabet, morseCode);
convertedString = convertedString + getMorseChar;
}
return convertedString;
}
public static String convert (char currentChar, char[] alphabet, String[] morseCode) {
String morse = "";
for (int x = 0; x < alphabet.length; x++) {
if (currentChar == alphabet[x])
morse = morseCode[x];
}
return morse;
}
}
MorseCodeTester class
public class MorseCodeTester {
public static void main(String[] args) throws IOException {
String[] morseCode = new String[26];
char[] alphabet = { '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' };
Scanner scanner = new Scanner(System.in);
Scanner inFile = new Scanner(new File("morse.rtf"));
for (int x = 0; x < 26; x++) {
morseCode[x] = inFile.next( );
}
inFile.close();
System.out.println("What message would you like to translate?");
String originalMessage = scanner.next();
String converted = MorseCode.decode(alphabet, morseCode, originalMessage);
System.out.println(converted);
}
}
I have a list of 75200 words. I need to give a 'unique' id to each word, and the length of each id could be 3 letters or less. I can use numbers, letters or even symbols but the max length is 3.
Below is my code.
import java.io.*;
import java.util.*;
public class HashCreator {
private Map completedWordMap;
private String [] simpleLetters = {"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 String[] symbols = {"!","#","#","$","%","^","&","*","~","?"};
private String indexNumber;
String currentlyUsingLetter, currentlyUsingSymbol;
private int currentlyActiveSimpleLetter = 0, currentlyActiveSymbol = 0, currentlyActiveSimpleLetter2 = 0, currentlyActiveSymbol2 = 0;
private boolean secondaryNumberIsHundred = false;
public HashCreator()
{
completedWordMap = createWordNumberingMap();
}
private Map createWordNumberingMap()
{
int number = 0;
int secondaryNumber = 0;
int thirdinoryNumber = 0;
Map wordMap = new HashMap();
BufferedReader br = null;
String str = "";
boolean reset = false;
//First Read The File
File readingFile = new File("WordList/NewWordsList.txt");
try
{
br = new BufferedReader(new FileReader(readingFile));
while((str=br.readLine())!=null)
{
if(number<1000) //Asign numbers from 0 t0 999
{
indexNumber = String.valueOf(number);
wordMap.put(indexNumber, str);
number++;
System.out.println(indexNumber);
}
else // It is 1000 now. Length exceeds so find another way.
{
if(indexNumber.length()<4)
{
if(currentlyActiveSimpleLetter<simpleLetters.length) //Start using simple letter array
{
if(secondaryNumber<100) //Start combining numbers with letters. Results will look like 'a0', a1', 'a2'......'x98',x99'
{
indexNumber = simpleLetters[currentlyActiveSimpleLetter]+secondaryNumber;
wordMap.put(indexNumber, str);
secondaryNumber++;
System.out.println(indexNumber);
}
else
{
//If the number is 100, that means the last result is something like 'a99','b99'...'x99'
//Time to use a new letter and set the counter back to 0 and select the next letter
secondaryNumber = 0;
currentlyActiveSimpleLetter++;
}
}
else
{
if(currentlyActiveSymbol<symbols.length) //We have used the entire alphabet. Start using sybmols now.
{
if(currentlyActiveSymbol==0) //If this is the first time we are reaching this step, reset the counter to 0
{
secondaryNumber = 0;
}
if(secondaryNumber<100)
{
indexNumber = symbols[currentlyActiveSymbol]+secondaryNumber;
wordMap.put(indexNumber, str);
secondaryNumber++;
System.out.println(indexNumber);
}
else
{
//If the number is 100, that means the last result is something like '!99','#99'...'*99'
//Time to use a new letter and set the counter back to 0 and select the next symbol
secondaryNumber = 0;
currentlyActiveSymbol++;
}
}
else
{
//We have used entire list of numbers (0-999), entire list of letters (a0-z99) and entire set of symbols (!0 - ?99)
//Now we need to combine all 3 together.
if(thirdinoryNumber<10)//We are starting with a new 'Number' counter
{
//We again start with replacing numbers. Here the first few and last few results will look like a!0'.....'a!9'
indexNumber = simpleLetters[currentlyActiveSimpleLetter2]+symbols[currentlyActiveSymbol]+thirdinoryNumber;
wordMap.put(indexNumber, str);
thirdinoryNumber++;
System.out.println(indexNumber);
thirdinoryNumber++;
}
else
{
//We have used number from 0-9. Time to start replacing letters
if(currentlyActiveSimpleLetter2<simpleLetters.length)
{
if(currentlyActiveSimpleLetter2==0) //If this is the 'first' time we reach this point, reset the number counter.
{
thirdinoryNumber = 0;
}
if(thirdinoryNumber<10)
{
indexNumber = simpleLetters[currentlyActiveSimpleLetter2]+symbols[currentlyActiveSymbol]+thirdinoryNumber;
wordMap.put(indexNumber, str);
thirdinoryNumber++;
System.out.println(indexNumber);
}
else
{
thirdinoryNumber = 0;
currentlyActiveSimpleLetter2++; //If we are at the peek of usable numbers (0-9) reset simpleletter array position to
// 0 and numbercounter to 0
}
}
else
{
//We have used number from 0-9. Time to start replacing symbols
if(currentlyActiveSymbol2<symbols.length)
{
if(currentlyActiveSymbol2==0) //If this is the 'first' time we reach this point, reset the number counter.
{
thirdinoryNumber = 0;
}
if(thirdinoryNumber<10)
{
indexNumber = simpleLetters[currentlyActiveSimpleLetter2]+symbols[currentlyActiveSymbol]+thirdinoryNumber;
wordMap.put(indexNumber, str);
thirdinoryNumber++;
System.out.println(indexNumber);
}
else
{
thirdinoryNumber = 0;
currentlyActiveSymbol2++; //If we are at the peek of usable numbers (0-9) reset symbol array position to
// 0 and numbercounter to 0
}
}
}
}
}
}
}
else
{
System.out.println("Error in Somewhere. Length Exceeded");
}
}
}
br.close();
System.out.println("Completed");
System.out.println(wordMap.get(0));
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
try
{
br.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
return wordMap;
}
}
Unfortunately this doesn't work. It prints the results, and it is bunch of !0 after the result 'z99'. Below is a small piece of it:
!0
!0
!0
!0
...
Completed
null
Apart from that, after k99, it has generated ids from 10-199 then started back with m0 properly. You can find the result file from here.
As you can see, wordMap.get(0) also generated null. What is wrong here? If there is any other simple method for generating 75000 unique ids with maximum 3 digits/letters/symbols length, I am more than happy to move with it.
Here is generator with enough IDs.
public class Main {
private char[] A;
void init()
{
A = new char[] {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'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',
'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'
};
System.out.println("digits = " + A.length);
//for (int i = 0; i < A.length; i++)
// System.out.print(A[i] + " ");
//System.out.println();
}
public void generate(int length, String id)
{
if (length == 3) {
System.out.println(id);
} else {
for (int i = 0; i < A.length; i++)
generate(length + 1, id + A[i]);
}
}
public static void main(String[] args) {
Main test = new Main();
test.init();
test.generate(0, "");
}
}
The number of unique IDs is (26 + 26 + 10) ^ 3 = 62^3 = 238328.
Obviously you need to adapt it to fit your particular problem.
Actually only 43 characters are needed since 43 ^ 3 = 79507 > 75200.
EDIT: Explanation of the generate() method.
This method implements a recursive algorithm to generate combinations of characters (the keys). The meaning of the parameters is the following:
length The length of the key.
id stores the combination of characters.
The following picture can help to understand the algorithm.
This is similar to how the decimal (or any other base) numbers are formed.
A thing that I don't noticed is that you are trying to first create all the possible keys of length 1, then all possible keys of length 2, and so on. My generator creates keys of exactly 3 character only. That behavior can be achieved modifying the generate() method as follows:
public void generate(int count, String id)
{
if (count == 0) {
System.out.println(id);
} else {
for (int i = 0; i < A.length; i++)
generate(count - 1, id + A[i]);
}
}
And then call the method tree times:
test.generate(1, "");
test.generate(2, "");
test.generate(3, "");
Some keys contains leading zeros but that shouldn't be a problem since this keys are identifiers, not numbers. The number of possible keys increases by length(alphabet) + length(alphabet) ^ 2, i.e. we have 62 + 62^2 additional keys.
Since the length of the key is at most 3 the iterative version can be easily implemented using for loops:
public void iterative_generator()
{
for (int i = 0; i < A.length; i++) {
for (int j = 0; j < A.length; j++) {
for (int k = 0; k < A.length; k++) {
System.out.println("" + A[i] + A[j] + A[k]);
}
}
}
}
I think you get the idea.
You could create a method that basically converts a decimal number to a base of your choice. Here I have 46 symbols for example, which gives 97336 unique sequences:
private static final String[] symbols = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "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 String getSequence(final int i) {
return symbols[i / (symbols.length * symbols.length)] + symbols[(i / symbols.length) % symbols.length]
+ symbols[i % symbols.length];
}
(Posted on behalf of the question author).
This is how I wrote my code according to the answer of Stack Overflow user "Keppil".
import java.io.*;
import java.util.*;
public class HashCreator
{
private Map completedWordMap;
private String[]simpleLetters = {"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 char[] A;
private static final String[] symbols = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "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 HashCreator()
{
for(int i=0;i<75001;i++)
{
System.out.println(getSequence(i));
}
}
public static String getSequence(final int i) {
return symbols[i / (symbols.length * symbols.length)] + symbols[(i / symbols.length) % symbols.length]
+ symbols[i % symbols.length];
}
}