levenshtest.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #include "levenshtein.hpp"
  2. #define STRING_LEN 500
  3. #define TEST_COUNT 500
  4. #include <iostream>
  5. template <class T, typename SIZE=unsigned int>
  6. int levenshtein_base(const T &a, const T &b, const SIZE aSize, const SIZE bSize)
  7. {
  8. int **items = new int*[aSize +1]();
  9. for (SIZE i =0; i <= aSize; i++)
  10. {
  11. items[i] = new int[bSize +1]();
  12. items[i][0] = i;
  13. if (i == 0)
  14. for (SIZE j =1; j <= bSize; j++)
  15. items[i][j] = j;
  16. else
  17. for (SIZE j =1; j <= bSize; j++)
  18. items[i][j] = std::min(std::min(
  19. items[i][j -1] +1,
  20. items[i -1][j] +1),
  21. (items[i -1][j -1] + (a[i -1] == b[j -1] ? 0 : 1)));
  22. }
  23. const int levenshtein = items[aSize][bSize];
  24. for (SIZE i =0; i < aSize +1; i++)
  25. delete[] items[i];
  26. delete[] items;
  27. return levenshtein;
  28. }
  29. bool simpleTest(const std::string &a, const std::string &b, unsigned int expected)
  30. {
  31. unsigned int levenshteinScore;
  32. if ((levenshteinScore = levenshtein(a, b, a.size(), b.size())) != expected)
  33. {
  34. std::cerr << "Error: failed asserting levenshteinScore on file "
  35. << __FILE__ << ":" << __LINE__
  36. << " (got " << levenshteinScore << ") on "
  37. << a << " vs " << b
  38. << std::endl;
  39. return false;
  40. }
  41. if ((levenshteinScore = levenshtein_base(a, b, a.size(), b.size())) != expected)
  42. {
  43. std::cerr << "Error: failed asserting levenshteinScore on file "
  44. << __FILE__ << ":" << __LINE__
  45. << " (got " << levenshteinScore << ")"
  46. << std::endl;
  47. return false;
  48. }
  49. return true;
  50. }
  51. char randomChar()
  52. {
  53. return (rand() % 94) + 32;
  54. }
  55. std::string generateString()
  56. {
  57. std::string str;
  58. for (int i =0; i < STRING_LEN; i++)
  59. str += randomChar();
  60. return str;
  61. }
  62. void speedTest(const std::string &a, const std::string &b)
  63. {
  64. const unsigned int timeBefore = time(NULL);
  65. for (unsigned int i =0; i < TEST_COUNT; ++i)
  66. levenshtein(a, b, a.size(), b.size());
  67. const unsigned int timeMid = time(NULL);
  68. for (unsigned int i =0; i < TEST_COUNT; ++i)
  69. levenshtein_base(a, b, a.size(), b.size());
  70. const unsigned int timeEnd = time(NULL);
  71. std::cout << "Processing items in "
  72. << (float) (1000.f * (timeMid -timeBefore)) / TEST_COUNT
  73. << "ms (optimized) vs "
  74. << (float) (1000.f * (timeEnd -timeMid)) / TEST_COUNT
  75. << "ms" << std::endl;
  76. }
  77. void speedTestEq()
  78. {
  79. std::string a, b;
  80. a = b = generateString();
  81. if (!simpleTest(a, b, 0))
  82. return;
  83. speedTest(a, b);
  84. }
  85. void speedTestAddDel()
  86. {
  87. std::string a, b;
  88. a = generateString();
  89. b = a;
  90. b.erase(rand() % b.size(), 1);
  91. b.erase(rand() % b.size(), 1);
  92. b.erase(rand() % b.size(), 1);
  93. b.insert(rand() % b.size(), std::string(1, randomChar()));
  94. b.insert(rand() % b.size(), std::string(1, randomChar()));
  95. b.insert(rand() % b.size(), std::string(1, randomChar()));
  96. if (!simpleTest(a, b, 6))
  97. return;
  98. speedTest(a, b);
  99. }
  100. void speedTestDiff()
  101. {
  102. std::string a, b;
  103. a = b = generateString();
  104. b[rand() % b.size()] = randomChar();
  105. b[rand() % b.size()] = randomChar();
  106. b[rand() % b.size()] = randomChar();
  107. if (!simpleTest(a, b, 3))
  108. return;
  109. speedTest(a, b);
  110. }
  111. int main()
  112. {
  113. srand(11);
  114. if (!simpleTest("qwerty123", "qwerty123", 0))
  115. exit(EXIT_FAILURE);
  116. if (!simpleTest("abcdefghuijklmnop", "abcdefg0huijk0lmnop", 2))
  117. exit(EXIT_FAILURE);
  118. std::cout << "starting eq speed test" << std::endl;
  119. speedTestEq();
  120. std::cout << "starting add/del speed test" << std::endl;
  121. speedTestAddDel();
  122. std::cout << "starting diff speed test" << std::endl;
  123. speedTestDiff();
  124. exit(EXIT_SUCCESS);
  125. }