diff options
author | Dimitri Sokolyuk <demon@dim13.org> | 2019-07-06 17:17:46 +0200 |
---|---|---|
committer | Dimitri Sokolyuk <demon@dim13.org> | 2019-07-06 17:17:46 +0200 |
commit | 1d2ca509c77cbb2af0475b1319cd840f8ce9a1d0 (patch) | |
tree | 05a838baaf4f96fbcce03d06090a2403ee56c878 /internal/flood | |
parent | 87e820722cf02054225b47a58f97d0824118292f (diff) |
Split in packages
Diffstat (limited to 'internal/flood')
-rw-r--r-- | internal/flood/flood.go | 62 | ||||
-rw-r--r-- | internal/flood/flood_test.go | 51 |
2 files changed, 113 insertions, 0 deletions
diff --git a/internal/flood/flood.go b/internal/flood/flood.go new file mode 100644 index 0000000..b8a71d1 --- /dev/null +++ b/internal/flood/flood.go @@ -0,0 +1,62 @@ +package flood + +import ( + "math" + "sort" + "strings" + "unicode" + "unicode/utf8" +) + +const ( + runes = 6 + words = 6 + black = "\u24B6\u262D\u272F\u262E\u2721\u5350\u534D\u2719\u0FD5\u0FD6\u16CB\uA5A6\u0FD7\u0FD8" +) + +func entropy(s string) (e float64) { + n := make(map[rune]float64) + for _, r := range s { + n[r] += 1 / float64(len(s)) + } + for _, v := range n { + e -= v * math.Log2(v) + } + return e +} + +func Is(s string) bool { + if strings.ContainsAny(s, black) { + return true + } + if utf8.RuneCountInString(s) <= runes { + return false + } + if v := strings.Fields(s); len(v) >= words { + return commonWord(v) >= len(v)/2 + } + return entropy(s) <= 1 +} + +func commonWord(v []string) int { + m := make(map[string]int) + for _, w := range v { + m[w]++ + } + l := make([]int, len(m)) + for _, n := range m { + l = append(l, n) + } + sort.Sort(sort.Reverse(sort.IntSlice(l))) + return l[0] +} + +func noSpaceCompare(a, b string) bool { + dropSpaces := func(r rune) rune { + if unicode.IsSpace(r) { + return -1 + } + return r + } + return strings.Map(dropSpaces, a) == strings.Map(dropSpaces, b) +} diff --git a/internal/flood/flood_test.go b/internal/flood/flood_test.go new file mode 100644 index 0000000..c16da7c --- /dev/null +++ b/internal/flood/flood_test.go @@ -0,0 +1,51 @@ +package flood + +import "testing" + +func TestFlood(t *testing.T) { + testCases := []struct { + line string + ok bool + }{ + {`! ! ! ! ! ! ! !`, true}, + {`test test test test abc abc`, true}, + {`! test ! test ! test ! test !`, true}, + {`a b c d e f g h i j`, false}, + {`const union __infinity_un __infinity = { { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f } };`, false}, + {`a = b > 3 ? 2 : 4`, false}, + {`AAAAAAAAAAAAAAAAAAAA`, true}, + {`AAAAAAAAAABBBBBBBBBB`, true}, + {`ivy 3 3 rho (iota 9) in 2 6 7 8 9`, false}, + {"\u262etest", true}, + } + for _, tc := range testCases { + t.Run(tc.line, func(t *testing.T) { + if Is(tc.line) != tc.ok { + t.Errorf("want %v", tc.ok) + } + }) + } +} + +func TestNoSpaceCompare(t *testing.T) { + testCases := []struct { + a, b string + ok bool + }{ + {"", "", true}, + {"x", "", false}, + {"", "x", false}, + {"x ", "x", true}, + {" x", "x", true}, + {"x x", "xx", true}, + {"x x x", "x", false}, + } + for _, tc := range testCases { + t.Run(tc.a+"?"+tc.b, func(t *testing.T) { + ok := noSpaceCompare(tc.a, tc.b) + if ok != tc.ok { + t.Errorf("got %v; want %v", ok, tc.ok) + } + }) + } +} |