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"]
This one does some preprocessing of prefixes, which helps matching as we build from the outer ends in, adding to the side that has less characters. The idea is that each proper prefix of the middle (which belongs to either the right or left side) must match a whole word to be added to the other side; or that the complete middle must be a prefix of the word we'll add to the other side.
Python code. Can find the palindromes of the "reasonable" True example, but the trouble is affirming that a palindrome cannot be found.
Python code: