mirror of
https://github.com/gopl-zh/gopl-zh.github.com.git
synced 2024-11-25 07:38:57 +00:00
149 lines
3.2 KiB
Go
149 lines
3.2 KiB
Go
|
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
|
|||
|
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
|
|||
|
|
|||
|
package word
|
|||
|
|
|||
|
import (
|
|||
|
"fmt"
|
|||
|
"math/rand"
|
|||
|
"time"
|
|||
|
)
|
|||
|
|
|||
|
//!+bench
|
|||
|
|
|||
|
import "testing"
|
|||
|
|
|||
|
//!-bench
|
|||
|
|
|||
|
//!+test
|
|||
|
func TestIsPalindrome(t *testing.T) {
|
|||
|
var tests = []struct {
|
|||
|
input string
|
|||
|
want bool
|
|||
|
}{
|
|||
|
{"", true},
|
|||
|
{"a", true},
|
|||
|
{"aa", true},
|
|||
|
{"ab", false},
|
|||
|
{"kayak", true},
|
|||
|
{"detartrated", true},
|
|||
|
{"A man, a plan, a canal: Panama", true},
|
|||
|
{"Evil I did dwell; lewd did I live.", true},
|
|||
|
{"Able was I ere I saw Elba", true},
|
|||
|
{"été", true},
|
|||
|
{"Et se resservir, ivresse reste.", true},
|
|||
|
{"palindrome", false}, // non-palindrome
|
|||
|
{"desserts", false}, // semi-palindrome
|
|||
|
}
|
|||
|
for _, test := range tests {
|
|||
|
if got := IsPalindrome(test.input); got != test.want {
|
|||
|
t.Errorf("IsPalindrome(%q) = %v", test.input, got)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//!-test
|
|||
|
|
|||
|
//!+bench
|
|||
|
func BenchmarkIsPalindrome(b *testing.B) {
|
|||
|
for i := 0; i < b.N; i++ {
|
|||
|
IsPalindrome("A man, a plan, a canal: Panama")
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//!-bench
|
|||
|
|
|||
|
//!+example
|
|||
|
|
|||
|
func ExampleIsPalindrome() {
|
|||
|
fmt.Println(IsPalindrome("A man, a plan, a canal: Panama"))
|
|||
|
fmt.Println(IsPalindrome("palindrome"))
|
|||
|
// Output:
|
|||
|
// true
|
|||
|
// false
|
|||
|
}
|
|||
|
|
|||
|
//!-example
|
|||
|
|
|||
|
/*
|
|||
|
//!+random
|
|||
|
import "math/rand"
|
|||
|
|
|||
|
//!-random
|
|||
|
*/
|
|||
|
|
|||
|
//!+random
|
|||
|
// randomPalindrome returns a palindrome whose length and contents
|
|||
|
// are derived from the pseudo-random number generator rng.
|
|||
|
func randomPalindrome(rng *rand.Rand) string {
|
|||
|
n := rng.Intn(25) // random length up to 24
|
|||
|
runes := make([]rune, n)
|
|||
|
for i := 0; i < (n+1)/2; i++ {
|
|||
|
r := rune(rng.Intn(0x1000)) // random rune up to '\u0999'
|
|||
|
runes[i] = r
|
|||
|
runes[n-1-i] = r
|
|||
|
}
|
|||
|
return string(runes)
|
|||
|
}
|
|||
|
|
|||
|
func TestRandomPalindromes(t *testing.T) {
|
|||
|
// Initialize a pseudo-random number generator.
|
|||
|
seed := time.Now().UTC().UnixNano()
|
|||
|
t.Logf("Random seed: %d", seed)
|
|||
|
rng := rand.New(rand.NewSource(seed))
|
|||
|
|
|||
|
for i := 0; i < 1000; i++ {
|
|||
|
p := randomPalindrome(rng)
|
|||
|
if !IsPalindrome(p) {
|
|||
|
t.Errorf("IsPalindrome(%q) = false", p)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//!-random
|
|||
|
|
|||
|
/*
|
|||
|
// Answer for Exercicse 11.1: Modify randomPalindrome to exercise
|
|||
|
// IsPalindrome's handling of punctuation and spaces.
|
|||
|
|
|||
|
// WARNING: the conversion r -> upper -> lower doesn't preserve
|
|||
|
// the value of r in some cases, e.g., µ Μ, ſ S, ı I
|
|||
|
|
|||
|
// randomPalindrome returns a palindrome whose length and contents
|
|||
|
// are derived from the pseudo-random number generator rng.
|
|||
|
func randomNoisyPalindrome(rng *rand.Rand) string {
|
|||
|
n := rng.Intn(25) // random length up to 24
|
|||
|
runes := make([]rune, n)
|
|||
|
for i := 0; i < (n+1)/2; i++ {
|
|||
|
r := rune(rng.Intn(0x200)) // random rune up to \u99
|
|||
|
runes[i] = r
|
|||
|
r1 := r
|
|||
|
if unicode.IsLetter(r) && unicode.IsLower(r) {
|
|||
|
r = unicode.ToUpper(r)
|
|||
|
if unicode.ToLower(r) != r1 {
|
|||
|
fmt.Printf("cap? %c %c\n", r1, r)
|
|||
|
}
|
|||
|
}
|
|||
|
runes[n-1-i] = r
|
|||
|
}
|
|||
|
return "?" + string(runes) + "!"
|
|||
|
}
|
|||
|
|
|||
|
func TestRandomNoisyPalindromes(t *testing.T) {
|
|||
|
// Initialize a pseudo-random number generator.
|
|||
|
seed := time.Now().UTC().UnixNano()
|
|||
|
t.Logf("Random seed: %d", seed)
|
|||
|
rng := rand.New(rand.NewSource(seed))
|
|||
|
|
|||
|
n := 0
|
|||
|
for i := 0; i < 1000; i++ {
|
|||
|
p := randomNoisyPalindrome(rng)
|
|||
|
if !IsPalindrome(p) {
|
|||
|
t.Errorf("IsNoisyPalindrome(%q) = false", p)
|
|||
|
n++
|
|||
|
}
|
|||
|
}
|
|||
|
fmt.Fprintf(os.Stderr, "fail = %d\n", n)
|
|||
|
}
|
|||
|
*/
|