package main import ( "bufio" "io" "os" "strconv" ) // --------------------------------------------------------------------------- // 入出力 // 標準入力を最初に丸ごと読み込み、バイト列から直接切り出す。 // - トークン長に上限がない(bufio.Scanner のような ErrTooLong が起きない) // - 単語読み(ri/rs)と行読み(rline)を自由に混ぜられる // - 空白・タブ・改行はすべて同じ区切り。末尾の改行の有無は結果に影響しない // 代償として入力全体がメモリに載る。AtCoder の入力規模なら問題にならない。 // 出力は必ず wr 経由。main の defer で 1 度だけ Flush する。 // --------------------------------------------------------------------------- var ( data []byte // 標準入力の全体 pos int // 次に読む位置 wr = bufio.NewWriter(os.Stdout) ) func main() { _ = ri() S := rs() count := 0 for i := 0; i < len(S)-5; i++ { if S[i:i+5] == "HAPPY" { count++ } } l := len(S) - 5 P := "HAPPY" for i, s := range S[l : l+5] { if P[i] != byte(s) { count++ } } outln(count) defer wr.Flush() } // --- 入力 ------------------------------------------------------------------- // init は標準入力を全部 data に読み込む。 // main の中に置くと、解答を書くときに消えてしまって読み取りが全部 EOF になるため、 // あえて main の外に置いている。ここは消さないこと。 func init() { var err error data, err = io.ReadAll(bufio.NewReaderSize(os.Stdin, 1<<20)) if err != nil { panic(err) } } // skipSpace は空白類(スペース・タブ・改行など ' ' 以下のバイト)を読み飛ばす。 func skipSpace() { for pos < len(data) && data[pos] <= ' ' { pos++ } } // rbs はトークンを 1 つ、コピーせずに []byte のまま返す。 // 戻り値は入力バッファそのものを指すので、書き換えると入力が変わる。 // 使い終わるまで保持しておくのは自由(入力全体が生きているため)。 func rbs() []byte { skipSpace() start := pos for pos < len(data) && data[pos] > ' ' { pos++ } return data[start:pos] } // rs はトークンを 1 つ読む(文字列としてコピーする)。 func rs() string { return string(rbs()) } // ri は整数を 1 つ読む。数字以外が混ざっていたら panic して気づけるようにする。 func ri() int { skipSpace() if pos >= len(data) { panic("入力を読みすぎている (EOF)") } neg := false switch data[pos] { case '-': neg = true pos++ case '+': pos++ } start := pos n := 0 for pos < len(data) && data[pos] > ' ' { c := data[pos] if c < '0' || c > '9' { panic("整数として読めない: " + string(data[start:pos+1])) } n = n*10 + int(c-'0') pos++ } if pos == start { panic("整数がない") } if neg { return -n } return n } // rf は浮動小数を 1 つ読む。 func rf() float64 { f, err := strconv.ParseFloat(string(rbs()), 64) if err != nil { panic(err) } return f } // ri2 / ri3 は整数をまとめて読む。`a, b := ri2()` のように使う。 func ri2() (int, int) { return ri(), ri() } func ri3() (int, int, int) { return ri(), ri(), ri() } // ris は整数を n 個読む。 func ris(n int) []int { a := make([]int, n) for i := range a { a[i] = ri() } return a } // rss はトークンを n 個読む。 func rss(n int) []string { a := make([]string, n) for i := range a { a[i] = rs() } return a } // rgrid は h 行の文字列グリッドを読む。g[i][j] でアクセスする。 // 各行は入力バッファを指すだけなのでコピーが起きない。書き換えても構わない // (行どうしは重ならない)が、書き換えた内容は rline などからも見える。 func rgrid(h int) [][]byte { g := make([][]byte, h) for i := range g { g[i] = rbs() } return g } // rline は次の 1 行を、行内の空白を保ったまま返す。 // 直前のトークンの後ろに残っている改行と、空行は読み飛ばす。 func rline() string { for pos < len(data) && (data[pos] == '\n' || data[pos] == '\r') { pos++ } start := pos for pos < len(data) && data[pos] != '\n' { pos++ } end := pos if end > start && data[end-1] == '\r' { // CRLF の \r を落とす end-- } if pos < len(data) { pos++ // 行末の改行を捨てる } return string(data[start:end]) } // --- 出力 ------------------------------------------------------------------- // obuf は数値を文字列化するときの作業領域。使い回して確保を避ける。 var obuf []byte func writeInt(x int) { obuf = strconv.AppendInt(obuf[:0], int64(x), 10) wr.Write(obuf) } // outln は値を空白区切りで並べて改行する。 func outln(a ...any) { for i, v := range a { if i > 0 { wr.WriteByte(' ') } writeAny(v) } wr.WriteByte('\n') } // outis は整数スライスを空白区切り 1 行で出力する。 func outis(a []int) { for i, v := range a { if i > 0 { wr.WriteByte(' ') } writeInt(v) } wr.WriteByte('\n') } // yesno は真偽を Yes / No で出力する。 func yesno(ok bool) { if ok { wr.WriteString("Yes\n") } else { wr.WriteString("No\n") } } func writeAny(v any) { switch x := v.(type) { case int: writeInt(x) case int64: obuf = strconv.AppendInt(obuf[:0], x, 10) wr.Write(obuf) case string: wr.WriteString(x) case []byte: wr.Write(x) case byte: wr.WriteByte(x) case float64: obuf = strconv.AppendFloat(obuf[:0], x, 'f', 10, 64) wr.Write(obuf) case bool: if x { wr.WriteString("true") } else { wr.WriteString("false") } default: panic("outln: 対応していない型") } } // --- よく使う小物 ----------------------------------------------------------- // min / max は Go 1.21 以降の組み込みを package スコープで覆う。 // AtCoder 側が Go 1.20 系でも同じコードが通るように、あえて自前で定義している。 type number interface { ~int | ~int64 | ~float64 } func min[T number](a, b T) T { if a < b { return a } return b } func max[T number](a, b T) T { if a > b { return a } return b } // chmin / chmax は代入して更新できたら true を返す。DP の更新で使う。 func chmin[T number](a *T, b T) bool { if b < *a { *a = b return true } return false } func chmax[T number](a *T, b T) bool { if b > *a { *a = b return true } return false } func abs(a int) int { if a < 0 { return -a } return a }