-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement CLI suggestions in case of errors thanks to Levenshtein dis…
…tance to all option names computation
- Loading branch information
Showing
7 changed files
with
144 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#pragma once | ||
|
||
#include <string_view> | ||
|
||
#include "cct_vector.hpp" | ||
|
||
namespace cct { | ||
class LevenshteinDistanceCalculator { | ||
public: | ||
LevenshteinDistanceCalculator() noexcept = default; | ||
|
||
/// Computes the levenshtein distance between both input words. | ||
/// Complexity is in 'word1.length() * word2.length()' in time, | ||
/// min(word1.length(), word2.length()) in space. | ||
int operator()(std::string_view word1, std::string_view word2); | ||
|
||
private: | ||
// This is only for caching purposes, so that repeated calls to distance calculation do not allocate memory each time | ||
vector<int> _minDistance; | ||
}; | ||
} // namespace cct |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
#include "levenshteindistancecalculator.hpp" | ||
|
||
#include <algorithm> | ||
#include <numeric> | ||
|
||
namespace cct { | ||
int LevenshteinDistanceCalculator::operator()(std::string_view word1, std::string_view word2) { | ||
if (word1.size() > word2.size()) { | ||
std::swap(word1, word2); | ||
} | ||
|
||
const int l1 = static_cast<int>(word1.size()) + 1; | ||
if (l1 > static_cast<int>(_minDistance.size())) { | ||
// Favor insert instead of resize to ensure reallocations are exponential | ||
_minDistance.insert(_minDistance.end(), l1 - _minDistance.size(), 0); | ||
} | ||
|
||
std::iota(_minDistance.begin(), _minDistance.end(), 0); | ||
|
||
const int l2 = static_cast<int>(word2.size()) + 1; | ||
for (int word2Pos = 1; word2Pos < l2; ++word2Pos) { | ||
int previousDiagonal = _minDistance[0]; | ||
|
||
++_minDistance[0]; | ||
|
||
for (int word1Pos = 1; word1Pos < l1; ++word1Pos) { | ||
const int previousDiagonalSave = _minDistance[word1Pos]; | ||
if (word1[word1Pos - 1] == word2[word2Pos - 1]) { | ||
_minDistance[word1Pos] = previousDiagonal; | ||
} else { | ||
_minDistance[word1Pos] = | ||
std::min(std::min(_minDistance[word1Pos - 1], _minDistance[word1Pos]), previousDiagonal) + 1; | ||
} | ||
previousDiagonal = previousDiagonalSave; | ||
} | ||
} | ||
|
||
return _minDistance[l1 - 1]; | ||
} | ||
} // namespace cct |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
#include "levenshteindistancecalculator.hpp" | ||
|
||
#include <gtest/gtest.h> | ||
|
||
namespace cct { | ||
|
||
TEST(LevenshteinDistanceCalculator, CornerCases) { | ||
LevenshteinDistanceCalculator calc; | ||
|
||
EXPECT_EQ(calc("", "tata"), 4); | ||
EXPECT_EQ(calc("tutu", ""), 4); | ||
} | ||
|
||
TEST(LevenshteinDistanceCalculator, SimpleCases) { | ||
LevenshteinDistanceCalculator calc; | ||
|
||
EXPECT_EQ(calc("horse", "ros"), 3); | ||
EXPECT_EQ(calc("intention", "execution"), 5); | ||
EXPECT_EQ(calc("niche", "chien"), 4); | ||
} | ||
|
||
TEST(LevenshteinDistanceCalculator, TypicalCases) { | ||
LevenshteinDistanceCalculator calc; | ||
|
||
EXPECT_EQ(calc("--orderbook", "orderbook"), 2); | ||
EXPECT_EQ(calc("--timeout-match", "--timeot-match"), 1); | ||
EXPECT_EQ(calc("--no-multi-trade", "--no-mukti-trade"), 1); | ||
EXPECT_EQ(calc("--updt-price", "--update-price"), 2); | ||
} | ||
|
||
TEST(LevenshteinDistanceCalculator, ExtremeCases) { | ||
LevenshteinDistanceCalculator calc; | ||
|
||
EXPECT_EQ( | ||
calc( | ||
"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the " | ||
"industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and " | ||
"scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into " | ||
"electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release " | ||
"of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software " | ||
"like Aldus PageMaker including versions of Lorem Ipsum.", | ||
"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the " | ||
"industrj's standard dummytext ever since the 1500s, when an unknown printer took a galley of type and " | ||
"scrambled iT to make a type specimen book. I has survived not only five centuroes, but also the leap into " | ||
"electronic typesetting, i remaining essentially unchanged. It was popularised in the 1960s with the release " | ||
"of Letraset sheets; containing Lorem Ipsum passages, and more recently with desktogp publishing software " | ||
"like Aldus PageMaker including versions of Lorem Ipsum."), | ||
9); | ||
} | ||
} // namespace cct |