Find shortest text containing all combinations of a given string - java

Given a string, find another string which contains all the combinations of the input string.
Example:
If input string = "23", then its combinations would be ["22", "23", "32", "33"],
One of the strings to contain all the above combinations would be "22233233", but that would not be the shortest. The shortest would be "22332".
Algorithm should be generic enough to work for input string of any size. (Assume that input is not too large and the output will remain under normal int/string/jvm etc. sizes. Also assume that input string will have alphanumeric characters from English language only)
I have tried the following algorithm but it does not seem to be working:
1) Find all combinations of the string = ["22", "23", "32", "33"]
2) Build a prefix map [2: {22, 23}, 3: {32, 33}]
3) Start from any combination and lookup suffix in the prefix map.
Example: Start with 22, its suffix is 2
From the prefix-map, values corresponding 2 are 22 and 23.
Pick one of the words here which is not the current picked word, so it will give 23
4) Add picked word's suffix to current string (This gives 223)
5) Repeat.
So I will get 223's suffix = 3
From prefix map, 3: {32, 33}
Choose any one, say 32
Append to current string to get 2232
6) If nothing else matches, append to current string. This gives 223233
However, the answer should be 22332 as that is the shortest.
Here is the full code I have written till now:
public class TextContainingAllPermutations
{
static String input = "ABC";
public static void main (String args[])
{
int suffixLen = input.length()-1;
Set<String> combinations = getCombinations();
while (suffixLen > 0 && combinations.size() > 1)
{
Map<String, List<String>> suffixToWords = getPrefixMap(combinations, suffixLen);
String someWordsString = combinations.iterator().next();
combinations.remove(someWordsString);
Set<String> combinations2 = new HashSet<String>();
while (combinations.size() > 0)
{
String suffix = someWordsString.substring(someWordsString.length()-suffixLen);
List<String> words = suffixToWords.get(suffix);
if (words == null || words.size()==0)
{
combinations2.add(someWordsString);
System.out.println (someWordsString);
if (combinations.size() == 0)
break;
someWordsString = combinations.iterator().next();
combinations.remove(someWordsString);
}
else
{
String w = words.get(words.size()-1);
words.remove(words.size()-1);
combinations.remove(w);
if (someWordsString.indexOf(w) == -1)
someWordsString += w.charAt(w.length()-1); // append last char
}
}
combinations2.add(someWordsString);
System.out.println (someWordsString);
combinations = combinations2;
suffixLen--;
}
}
private static Map<String, List<String>> getPrefixMap(Set<String> combinations, int suffixLen)
{
Map<String, List<String>> suffixToWords = new HashMap<String, List<String>>();
for (String s: combinations)
{
String suffix = s.substring(0,suffixLen);
if (!suffixToWords.containsKey(suffix))
{
suffixToWords.put(suffix, new ArrayList<String>());
}
suffixToWords.get(suffix).add(s);
}
return suffixToWords;
}
static Set<String> getCombinations()
{
char[] inputChars = input.toCharArray();
int N = (int)Math.pow(input.length(), input.length());
Set<String> combinations = new HashSet<String>(N);
for (int i=0; i<N; i++)
{
char[] binary = padZeroes(Integer.toString(i, input.length())).toCharArray();
String combination = "";
for (int j=0; j<inputChars.length; j++)
{
char c = binary[j];
int index = c - '0';
char inputChar = inputChars[index];
combination = inputChar + combination;
}
System.out.println (new String(binary) + " = " + combination);
combinations.add(combination);
}
return combinations;
}
private static String padZeroes(String s)
{
int j = input.length()-s.length();
for (int i=0; i<j; i++)
s = '0' + s;
return s;
}
}
This is not a homework problem.

What you are looking for is basically a De Bruijn sequence. A De Bruijn sequence B(k,n) is a cyclic sequence which contains all the possible subsequences of length n from a set of k symbols, each appearing exactly once. The length of the sequence is precisely kn.
The minimal non-cyclic sequence can be obtained by breaking the cycle at any point and then copying the first n-1 symbols to the end, producing a sequence of length kn + n - 1, which is obviously minimal.
There are a variety of techniques to generate a De Bruijn sequence. The simplest technique to describe is that the de Bruijn sequence consists of the concatenation of all the Lyndon words over the alphabet whose length divides n, in lexicographic order. (A Lyndon word is a sequence which is lexicographically previous to any rotation of itself. This implies that the Lyndon word is aperiodic.)
There is a simple algorithm to generate Lyndon words of maximum length n over an alphabet in lexicographic order:
Start with the length consisting of only the lexicographically first character in the set.
As long as possible, form the next word by cyclically repeating the previous word up to length n (discarding the extra symbols from the last repetition, if necessary) and then "incrementing" the word by:
As long as the last symbol in the word is the lexicographically greatest symbol in the alphabet, remove it.
If there is still a symbol in the word, change the last symbol to the lexicographical successor. If there are no symbols left in the word, the production is finished.
To make the De Bruijn sequence of order n, we produce the above sequence of Lyndon words, but we only keep the ones whose length divides n. Since "almost all" of the Lyndon words of maximum length n are actually of length n, the algorithm can be considered O(1) per symbol, or O(kn) for the full sequence.
In the specific case requested by the question, k == n.

Related

(Java) How do you check a string for two or more digit integers using .matches()?

The objective of this program is to return the atomic mass from a given formula (as a String), using a CSV file that contains elements and their atomic masses.
My code for this particular problem is this:
double mass = 0.0;
Map<String, Double> perTableMap = fileReader(periodicTable);
Map<String, Integer> atomMap = getAtoms(formula);
for (Map.Entry<String, Double> periEntry : perTableMap.entrySet()) {
for (Map.Entry<String, Integer> atomEntry : atomMap.entrySet()) {
if (atomEntry.getKey().equals(periEntry.getKey())) {
mass += periEntry.getValue() * atomEntry.getValue();
}
}
}
return mass;
I have another method "fileReader" that takes the data from the mile and returns a map with the elements as the key and the mass as the value, this works fine.
This code also works well for "formulas" that have a single digit number of atoms, like "OCS", "C4H4AsH", and "Fe2O3".
However, when the amount of atoms is a 2 or more digit number, it is only reading the first digit of that number.
For example: with "RuSH2112", it is supposed to be Ru1 + S1 + H2112, but instead the output is Ru1 + S1 + H2.
I believe there is something wrong in my method "getAtoms" where it says "!!! HERE !!!", here is the code for that:
public static Map<String, Integer> getAtoms(String formula) {
// LinkedHashMap stores in insertion order
Map<String, Integer> newMap = new LinkedHashMap<>();
for (int i = 0; i < formula.length(); i++) {
int count = 0;
// convert string to char
char c = formula.charAt(i);
// convert char to string
String a = String.valueOf(c);
// check formula for upper case values
if (a.matches("[A-Z]")) {
for (int j = i + 1; j < formula.length(); j++) {
char d = formula.charAt(j);
String b = String.valueOf(d);
// check formula for lower case values
if (b.matches("[a-z]")) {
a += b;
if (newMap.get(a) == null)
newMap.put(a, 1);
else
newMap.put(a, newMap.get(a) + 1);
count = 1;
}
// check formula for integer values (the end of each molecule)
// !!! HERE !!!
else if (b.matches("[\\d]")) {
int k = Integer.parseInt(b);
newMap.put(a, k);
count = 1;
}
else {
i = j - 1;
break;
}
}
// put values into a map
if (count == 0) {
if (newMap.get(a) == null)
newMap.put(a, 1);
else
newMap.put(a, newMap.get(a) + 1);
}
}
}
return newMap;
}
Is there another way to say .matches("[\d]")) because I think that only uses one digit numbers?
I've reimplemented your method getAtom(). The main change that has been done to it is that instead of processing a formula character by character it splits the formula into chunks that represent either uppercase letters, combinations of an uppercase and a lowercase letter, or number.
That's the code for it:
String[] elementsAndIndices = formula.split("(?<=\\p{Lower})(?=\\p{Upper})|(?<=\\p{Upper})(?=\\p{Upper})|(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
Let's examine what's going on here:
\d - a digit: [0-9];
\D - a non-digit: [^0-9];
\p{Lower} - a lower-case alphabetic character: [a-z];
\p{Upper} - an upper-case alphabetic character:[A-Z];
\p{Alpha} - an alphabetic character:[\p{Lower}\p{Upper}];
Special constructs that start with a question mark are called lookbehind (?<=\\p{Lower}) and lookahead (?=\\p{Upper}). Both match a zero-length string that allows to split the formula in a manner that I described above without losing any symbol (you can read more about them here).
Meanings of lookbehind and lookbehind combinations that are used to split the formula:
(?<=\p{Lower})(?=\p{Upper}) - matches a zero-length string between a lower-case character \p{Lower} and an upper-case character \p{Upper};
(?<=\p{Upper})(?=\p{Upper}) - matches a zero-length string on the border between two upper-case characters \p{Upper};
(?<=\D)(?=\d) - matches a zero-length string between a non-digit \D and a digit \d;
(?<=\d)(?=\D) - matches a zero-length string between a digit \d and a non-digit \D.
Method merge() is used to update the map. It takes three arguments: key, value and remapping function. If the given key is absent (or this key is associated with null value) then this key will be associated with the given value. The remapping function, which is used to merge two values will be evaluated only if the provided key is already present and the value for it is not null.
elements.merge(elementsAndIndices[i], 1, Integer::sum);
The line of code shown above associates value 1 with a key elementsAndIndices[i] if it's not present in the map otherwise, it'll merge the existing value with 1 producing a sum. Method reference Integer::sum is an equivalent of lambda (val1, val2) -> val1 + val2;.
public static Map<String, Integer> getAtoms(String formula) {
Map<String, Integer> elements = new LinkedHashMap<>();
String[] elementsAndIndices =
formula.split("(?<=\\p{Lower})(?=\\p{Upper})|(?<=\\p{Upper})(?=\\p{Upper})|(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
for (int i = 0; i < elementsAndIndices.length; i++) {
if (elementsAndIndices[i].matches("\\p{Alpha}+")) {
if (i == elementsAndIndices.length - 1 || !elementsAndIndices[i + 1].matches("\\d+")) {
elements.merge(elementsAndIndices[i], 1, Integer::sum);
} else {
elements.merge(elementsAndIndices[i], Integer.parseInt(elementsAndIndices[i + 1]), Integer::sum);
i++;
}
}
}
return elements;
}
public static void main(String[] args) {
System.out.println(getAtoms("C6H12O6"));
System.out.println(getAtoms("NH3"));
System.out.println(getAtoms("RuSH2112"));
}
output
{C=6, H=12, O=6}
{N=1, H=3}
{Ru=1, S=1, H=2112}

How do I merge the indexes in an array to create 1 main array/String in Java?

The input is supposed to be
ABDECDEABCAADD
ABCDE
The first line is a random piece of text. The second line is a circular shift.
The output is supposed to be:
yes
This program is supposed to take a piece of text and determine if it contains a circular shift based on the second line of input.
A circular shift is when you take the first letter of the string and move it to the back of the string. Thus creating a new string.
If the text entered contains a circular shift from the second line then the output would be yes otherwise it would be no.
Since ABDECDEABCAADD contains DEABC which is a shift of ABCDE the output would be yes.
Scanner scan = new Scanner(System.in);
String text;
System.out.println("Enter text:");
text=scan.nextLine();
System.out.println("Enter shift:");
String shift=scan.nextLine();
String[] split1=shift.split("");
String[] array2=new String[split1.length];
String[] array3=new String[split1.length];
for(int z=0;z<split1.length;z++) {
array2[split1.length-1]=split1[0];
for(int x=0;x<split1.length-1;x++) {
array2[x]=split1[x+1];
array3[0]=array2[x]+array2[x+1];
}
//if(text!=)
}
for(int y=0;y<array2.length;y++) {
System.out.print(array2[y]);
}
How I wanted to tackle this question was to first get the input then separate the second line into characters so I can create a circular shift. Once I'm done with that I would take the new order of characters and merge them to create a string.
I need help when it comes to the merging but also with how I can create multiple shifts.
If you see this pleas help.
Don't create shifts. For best performance, do it like this:
String text = "ABDECDEABCAADD";
String shift = "ABCDE";
Scan text for the first character in shift, i.e. scan for 'A'.
When found, match as many of the following characters as possible.
If not all characters in shift were matched, get the count of missing characters.
Grab that many characters from before the found 'A', if available.
If found and they match the remaining characters in shift, your search is done.
Repeat from step 1, searching for the next 'A'.
Example
static int matchShift(String text, String shift) {
if (shift.isEmpty())
throw new IllegalArgumentException("Shift value is empty");
char first = shift.charAt(0);
for (int i = 0; i < text.length(); i++) {
if (text.charAt(i) == first) {
int j = 1;
while (j < shift.length() && i + j < text.length()
&& text.charAt(i + j) == shift.charAt(j))
j++;
if (j == shift.length())
return i; // Match found at index 'i', with unshifted value
int start = i + j - shift.length();
if (start >= 0 && text.substring(start, i).equals(shift.substring(j, shift.length())))
return start; // Match found at index 'start', with shifted value
}
}
return -1; // No match found
}
Test
public static void main(String[] args) {
test("ABDECDEABCAADD", "ABCDE");
}
static void test(String text, String shift) {
int i = matchShift(text, shift);
if (i == -1)
System.out.printf("'%s', '%s': No Match%n", text, shift);
else
System.out.printf("'%s', '%s': Match at index %d ('%s')%n",
text, shift, i, text.substring(i, i + shift.length()));
}
Output
'ABDECDEABCAADD', 'ABCDE': Match at index 5 ('DEABC')
It could also have responded with Match at index 4 ('CDEAB'). If that is important, change the logic to search for the last character instead of the first, match backwards, then compare substrings after.

Java: Determining if a word contains letters that can be found in another word?

For example:
If you have a String "magikarp", and you tested it against "karma", this would be true, because all of the letters that make up "karma" can be found in "magikarp".
"kipp" would return false, because there is only one "p" in "magikarp."
This is the attempt that I have right now, but I don't think it's very efficient, and it doesn't return correctly for cases when there are multiple occurrences of one letter.
private boolean containsHelper(String word, String word2){
for (int i = 0; i < word2.length(); i ++){
if (!word.contains(String.valueOf(word2.charAt(i)))){
return false;
}
}
return true;
}
I don't write the program here, but let you know how to do. There are 2 ways to do this considering complexity:
1) If you are sure that you would be getting only a-z/A-Z characters in the string, then take a array of size 26. Loop thorough the first string and place the count of the character appeared in the respective index. Say for example you have String "aabcc". Now array would look like [2,1,2,0,...0]. Now loop through the second String, and at each character, subtract the 1 from the array at the respective character position and check the resultant value. If value is less than 0, then return false. For example you have "aacd". When you are at d, you would be doing (0-1), resulting -1 which is less than 0, hence return false.
2) Sort the characters in the each String, and then compare.
Since you are only checking for characters, it would be more efficient to use indexOf and to check if it return -1 as contains itself call indexOf but with some other trims...
However, I think it would be simplier to convert the String to an array of char and to remove them if they are found which would also handle the case of multiple occurences.
So you're algorithm woud look something like this :
private final boolean containsHelper(final String word, final String word2)
{
char[] secondWordAsCharArray = word2.toCharArray();
char[] firstWordAsCharArray = word.toCharArray();
Arrays.sort(firstWordAsCharArray);//Make sure to sort so we can use binary search.
int index = 0;
for(int i = 0; i++ < secondWordAsCharArray.length;)
{
index = Arrays.binarySearch(firstWordAsCharArray, secondWordAsCharArray[i]);//Binary search is a very performant search algorithm
if(index == -1)
return false;
else
firstWordAsCharArray[index] = ''; //A SENTINEL value, set the char a value you are sure that will never be in word2.
}
}
Basically, what I do is :
Convert both word to char array to make it easier.
Sort the char array of the word we inspect so we can use binary search.
Loop over all characters of the second word.
retrieve the index using the binary search algorithm (a very performant algorithm on char, the best from my knowledge).
if index is -1, it was not found so we can return false.
else make sure we unset the character.
You need to ensure that for any character c that appears in the second string, the number of times that c appears in the second string is no greater than the number of times that c appears in the first string.
One efficient way to tackle this is to use a hashmap to store the count of the characters of the first string, and then loop through the characters in the second string to check whether their total count is no greater than that in the first string. The time and space complexity are O(n) in the worst case, where n is the length of the input strings.
Here is the sample code for your reference:
import java.util.HashMap;
import java.util.Map;
public class HashExample {
public static void main(String[] args) {
System.out.println(containsHelper("magikarp", "karma")); // true
System.out.println(containsHelper("magikarp", "kipp")); // false
}
private static boolean containsHelper(String word, String word2) {
Map<Character, Integer> hm = new HashMap<>();
for (int i = 0; i < word.length(); i++) {
Character key = word.charAt(i);
int count = 0;
if (hm.containsKey(key)) {
count = hm.get(key);
}
hm.put(key, ++count);
}
for (int i = 0; i < word2.length(); i++) {
Character key = word2.charAt(i);
if (hm.containsKey(key)) {
int count = hm.get(key);
if (count > 0) {
hm.put(key, --count);
} else {
return false;
}
} else {
return false;
}
}
return true;
}
}
On possible algorithm is to remove all letters from your second word that don't occur in the first, sort both and then compare them.
Here is a reasonable way to achieve that in Java 8:
List<Integer> wordChars = word.chars().sorted().collect(Collectors.toList());
List<Integer> searchChars = search.chars()
.filter(wordChars::contains).sorted().collect(Collectors.toList());
return wordChars.equals(searchChars);

scramble some letter in ArrayList assignment

This assignment involves reasoning about strings made up of uppercase letters. You will implement several static methods that appear in the same class (not shown). Here are the details.
1. The first method takes a single string parameter and returns a scrambled version of that string. The scrambling process begins at the first letter of the word and continues from left to right. If two consecutive letters consist of an "A" followed by a letter that is not an "A", then the two letters are swapped in the resulting string. Once the letters in two adjacent positions have been swapped, neither of those two positions can be involved in a future swap.
public static String scrambleWord(String word)
The method takes a given word (an empty string or a string containing only upper case letters) and returns a string that contains a scrambled version of the word according to the rules given above. The following table shows several examples of words and their scrambled versions.
Original word After scrambling
"TAN" "TNA"
"ABRACADABRA" "BARCADABARA"
"WHOA" "WHOA"
"AARDVARK" "ARADVRAK"
"EGGS" "EGGS"
"A" "A"
"" ""
the code i used but it dose not work is
public class ScrambleWord {
public static void main(String[] args) {
List<String> strList = new ArrayList<String>();
strList.add("TAN");
strList.add("ABRACADABRA");
strList.add("WHOA");
strList.add("EGGS");
strList.add("A");
strList.add("");
System.out.prentln(MainMethod.scrambleWordMeth(strList));
}
class MainMethod {
public static void scrambleWordMeth(List<String> strList) {
int curr = 0;
String res = "";
while (curr < strList.size()) {
String currentString = strList.get(curr);
for(int i = 0; i < currentString.length(); i++){
if (currentString.charAt(i) == 'A' && !(currentString.charAt(i + 1) == 'A')) {
res = res + currentString.substring(curr + 1, curr + 2);
res = res + 'A';
curr = curr + 2;
}
else {
res = res + currentString.substring(curr, curr + 1);
curr++;
}
}
if (curr < strList.size()) {
res = res + currentString.charAt(curr);
//res=res + strList.substring(curr);
}
}
return res;
}
}
}
Here is template for how to setup the methods such that the algorithm can be worked on in a more clear and isolated manner (note how the task states for "several methods"). This will prevent some issues in the posted code such as the incorrect usage of curr (which did not related to characters at all) in the inner loop. The usage of the array for the letters makes the task itself more logical to focus on without needing to perform slicing and concatenation.
static void scrambleAllWords(List<String> words) {
// Iterate through the list of word applying the scramble
// function and replacing the original item with the result.
for (int i = 0; i < words.size(); i++) {
String scrambled = scrambleWord(words.get(i));
words.set(i, scrambled);
}
}
static String scrambleWord(String word) {
// Get the letters that make up the word
char[] letters = word.toCharArray();
// Perform the algorithm on the letters
// for (int i = 0; i < ..
// Create a new string from the now-scrambled letters
return new String(letters);
}
The algorithm itself is rather simple and can be read as the following pseudo-code, which should be trivial to apply to letters as it is now an array clearly separated from the other cruft.
for i in the range [0, the number of letters in the word - 1)
if the letter at i is an 'A' and the following letter at i+1 is not an 'A' then
swap the letter at i with the letter at i+1 and
skip the next letter by advancing i by 1
(so that the current-now-next 'A' letter cannot be swapped again)
otherwise
do nothing

Highest "Valued" Palindrome

So I was at a programming interview a few months ago and this problem tripped me up for some reason. There are a couple of solutions I can think of but most of them seem extremely inefficient. Though I've been programming in some capacity for years, I'm currently in college for a CS degree so my point of reference may be incomplete. I was hoping someone here might offer up some possible solutions:
"Given a set of strings and associated numerical 'values,' assemble a palindrome from these string whose value (defined by the sum of the strings used to create it) is the highest possible."
There were no limits to how many strings could be provided, some strings may not be used.
Example:
"asd" - 3
"dsa" - 5
"appa" - 1
Result would be "asdappadsa" with a value of 9.
My thought would be to try all strings in all orders, then drop off one, starting with the lowest valued one, but that solution is O(N!) and I'd assume that's not ok.
(Preferred languages are C and Java, but whatever works)
EDIT: Clarification. Each string provided can only be used once, and has to be used exactly as provided, though you may choose to not use any of the strings in your palindrome. You can not use substrings of provided strings, nor can you reverse the string.
Replace "all strings" with "all palindromes" and the problem space becomes much smaller.
Divide the strings into 26 subsets.
Strings beginning with x (for 'a' <= x <= 'z')
[or whatever the set of "letters" is]
Now divide them into another 26 subsets
Strings ending with y ( for 'a' <= y <= 'z')
Note each string appears in a "begins with" set and an "ends with" set.
Use these sets to guide creation of all possible palindromes.
Start with two empty strings: prefix and suffix
for each string in the original set
assign it to the prefix
call recursiveFunction(prefix, suffix)
def recursiveFunction(prefix, suffix):
if prefix + <anything> + suffix cannot form a palindrome return
if prefix + suffix is a palindrome, remember it
while you have unused strings
if the suffix is shorter than the prefix
Look at the first unmatched character in the prefix
for each unused string that ends in that character
call recursiveFunction(prefix, string + suffix)
else if prefix is shorter than suffix
look at the last unmatched character in the suffix
for each unused string that ends with that character
call recursiveFunction(prefix + string, suffix)
else // suffix and prefix have equal lenghths
for each unused string
call recursiveFunction(prefix + string, suffix)
Be sure to mark the string used in both begins with and ends when you use it.
And be sure to consider the impact of recursion on the "used" marker.
Then pick the palindrome with the best score.
With palindrones, you can split the string into 3 substrings, ABC. There is potential within the set to find string reversals, so when you get a hit you can keep track of these strings for useage in substring A and C. If you don't get a reversal hit within the entire set, you just need to find the largest string (or string with the highest value) that is a reflection of itself. Not the best solution, I'm sure, but I did it for fun anyways so I may as well share. Also, I made no efforts to make this code "clean", so its a bit ugly, but it works.
public class Main {
private static String[] set = new String[] { "asdf" , "kjdij", "skjdihi", "ddidid" , "ididid", "iddid", "oihu", "uhio", "fdsa", "ajsja" };
public static void main(String[] args){
//Used for a couple of for loops...
int count;
Map<String, String> map = new HashMap<String,String>(); //Hold the strings and their reversals in a hashmap for quick lookups.
/* Think of the palindrome as 3 substrings, A, B, and C. */
ArrayList<String> A = new ArrayList<String>();
ArrayList<String> B = new ArrayList<String>();
ArrayList<String> C = new ArrayList<String>();
count = set.length;
String[] reverse_set = new String[count];
for(int x = 0; x < count; x++){
String reverse = new StringBuilder(set[x]).reverse().toString();
/* Check strings that would work for section B, since it's a set, we know that if it could work for B,
* it couldn't work for A or C - since a set contains no duplicates. */
if(reverse.equals(set[x])){
B.add(set[x]);
} else {
/* Otherwise, we'll have to check to see if it would work for A and C */
reverse_set[x] = reverse;
map.put(set[x], reverse);
}
}
/* Check the map for reverse string hits, we know that if another string exists in set S such that S(X) == R(X) it can work for substring
* A and C. */
int map_size = map.size();
int hit_count = 0;
for(int i = 0; i < map_size; i++){
String s = map.get(reverse_set[i]);
if(s != null){
hit_count++;
A.add(set[i]);
C.add(reverse_set[i]);
map.remove(set[i]); //remove the reflection, so we don't get duplicates
}
}
/* Find the longest string in B, since we'll have to do this even if was had any hits in the previous loop. */
String b = null;
if(B.size() > 0){
int length = 0;
for(String x : B){
int mLength = x.length();
if(mLength > length){
b = x;
length = mLength;
}
}
}
/* Build the palinedrome */
String palineString = "";
if(hit_count == 0 && b != null){
palineString = b;
} else {
for(String x : A){
palineString += x;
}
if(b != null){
palineString += b;
}
count = C.size();
for(int y = (count - 1); y >= 0; y--){
palineString += C.get(y);
}
}
if(checkPalindrome(palineString)){
System.out.print("The Palindrone is: " + palineString + " Score: " + Integer.toString(palineString.length()));
} else {
System.out.print("Oops...");
}
}
private static boolean checkPalindrome(String x){
if(x.equals(new StringBuilder(x).reverse().toString())){
return true;
} else {
return false;
}
}
}
Output:
The Palindrone is: asdfoihuajsjauhiofdsa Score: 21
EDIT:
Note: for the time being, I used the string's length as the "assigned value", I'll make an edit later to account for assigning random values to strings, but it won't make too much of a difference, since it only adds a few extra use cases to check for.

Categories

Resources