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

https://www.socketloop.com/tutorials/golang-removes-punctuation-or-defined-delimiter-from-the-user-s-input

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

https://socketloop.com/tutorials/golang-accept-input-from-user-with-fmt-scanf-skipped-white-spaces-and-how-to-fix-it





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