🔑

Go言語で回文の判定をする

2024/11/18に公開

問題

文字列が与えられたとき、その文字列が回文(前から読んでも後ろから読んでも同じ)かどうかを判定する関数をGoで実装してください。大文字と小文字は区別せず、スペースや記号も無視して判定するものとします。

実装ヒント

  • 文字列を正規化(すべて小文字にし、アルファベット以外の文字を除去)する処理が必要です。
  • その後、両端から文字を比較していく方法で判定すると良いでしょう。

使えそうなGoの標準ライブラリ

  • strings.ToLower(): 文字列全体を小文字に変換します。
  • unicode.IsLetter()strings.Builder: アルファベットのみを取り出すためのフィルタリングや文字列の再構築に便利です。

ステップ1: 文字列の正規化

  • 小文字に変換: strings.ToLower() を使って文字列全体を小文字に変換します。これで、大文字と小文字の区別をなくします。
  • アルファベット以外を除去: unicode.IsLetter() などを使って、アルファベットだけを取り出し、スペースや記号を無視します。

ステップ2: 回文かどうかを確認

  • 文字列の先頭と末尾から1文字ずつ比較していきます。たとえば、最初の文字と最後の文字が同じかを確認し、それが一致していれば次に進み、途中で異なる場合は回文ではないと判断します。

具体的な方法は、インデックス left を0、right を文字列の最後のインデックスに設定し、それらを内側に向かって移動させながら比較することで確認できます。

実際のコード

package main

import (
	"fmt"
	"strings" // 文字列操作を行うための標準パッケージ
	"unicode" // Unicode文字の分類や変換を行うための標準パッケージ
)

// 文字列が回文かどうかを判定する関数
func isPalindrome(s string) bool {
	// 1. 文字列を小文字に変換し、アルファベット以外の文字を除去
	var cleaned strings.Builder // 文字列を構築するための構造体
	for _, r := range s {
		if unicode.IsLetter(r) {
			cleaned.WriteRune(unicode.ToLower(r)) // 小文字に変換して追加
		}
	}

	// 2. 左右から文字を比較して回文かどうかを確認する
	cleanedStr := cleaned.String()
        // cleaned は strings.Builder 型なので、string 型に変換する

	left, right := 0, len(cleanedStr)-1
        // 左端と右端のインデックス. 0 から始まるので、右端は長さ-1

	for left < right {
		if cleanedStr[left] != cleanedStr[right] {
			return false // 左右の文字が異なる場合は回文ではない
		}
		left++  // 左端を右に移動
		right-- // 右端を左に移動
	}

	return true // 左右の文字が全て一致した場合は回文!
}

func main() {
	fmt.Println(isPalindrome("A man, a plan, a canal, Panama!")) // true
	fmt.Println(isPalindrome("Hello, World!"))                   // false
}

Discussion