A Python robot that edits Wikipedia and interacts with people over IRC https://en.wikipedia.org/wiki/User:EarwigBot
Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

98 linhas
3.5 KiB

  1. # Copyright (C) 2009-2015 Ben Kurtovic <ben.kurtovic@gmail.com>
  2. #
  3. # Permission is hereby granted, free of charge, to any person obtaining a copy
  4. # of this software and associated documentation files (the "Software"), to deal
  5. # in the Software without restriction, including without limitation the rights
  6. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. # copies of the Software, and to permit persons to whom the Software is
  8. # furnished to do so, subject to the following conditions:
  9. #
  10. # The above copyright notice and this permission notice shall be included in
  11. # all copies or substantial portions of the Software.
  12. #
  13. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  19. # SOFTWARE.
  20. from re import UNICODE, sub
  21. __all__ = ["EMPTY", "EMPTY_INTERSECTION", "MarkovChain", "MarkovChainIntersection"]
  22. class MarkovChain:
  23. """Implements a basic ngram Markov chain of words."""
  24. START = -1
  25. END = -2
  26. degree = 5 # 2 for bigrams, 3 for trigrams, etc.
  27. def __init__(self, text):
  28. self.text = text
  29. self.chain = self._build()
  30. self.size = self._get_size()
  31. def _build(self):
  32. """Build and return the Markov chain from the input text."""
  33. padding = self.degree - 1
  34. words = sub(r"[^\w\s-]", "", self.text.lower(), flags=UNICODE).split()
  35. words = ([self.START] * padding) + words + ([self.END] * padding)
  36. chain = {}
  37. for i in range(len(words) - self.degree + 1):
  38. phrase = tuple(words[i : i + self.degree])
  39. if phrase in chain:
  40. chain[phrase] += 1
  41. else:
  42. chain[phrase] = 1
  43. return chain
  44. def _get_size(self):
  45. """Return the size of the Markov chain: the total number of nodes."""
  46. return sum(self.chain.values())
  47. def __repr__(self):
  48. """Return the canonical string representation of the MarkovChain."""
  49. return f"MarkovChain(text={self.text!r})"
  50. def __str__(self):
  51. """Return a nice string representation of the MarkovChain."""
  52. return f"<MarkovChain of size {self.size}>"
  53. class MarkovChainIntersection(MarkovChain):
  54. """Implements the intersection of two chains (i.e., their shared nodes)."""
  55. def __init__(self, mc1, mc2):
  56. self.mc1, self.mc2 = mc1, mc2
  57. self.chain = self._build()
  58. self.size = self._get_size()
  59. def _build(self):
  60. """Build and return the Markov chain from the input chains."""
  61. c1 = self.mc1.chain
  62. c2 = self.mc2.chain
  63. chain = {}
  64. for phrase in c1:
  65. if phrase in c2:
  66. chain[phrase] = min(c1[phrase], c2[phrase])
  67. return chain
  68. def __repr__(self):
  69. """Return the canonical string representation of the intersection."""
  70. res = "MarkovChainIntersection(mc1={0!r}, mc2={1!r})"
  71. return res.format(self.mc1, self.mc2)
  72. def __str__(self):
  73. """Return a nice string representation of the intersection."""
  74. res = "<MarkovChainIntersection of size {0} ({1} ^ {2})>"
  75. return res.format(self.size, self.mc1, self.mc2)
  76. EMPTY = MarkovChain("")
  77. EMPTY_INTERSECTION = MarkovChainIntersection(EMPTY, EMPTY)