There's no end to the leetcode questions about finding palindrome pairs and how to determine if a given string is a palindrome, but I can't seen to find any discussion about sentence palindrome testing for unordered words. (Every word must be used in the palindrome for the function to return true)
For instance, on the input:
["stop", "nine", "rum", "myriad", "put", "up", "rum", "dairymen", "murmur", "in", "pots"]
the function would return True, and on:
["sit", "on", "potato", "pan", "otis"]
it would return False.
A naive solution in Python would be to useitertools.permutations(words, len(words))
to check every possible solution, but as word count grows, I believe this is at least O(n!*c)
with n words and c characters.
Heap's algorithm doesn't seem to particularly lend itself well to the problem, because a way of generating half of the permutations and short circuiting all the "children" permutations that have the same outer configuration when the first and last words don't start palindromic, doesn't really make itself obvious.
However with the Steinhaus–Johnson–Trotter algorithm, it seems there is a nice delineation at the halfway point in which the permutations repeat essentially in reverse. However I can't think of a way to efficiently "short circuit" cases we don't need to check past that. Perhaps there is some way to skip inversion numbers based off of what cases can be ruled out?
Edit: Here's an example that would be quite hard to crack:
['1', '10', '11', '100', '101', '110', '111', '1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111', '10000', '10001', '10010', '10011', '10100', '10101', '10110', '10111', '11000', '11001', '11010', '11011', '11100', '11101', '11110', '11111', '100000', '100001', '100010', '100011', '100100', '100101', '100110', '100111', '101000', '101001', '101010', '101011', '101100', '101101', '101110', '101111', '110000', '110001', '110010', '110011', '110100', '110101', '110110', '110111', '111000', '111001', '111010', '111011', '111100', '111101', '111110', '111111', '1000000', '1000001', '1000010', '1000011', '1000100', '1000101', '1000110', '1000111', '1001000', '1001001', '1001010', '1001011', '1001100', '1001101', '1001110', '1001111', '1010000', '1010001', '1010010', '1010011', '1010100', '1010101', '1010110', '1010111', '1011000', '1011001', '1011010', '1011011', '1011100', '1011101', '1011110', '1011111', '1100000', '1100001', '1100010', '1100011', '1100100']
As there are about 10^157 permutations. But more reasonably:
['1', '10', '11', '100', '101', '110', '111', '1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111', '10000', '10001', '10010', '10011', '10100', '10101', '10110', '10111']
would return False but
['1', '10', '11', '100', '101', '110', '111', '1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111', '10000', '10001', '10010', '10011', '10100', '10101', '10110']
would return True, as this palindrome exists:
["1000", "1100", "110", "10100", "10011", "11", "1010", "1101", "1011", "1110", "10000", "10", "1111", "10110", "1", "10101", "111", "100", "10010", "101", "1001", "10001"]
Here's an approach to solving this problem.
Note: This approach is based on the following assumptions:
The following is a simple implementation of this approach: