Java – Exam – Congate Words
Some time ago, to be more honest last Sunday, I participated at some Java exam again. The results were not something to boast, quite on the contrary, but I did not have a lot of time to prepare 🙂 The contest was hosted by the SoftUni and the tasks were quite tough. At least this time I knew how to debug in Eclipse, so I did not waste time to learn it 🙂
The Java problem, which I had to resolve was concerning words.
Pretty much, you have a string as input where you should consider all the latin characters as words. You should return all triples, in which two words together make a third one. It is probably better to see the original examples in order to understand:
Yup, I am probably the only person in the world, who knows enough HTML to format a table and still prefers to make a screenshot of it. Pretty much, I managed to resolve the problem after some time. This was my approach:
- I read the string;
- I replaced everything, which is not a latin character with a space (with a Regex 🙂 );
- In order to avoid some misunderstanding, if there were some places with more than one space, I replaced them with one space;
- I split by the space to make a string array;
- Then came the real part – I started three loops, which gave me values for a , b and c;
- Then I made the check for the condition;
- I wrote the solution in one ArrayList;
- I checked the frequency of my solution in the ArrayList;
- If the frequency was 1, I printed it;
- If I printed anything, I increased the counter plus one;
- At the end I made a check whether the counter is 0, in order to print “No” if true;
Here is the outstanding code:
import java.util.*;
public class CognateWords {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String Normal = input.nextLine();
String MoreNormal = Normal.replaceAll("[^A-Za-z]", " ");
String SuperNormal = MoreNormal.replaceAll("[ ]+", " ");
String[] numsStr = SuperNormal.split(" ");
int Counter = 0;
ArrayList ar = new ArrayList();
int myCount = 0;
for (int k = 0; k < numsStr.length; k++) {
for (int i = 0; i < numsStr.length; i++) {
for (int z = 0; z < numsStr.length; z++) {
String a = numsStr[k];
String b = numsStr[i];
String c = numsStr[z];
if ((a + b).equals(c)) {
String myString = a + "|" + b + "=" + c;
ar.add(myString);
for (String sA : ar) {
myCount = Collections.frequency(ar, sA);
}
if (myCount == 1) {
System.out.println(myString);
Counter++;
}
}
}
}
}
if (Counter == 0) {
System.out.println("No");
}
}
}
Pretty much I could have reduced a pair of lines, but I really thing it is a smooth decision.
The original solution was a bit better:
- It used HashSet<String> – thus, you do not have to check whether the value is unique or not;
- The reading of the first line and the split into an array is done in one line;
- I like the way the boolean check is declared and given value;
- Also, the original solution works with less variables, thus it should be faster;
Pretty much, this is how it looks like:
import java.util.Scanner;
import java.util.HashSet;
public class CognateWords {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] words = sc.nextLine().split("[^a-zA-Z]+");
HashSet cognateWords = new HashSet<>();
for (int a = 0; a < words.length; a++) {
for (int b = 0; b < words.length; b++) {
for (int c = 0; c < words.length; c++) {
// Check if a!=b and a|b=c
if (a != b) {
boolean check = (words[a] + words[b]).equals(words[c]);
if (check) {
cognateWords.add(words[a] + "|" + words[b] + "=" + words[c]);
}
}
}
}
if (cognateWords.isEmpty()) {
System.out.println("No");
} else {
for (String cognate : cognateWords) {
System.out.println(cognate);
}
}
}
}
Enjoy it responsibly! 😀

