How do you check if a word has an anagram that is a palindrome?
Asked Answered
D

2

0

How do you compare a palindromic word to one of the newly formed words of an anagram?

And how do you grab one of the newly formed words for it to be compared to the input word?

This is my code:

public class SampleCode2 {
    public static boolean isPalindromic(String word, String mark) {
        if (word.length() == 0) {
        }

        for (int i = 0; i < word.length(); i++) {
            String newMark = mark + word.charAt(i);
            String newLetters = word.substring(0, i) +
                    word.substring(i + 1);
        }

        String ifPalindrome = ""; //will store here the reversed string
        String original = word; //will store here the original input word

        //to reverse the string
        for (int i = word.length() - 1; i >= 0; i--) {
            ifPalindrome += word.charAt(i);
        }

        //to compare the reversed string to the anagram
        if (word.equals(ifPalindrome)) {
            return true;
        } else {
            return false;
        }
    }

    public static void main(String[] args) {
        boolean check = isPalindromic("mmaad", "");
        System.out.println(check);
    }
}

It's not yet done because the permutation and comparison won't work. The output is displaying false, I need it to be true because the anagram of MMAAD is madam. And I have to check if madam is indeed a palindrome of mmaad.

Docket answered 4/11, 2020 at 14:54 Comment(0)
H
1

So What I did is used HashMap instead of creating words from the given word
A String can be of even or odd length


If "EVEN" String is palindrome then every "character" in the String will appear even times
eg: String str = maam : m=2, a=2


If "ODD" String is a palindrome then there will only be 1 character of odd occurrence and the rest will occur even times.
eg: String str = mmaad: m=2,a=2,d=1


To store the Occurrence of the Characters in the String we will use HashMap where Character of the String is the KEY and its occurrence is VALUE

HashMap<Character,Integer> mapChar = new HashMap<>();

And we will add each Character in the HashMap with the number of times it has appeared in the String.

Now we will check if the String length is "even" or "odd" if "EVEN" Length String we know that every character will appear EVEN times and if any time a character appears "ODD" times we return false i.e It's not a Palindrome

for (Map.Entry<Character, Integer> entries : mapChar.entrySet()) {
    if (entries.getValue() % 2 != 0) {
        return false;
    }
}

If "ODD" Length String we know that only one Character will appear odd time and the rest will be of EVEN Occurrence
And if there are 2 characters that occur odd times then its not a palindrome

// Number of times odd value Character as occurred
int occur1 = 0;
for (Map.Entry<Character, Integer> entries : mapChar.entrySet()) {
    if (entries.getValue() % 2 == 1) {
        occur1++;
        if (occur1 > 1) {
            return false;
        }
    }
}

Here's the whole Code:

public static void main(String[] args) throws Exception {
    boolean check = isPalindromic("malayalam", "");
    System.out.println(check);
}
public static boolean isPalindromic(String word, String mark) {
    boolean isPal = true;
    if (word.length() == 0) {
        return false;
    }
    HashMap<Character, Integer> mapChar = new HashMap<>();
    for (int i = 0; i < word.length(); i++) {
        char ch = word.charAt(i);
        if (mapChar.containsKey(ch)) {
            mapChar.put(ch, mapChar.get(ch) + 1);
        } else {
            mapChar.put(ch, 1);
        }
    }
    if (word.length() % 2 == 0) {
        for (Map.Entry<Character, Integer> entries : mapChar.entrySet()) {
            if (entries.getValue() % 2 != 0) {
                return false;
            }
        }
    } else {
        int occur1 = 0;
        for (Map.Entry<Character, Integer> entries : mapChar.entrySet()) {
            if (entries.getValue() % 2 == 1) {
                occur1++;
                if (occur1 > 1) {
                    isPal = false;
                    break;
                }
            }
        }
    }
    return isPal;
}

output:

mmaa
Is Palindrome: true
mmaad
Is Palindrome: true
niti
Is Palindrome: false
Humoresque answered 4/11, 2020 at 15:43 Comment(1)
You could save about 75% procedural boilerplate by streaming and filtering with a BiPredicateJactitation
H
1

If you want to find a list of anagrams of a word that are palindromes, you can split this task into two parts: first get a list of the character permutations of that word List<String>, i.e. a list of anagrams, and then filter those strings that are palindromes. For example, for the mmaad string, the palindromes are:

madam
amdma

Getting a list of permutations is an expensive operation for large strings, since the number of permutations is a factorial of the string length. For example, for the mmaad string, there are 120 permutations. Filtering palindromes after that is cheaper.

Try it online!

public static void main(String[] args) {
    // list of distinct permutations
    getPermutations("mmaad")
            // Stream<String>
            .stream()
            // filter palindromes
            .filter(str -> isPalindrome(str))
            // output
            .forEach(System.out::println);
}
/**
 * @param str source string, may contain surrogate pairs.
 * @return whether the source string is a palindrome.
 */
public static boolean isPalindrome(String str) {
    // array of characters of the string
    int[] chars = str.codePoints().toArray();
    return IntStream
            // iterate from the beginning to the middle of the string
            .range(0, chars.length / 2)
            // compare the characters: first - last, second - penultimate
            .allMatch(i -> chars[i] == chars[chars.length - i - 1]);
}
/**
 * @param str source string, may contain surrogate pairs.
 * @return a list of distinct permutations of characters of the source string.
 */
public static List<String> getPermutations(String str) {
    // array of characters of the string
    int[] chars = str.codePoints().toArray();
    return IntStream.range(0, chars.length)
            // Stream<List<Map<Integer,String>>>
            .mapToObj(i -> IntStream.range(0, chars.length)
                    // represent each character as Map<Integer,String>
                    .mapToObj(j -> Map.of(j, Character.toString(chars[j])))
                    // collect a list of maps
                    .collect(Collectors.toList()))
            // reduce a stream of lists to a single list
            .reduce((list1, list2) -> list1.stream()
                    // summation of pairs of elements,
                    // i.e. maps, from two lists
                    .flatMap(map1 -> list2.stream()
                            // filter out those keys
                            // that are already present
                            .filter(map2 -> map2.keySet().stream()
                                    .noneMatch(map1::containsKey))
                            // join entries of two maps
                            .map(map2 -> {
                                Map<Integer, String> map =
                                        new LinkedHashMap<>();
                                map.putAll(map1);
                                map.putAll(map2);
                                return map;
                            }))
                    // collect into a single list
                    .collect(Collectors.toList()))
            // List<Map<Integer,String>>
            .orElse(List.of(Map.of(0, str)))
            // Stream<Map<Integer,String>>
            .stream()
            // map of strings to a single string
            .map(map -> String.join("", map.values()))
            .distinct()
            // list of distinct permutations
            .collect(Collectors.toList());
}

See also:
How to create all permutations of tuples without mixing them?
Reverse string printing method

Hydrotherapy answered 13/4, 2021 at 20:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.