password-analyzer/stat_keystroke.cpp

81 lines
2.7 KiB
C++
Raw Normal View History

2023-11-03 21:11:37 +08:00
#include <algorithm>
#include <map>
2023-11-05 14:32:03 +08:00
#include <sstream>
2023-11-03 21:11:37 +08:00
#include <vector>
#include "defs.hpp"
const char keyboard[2][4][15] = {{"`1234567890-=", "\0qwertyuiop[]\\", "\0asdfghjkl;'", "\0zxcvbnm,./"},
{"~!@#$%^&*()_+", "\0QWERTYUIOP{}|", "\0ASDFGHJKL:\"", "\0ZXCVBNM<>?"}};
auto string_to_cord(const std::string &password) -> std::vector<Cord> {
std::vector<Cord> ret;
for (auto ch : password) {
for (const auto &kbd : keyboard) {
for (int j = 0; j < 4; ++j) {
auto bgn = kbd[j][0] == '\0' ? 1 : 0;
auto pos = std::strchr(kbd[j] + bgn, ch);
if (pos) {
ret.push_back({j, static_cast<int>(pos - kbd[j])});
break;
}
}
}
}
return ret;
}
auto cord_to_string(const std::vector<Cord> &cords) -> std::string {
std::ostringstream ret;
for (auto cord : cords) {
auto ch = keyboard[0][cord.x][cord.y]; // only consider not shifted keyboard
if (ch != '\0')
ret << ch;
else
spdlog::warn("cord_to_string: invalid cord: ({}, {})", cord.x, cord.y);
}
return ret.str();
}
auto is_neighbour(const Cord &a, const Cord &b) -> bool {
auto [x1, y1] = a;
auto [x2, y2] = b;
auto same = x1 == x2 && y1 == y2; // NOTE: consider the case of `same` is true
return !same && std::abs(x1 - x2) <= 1 && std::abs(y1 - y2) <= 1;
}
void stat_keystroke(const DataSource &source) {
2023-11-04 00:24:22 +08:00
timeit(fmt::format("stat_keystroke({})", magic_enum::enum_name(source)));
2023-11-03 21:11:37 +08:00
std::map<std::string, size_t> stat;
for (auto const &password : passwords(source)) {
if (password.size() <= 1) continue;
auto cords = string_to_cord(password);
if (cords.size() <= 1) continue;
std::string longest;
size_t max_len = 0, cur_len = 1;
for (int i = 0; i < cords.size() - 1; i++) {
auto ok = is_neighbour(cords[i], cords[i + 1]);
if (ok) {
cur_len++;
} else {
if (cur_len > max_len) {
max_len = cur_len;
longest = cord_to_string(
std::vector<Cord>(cords.begin() + (int)(i - cur_len + 1), cords.begin() + i + 1));
}
cur_len = 1;
}
}
2023-11-03 21:28:08 +08:00
if (max_len > 5) stat[longest]++;
2023-11-03 21:11:37 +08:00
}
std::vector<std::pair<std::string, size_t>> vec(stat.begin(), stat.end());
std::sort(vec.begin(), vec.end(), [](auto const &lhs, auto const &rhs) { return lhs.second > rhs.second; });
for (auto const &[length, count] : vec | std::views::take(10)) spdlog::info("{}: {}", length, count);
}