Normally I post amusing PowerShell-related content on Fridays as part of my Friday Fun series. These are light-hearted articles about using PowerShell. Almost always they are not practical but they serve as a learning vehicle. My topic this week seems extra silly so I'm moving it to Saturday. I'm a pushover for alliteration.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
Last week I came across a comment on Facebook that involved palindromes. A palindrome is a word that is spelled the same backwards and forwards. Names like Otto and ABBA are palindromes. So are words like madam, civic, and redder. I thought it would be fun to use PowerShell to test if a string was a palindrome. To figure this out I would need to find the midpoint of the string, get the first part of the string and then compare it to the last part of the string, but in reverse order.
PS C:\> $t = "madam"
PS C:\> $mid=[math]::Truncate($t.length/2)
PS C:\> $mid
2
I'm using the Truncate method from the [Math] class so that when I divide the string length by 2, the value is rounded down. This will be important in a moment. Getting the first half of the string is pretty simple.
PS C:\> $start = -join ($t[0..($mid-1)])
PS C:\> $start
ma
I'm getting characters in $t by their index number. In this case going from 0 to the midpoint minus 1. This would give me an array of characters so I regroup them using the -join operator. As an alternative, I could also have done this:
PS C:\> $start = $t.Substring(0,($mid))
Now to get the last half. Remember, I need to get the end of the string in reverse order until I reach the midpoint again. I can use the same technique I used for the front, except this time starting at the end and going backwards.
PS C:\> $end = -join ($t[-1..-($mid)])
PS C:\> $end
ma
Now to compare $start and $end.
PS C:\> $start -eq $end
True
You may be wondering, "What about the 'd'?" Well, in this case it is irrelevant because going backwards or forwards the 'd' is in the same place. I think of these as pivot letters. But this technique also works for strings without a pivot point.
PS C:\> $t="redder"
PS C:\> $mid=[math]::Truncate($t.length/2)
PS C:\> $start = -join ($t[0..($mid-1)])
PS C:\> $end = -join ($t[-1..-($mid)])
PS C:\> $start -eq $end
True
PS C:\> $start
red
PS C:\> $end
red
PS C:\>
So how about a simple function to test if a string is a palindrome?
Function Test-IsPalindrome {
[cmdletbinding()]
Param(
[Parameter(Position=0,Mandatory=$True,ValueFromPipeline=$True)]
[ValidateNotNullorEmpty()]
[string]$Text,
[switch]$IgnoreSpace
)
Process {
Write-Verbose "Testing $Text"
if ($IgnoreSpace) {
Write-Verbose "Removing spaces from text"
$text = $text.Replace(" ","")
Write-Verbose $text
}
$l = $text.length
Write-Verbose "Length is $l"
$mid = [math]::Truncate($l/2)
Write-Verbose "Midpoint is $mid"
#could also use Substring()
$start = -join ($text[0..($mid-1)]) #$text.Substring(0,($mid))
$end = -join ($text[-1..-($mid)])
Write-Verbose "Start: $start"
Write-Verbose "Pivot: $($Text[$mid])"
Write-Verbose "End : $end"
if ($start -eq $end) {
$True
}
else {
$false
}
} #process
} #end Test-IsPalindrome
This is an advanced function so I could add some verbose messages, which is great for troubleshooting and debugging. I also wanted to be able to pipe strings to the function. The intent is to test a string and return True or False. The code is essentially the same thing I showed you, except now it is a little easier to use.
PS C:\> "redder","foo","civic","madam" | Test-IsPalindrome
True
False
True
True
I added an extra feature to strip out spaces.
PS C:\> Test-IsPalindrome "Madam Im Adam" -IgnoreSpace -Verbose
VERBOSE: Testing Madam Im Adam
VERBOSE: Removing spaces from text
VERBOSE: MadamImAdam
VERBOSE: Length is 11
VERBOSE: Midpoint is 5
VERBOSE: Start: Madam
VERBOSE: Pivot: I
VERBOSE: End : madAm
True
PS C:\> Test-IsPalindrome "A nut for a jar of tuna" -IgnoreSpace
True
Yes, this is a silly application of PowerShell. But I hope it gives you an idea of how to use the -Join operator and to work with strings. By the way, I could use these techniques to turn a string into a palindrome.
PS C:\> $text="sum"
PS C:\> -join ($Text, -join $Text[-1..-($Text.length)])
summus
Ok, perhaps not a valid word in English but see if you can follow what the -Join operators are doing and how this snippet works. If you'd like to play with this, you can download Test-IsPalindrome.
I’m sure it is no surprise that there is usually more than one way to do something in PowerShell. Here’s a technique from James O’Neill that is a bit more advanced and would require a little .NET experience to figure out:
“rotavator”,”foobar”,”madam”,”civic” | foreach {[char[]]$_[-1..-$_.length] -join “” -eq $_ }
Or this variation from Rob Campbell:
‘rotavator’,’fubar’,’madam’ | foreach {$s=[char[]]$_;[array]::reverse($s);$_ -eq ($s -join ”)}
thanks for great blog.
here is one more way to do it:
$t=”redder”
$reverse = -join $t[$t.Length..0]
$t -eq $reverse