Skip to content

Instantly share code, notes, and snippets.

@cdeszaq
Last active December 19, 2015 06:18
Show Gist options
  • Save cdeszaq/5909995 to your computer and use it in GitHub Desktop.
Save cdeszaq/5909995 to your computer and use it in GitHub Desktop.
// isPalindrome - ignore cases, spaces and punctuation
// Empty string is false
// O(1) space, cant modify original string
[1,2,3,4,5,6].each {
println "Running isPalindrome${it}"
assert !"isPalindrome${it}"("") // False
assert !"isPalindrome${it}"(" !,! ") // False
assert "isPalindrome${it}"("M") // True
assert "isPalindrome${it}"("M.") // True
assert "isPalindrome${it}"(".M") // True
assert "isPalindrome${it}"("..M") // True
assert "isPalindrome${it}"("M..") // True
assert "isPalindrome${it}"("MM") // True
assert "isPalindrome${it}"("MM.") // True
assert "isPalindrome${it}"(".MM") // True
assert "isPalindrome${it}"("M..") // True
assert "isPalindrome${it}"("..MM") // True
assert "isPalindrome${it}"("M..M") // True
assert "isPalindrome${it}"("MM..M") // True
assert "isPalindrome${it}"("Madam! I'm... Adam!!!!!") // True
}
// Assume you have this method available
def isAlphaNumeric(c) {
c ==~ "[A-Za-z0-9]"
}
def isPalindrome1(String s) {
int strLen = s.length()
// Special case of empty string
if(strLen == 0) {
return false;
}
int endPointer = strLen - 1;
boolean haveSeenCharacter = false
for (int i = 0; i <= endPointer; i++) {
// find the front
if(!isAlphaNumeric(s[i])) {
continue;
}
for(; endPointer >= i; endPointer--) {
// find the back
if(isAlphaNumeric(s[endPointer])) {
break;
}
}
// Compare
if(s[i].toLowerCase() != s[endPointer].toLowerCase() || (i > endPointer && !haveSeenCharacter)) {
return false;
}
// Remember to move in
endPointer--;
haveSeenCharacter = true
}
if(!haveSeenCharacter) {
return false
}
return true
}
def isPalindrome2(String s) {
// Set up the pointers
int backPointer = s.length() - 1
int frontPointer = 0
// Special case of empty string, where the back pointer is already off the front end
if(backPointer < 0) {
return false
}
// Keep track of having seen a character to compare against
boolean haveMadeOneComparison = false
while(frontPointer <= backPointer) {
// Find the next character from the front
if(!isAlphaNumeric(s[frontPointer])) {
frontPointer++
continue
}
// Find the next character from the back
while(backPointer >= 0) {
if(isAlphaNumeric(s[backPointer])) {
break
}
backPointer--
}
// If the pointers crossed, we're done looping
if (frontPointer > backPointer) {
break
}
// Compare characters
if(s[frontPointer].toLowerCase() != s[backPointer].toLowerCase()) {
// Characters don't match
return false;
} else {
// We've seen at least 1 character, so it's not all unimportant characters
haveMadeOneComparison = true
// Move the pointers one step
frontPointer++
backPointer--
}
}
if(haveMadeOneComparison) {
return true
} else {
return false
}
}
boolean isPalindrome3(String s) {
// Set up the pointers
int lastIndex = s.length() - 1
int backPointer = lastIndex
int frontPointer = 0
def pointersHaveCrossed = {frontPointer > backPointer} // Simple comparator to tell us if the pointers have crossed
// Keep track of having all good comparisons, assuming we don't have any
boolean allGoodComparisons = false
// Walk the pointers towards each other until they cross
for(; !pointersHaveCrossed(); frontPointer++) {
// Find the next character from the front
if(!isAlphaNumeric(s[frontPointer])) {
continue
}
// Find the next character from the back
for(; !pointersHaveCrossed(); backPointer--) {
if(!isAlphaNumeric(s[backPointer])) {
continue
}
}
// If the pointers crossed, we're done looping
if (pointersHaveCrossed()) {
break
}
// Compare characters
if(s[frontPointer].toLowerCase() != s[backPointer].toLowerCase()) {
// Characters don't match, we're done looping
allGoodComparisons = false
break
} else {
// So far, so good
allGoodComparisons = true
}
}
// If all the comparisons are good, it's a palindrome, otherwise its not
return allGoodComparisons
}
boolean isPalindrome4(String s) {
int left = 0
int right = s.length() - 1
boolean hasALetter = false
// Loop until the pointers cross
while (left <= right) {
// Get the indices
left = nextFrontIndex(left, s, right)
right = nextBackIndex(right, s, left)
// Check for crossed pointers
if(left <= right) {
// Check for palindrome
if(s[left].toLowerCase() != s[right].toLowerCase()) {
return false
} else {
hasALetter = true
}
}
// Move the pointers
left++
right--
}
return hasALetter
}
int nextFrontIndex(int start, String s, Integer end) {
for (int i = start; i <= end; i++) {
if (isAlphaNumeric(s[i])) {
return i
}
}
return end + 1 // Ran off the end
}
int nextBackIndex(int start, String s, Integer end) {
for (int i = start; i >= end; i--) {
if (isAlphaNumeric(s[i])) {
return i
}
}
return end - 1 // Ran off the end
}
boolean isPalindrome5(String s) {
int left = 0
int right = s.length() - 1
boolean hasALetter = false
// Loop until the pointers cross
while (left <= right) {
// Get the indices
for(; left <= right; left++) {
if (isAlphaNumeric(s[left])) {
break
}
}
for(; left <= right; right--) {
if (isAlphaNumeric(s[right])) {
break
}
}
// Check for crossed pointers
if(left <= right) {
// Check for palindrome
if(s[left].toLowerCase() != s[right].toLowerCase()) {
return false
} else {
hasALetter = true
}
}
// Move the pointers
left++
right--
}
return hasALetter
}
boolean isPalindrome6(String s) {
int left = 0
int right = s.length() - 1
// Loop until the pointers cross
while (left <= right) {
// Get the indices
for(; left <= right; right--) {
if (isAlphaNumeric(s[right])) {
break
}
}
for(; left <= right; left++) {
if (isAlphaNumeric(s[left])) {
break
}
}
// Check for crossed pointers
if(left <= right) {
// Check for palindrome
if(s[left].toLowerCase() != s[right].toLowerCase()) {
return false
}
// Move the pointers
left++
right--
}
}
return left > 0
}
boolean isPalindrome7(String s) {
int left = 0
int right = s.length() - 1
// Loop until the pointers cross
while (left <= right) {
// Get the indices or cross
while(!isAlphaNumeric(s[right]) && left <= right) {
right--
}
while(!isAlphaNumeric(s[left]) && left <= right) {
left++
}
// Check for crossed pointers
if(left <= right) {
// Check for palindrome
if(s[left].toLowerCase() != s[right].toLowerCase()) {
return false
}
// Move the pointers
left++
right--
}
}
return left > 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment