Golang : Handle Palindrome string with case sensitivity and unicode
Problem:
You are studying Computer Science and you have an assignment to check if a word, phrase, number or any other sequence of characters reads the same backward or forward.
This is a common assignment that your lecturer use to mold your brain into a computer scientist and it is known as the "Palindrome" test. To add new level of difficulties, your program needs to handle unicode characters in the string and allow case sensitivity test as well.
How to do that?
Solution:
This solution below can handle input strings with unicode characters, phrase, number and allow or disallow case sensitive test.
Here you go!
package main
import (
"bufio"
"fmt"
"os"
"strings"
"unicode/utf8"
)
func Reverse(s string) string {
totalLength := len(s)
buffer := make([]byte, totalLength)
for i := 0; i < totalLength; {
r, size := utf8.DecodeRuneInString(s[i:])
i += size
utf8.EncodeRune(buffer[totalLength-i:], r)
}
return string(buffer)
}
func isPalindrome(input string, caseSensitive bool) bool {
if caseSensitive != true {
input = strings.ToLower(input)
}
// to deal with phrases, we need to eliminate the
// spaces
input = strings.TrimSpace(input)
reverse := Reverse(input)
if input == reverse {
return true
} else {
return false
}
}
func main() {
fmt.Println("Enter a word, phrase or number : ")
consoleReader := bufio.NewReader(os.Stdin)
answer, _ := consoleReader.ReadString('\n')
// get rid of the extra newline character from ReadString() function
answer = strings.TrimSuffix(answer, "\n")
fmt.Println(answer, "is palindrome[case sensitive] ?", isPalindrome(answer, true))
fmt.Println(answer, "is palindrome[case INsensitive] ?", isPalindrome(answer, false))
}
Sample tests output:
Enter a word, phrase or number :
civic 世界你好 好你界世 civic
civic 世界你好 好你界世 civic is palindrome[case sensitive] ? true
civic 世界你好 好你界世 civic is palindrome[case INsensitive] ? true
Enter a word, phrase or number :
civiC
civiC is palindrome[case sensitive] ? false
civiC is palindrome[case INsensitive] ? true
Enter a word, phrase or number :
STRESSED DESSERTS
STRESSED DESSERTS is palindrome[case sensitive] ? true
STRESSED DESSERTS is palindrome[case INsensitive] ? true
Enter a word, phrase or number :
112233332211
112233332211 is palindrome[case sensitive] ? true
112233332211 is palindrome[case INsensitive] ? true
Enter a word, phrase or number :
世界你好好你界世
世界你好好你界世 is palindrome[case sensitive] ? true
世界你好好你界世 is palindrome[case INsensitive] ? true
If you are looking to enchance this code to handle input string with unicode and remove delimiters. Here it is :
package main
import (
"bufio"
"fmt"
"os"
"regexp"
"strings"
"unicode/utf8"
)
var delim = []string{"\"", ":", "?", "!", ".", ";", ",", "*"}
func removeDelimUnicodeString(str string, delimiters []string) string {
var charSlice []rune
var result string = ""
// push characters into charSlice
for _, char := range str {
charSlice = append(charSlice, char)
}
//check each character in charSlice against unwanted delimiters
for position, char := range charSlice {
for _, forbiddenChar := range delimiters {
if test := strings.Index(string(char), forbiddenChar); test > -1 {
replacement := rune(' ')
charSlice[position] = replacement
charSlice = append(charSlice[:position], charSlice[position:]...)
}
}
result = result + string(charSlice[position])
}
// convert []string slice back to string
// result = fmt.Sprintf("%c", charSlice)
// NOTE : this method will cause extra [ and ] in the result string
return result
}
// faster way to get rid delimiters
// for string without unicode
func removeDelimString(str string) string {
// alphanumeric (== [0-9A-Za-z])
// \s is a white space character
regExp := regexp.MustCompile(`[^[:alnum:]\s]`)
return regExp.ReplaceAllString(str, "")
}
// test to see if the input string has unicode
func testStringForUnicode(s string) bool {
a := len(s)
b := utf8.RuneCountInString(s)
if a == b {
return false
} else {
return true
}
}
func Reverse(s string) string {
totalLength := len(s)
buffer := make([]byte, totalLength)
for i := 0; i < totalLength; {
r, size := utf8.DecodeRuneInString(s[i:])
i += size
utf8.EncodeRune(buffer[totalLength-i:], r)
}
return string(buffer)
}
func isPalindrome(input string, caseSensitive bool) bool {
if caseSensitive != true {
input = strings.ToLower(input)
}
// don't remove delimiters from string with unicode
if !testStringForUnicode(input) {
input = removeDelimString(input)
} else {
input = removeDelimUnicodeString(input, delim)
}
// trim(remove)white space
input = strings.TrimSpace(input)
// trim(remove) white space in between characters
input = strings.Replace(input, " ", "", -1)
reverse := Reverse(input)
if input == reverse {
return true
} else {
return false
}
}
func main() {
fmt.Println("Enter a word, phrase or number : ")
consoleReader := bufio.NewReader(os.Stdin)
answer, _ := consoleReader.ReadString('\n')
// get rid of the extra newline character from ReadString() function
answer = strings.TrimSuffix(answer, "\n")
fmt.Println(answer, "is palindrome[case sensitive] ?", isPalindrome(answer, true))
fmt.Println(answer, "is palindrome[case INsensitive] ?", isPalindrome(answer, false))
}
Sample output:
Enter a word, phrase or number :
A MAN, A PLAN, A CANAL: PANAMA
A MAN, A PLAN, A CANAL: PANAMA is palindrome[case sensitive] ? true
A MAN, A PLAN, A CANAL: PANAMA is palindrome[case INsensitive] ? true
Enter a word, phrase or number :
A MAN, A PLAN, A CANAL: PANAMAx
A MAN, A PLAN, A CANAL: PANAMAx is palindrome[case sensitive] ? false
A MAN, A PLAN, A CANAL: PANAMAx is palindrome[case INsensitive] ? false
Enter a word, phrase or number :
civic 世界你好,好你界世 civic
civic 世界你好,好你界世 civic is palindrome[case sensitive] ? true
civic 世界你好,好你界世 civic is palindrome[case INsensitive] ? true
Happy coding and welcome to the world of Computer Science!
References:
https://socketloop.com/tutorials/golang-warp-text-string-by-number-of-characters-or-runes-example
https://socketloop.com/tutorials/golang-warp-text-string-by-number-of-characters-or-runes-example
http://www.brainjet.com/random/5471/13-palindrome-phrases-that-will-turn-you-around/#slide/4/0
https://www.socketloop.com/tutorials/golang-reverse-a-string-with-unicode
By Adam Ng
IF you gain some knowledge or the information here solved your programming problem. Please consider donating to the less fortunate or some charities that you like. Apart from donation, planting trees, volunteering or reducing your carbon footprint will be great too.
Advertisement
Tutorials
+20.2k Golang : Pipe output from one os.Exec(shell command) to another command
+21.4k Golang : Convert string slice to struct and access with reflect example
+10.6k Golang : How to transmit update file to client by HTTP request example
+13.2k Golang : How to get year, month and day?
+10.1k Golang : Wait and sync.WaitGroup example
+10.2k Golang : Allow Cross-Origin Resource Sharing request
+30.6k Golang : Calculate percentage change of two values
+5.4k Javascript : How to refresh page with JQuery ?
+5.5k Linux/Unix/PHP : Restart PHP-FPM
+14.7k Golang : Search folders for file recursively with wildcard support
+8.7k Golang : What is the default port number for connecting to MySQL/MariaDB database ?