420.strong-password-checker.go 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. func strongPasswordChecker(s string) int {
  2. // Missing: insert/delete/replace
  3. // Too short: insert
  4. // Too long: delete
  5. // Repeat: insert/delete/replace
  6. n := len(s)
  7. if n == 0 {
  8. return 6
  9. }
  10. a, A, d, cnt := 1, 1, 1, 0 // Find the cnt of missing and repeat
  11. repeat := make([]int, 0)
  12. pre := rune(s[0])
  13. for _, r := range s {
  14. if 'a' <= r && r <= 'z' {
  15. a = 0
  16. } else if 'A' <= r && r <= 'Z' {
  17. A = 0
  18. } else if '0' <= r && r <= '9' {
  19. d = 0
  20. }
  21. if r == pre {
  22. cnt++
  23. } else {
  24. if 3 <= cnt {
  25. repeat = append(repeat, cnt)
  26. }
  27. cnt = 1
  28. pre = r
  29. }
  30. }
  31. if 3 <= cnt {
  32. repeat = append(repeat, cnt)
  33. }
  34. miss := a + A + d
  35. if n < 6 {
  36. return miss + maxInt(0, 6-n-miss) // Repeat && missing can be both solved by insert
  37. }
  38. exceed, replace, m := maxInt(0, n-20), 0, len(repeat)
  39. res := exceed
  40. for k := 1; k <= 2; k++ { // Smaller k first, cauz aaa -> aa: 1 step, aaaa -> xaa: 2 step
  41. for i := 0; i < m && 0 < exceed; i++ {
  42. if repeat[i] < 3 || repeat[i]%3 != k-1 {
  43. continue
  44. }
  45. dec := minInt(exceed, k)
  46. repeat[i], exceed = repeat[i]-dec, exceed-dec
  47. }
  48. }
  49. for i := 0; i < m; i++ {
  50. if 3 <= repeat[i] && 0 < exceed {
  51. dec := minInt(exceed, repeat[i]-2) // 3k+2 -> 2 to make exceed == 0
  52. repeat[i], exceed = repeat[i]-dec, exceed-dec
  53. }
  54. if 3 <= repeat[i] {
  55. replace += repeat[i] / 3
  56. }
  57. }
  58. return res + maxInt(miss, replace)
  59. }
  60. func minInt(x, y int) int {
  61. if x < y {
  62. return x
  63. }
  64. return y
  65. }
  66. func maxInt(x, y int) int {
  67. if x < y {
  68. return y
  69. }
  70. return x
  71. }