Как я могу определить, находится ли символ рядом с другим символом на QWERTY-клавиатуре?

Я занимаюсь разработкой системы обнаружения спама, и меня предупредили, что она не может обнаружить строки вроде этой - "asdfsdf".

Мое решение этого заключается в обнаружении, если предыдущие клавиши были рядом с другими клавишами на клавиатуре. Я не получаю ввод (для обнаружения спама) с клавиатуры, я получаю его в виде строки.

Все, что я хочу знать, это то, является ли символ одним ключом, двумя ключами или более чем двумя ключами от другого символа.

Например, на современной клавиатуре QWERTY символы "q" и "w" будут на расстоянии 1 клавиши. То же самое с символами 'q' и 's'. Люди могут понять это логически, как я могу сделать это в коде?

5 ответов

Решение

Вы можете просто создать двумерную карту для стандартной клавиатуры qwerty. В принципе это может выглядеть примерно так:

map[0][0] = 'q';
map[0][1] = 'a';
map[1][0] = 'w';
map[1][1] = 's';

и так далее.

Когда вы получаете два символа, вам просто нужно найти их x и y в массиве 'map' выше, и вы можете просто вычислить расстояние, используя пифагоры. Это не будет соответствовать требованию, которое у вас было: "q" и "s" на расстоянии 1 расстояние. Но скорее это будет sqrt (1 ^ 2 + 1 ^ 2) около 1,4

Формула будет:

  • Символы с1 и с2
  • Найти координаты для c1 и c2: (x1, y1) и (x2, y2)
  • Рассчитайте расстояние с помощью Пифагора: dist = sqrt ((x2-x1) ^ 2 + (y2-y1) ^ 2).
  • При необходимости, потолок или пол результат.

Например:

Скажем, вы получаете символы c1= 'q' и c2= 'w'. Изучите карту и найдите, что "q" имеет координаты (x1, y1) = (0, 0), а "w" имеет координаты (x2, y2) = (1, 0). Расстояние

sqrt((1-0)^2 + (0-0)^2) = sqrt(1) = 1

Ну что ж, посмотрим. Это сложный вопрос. Я всегда использую метод грубой силы и держусь подальше от продвинутых концепций, подобных тому парню, которого Пифагор пытался навязать нам, так как насчет двумерного стола? Что-то вроде этого. может быть:

+---+---+---+---+---+---+---
|   | a | b | c | d | f | s ...
+---+---+---+---+---+---+---
| a | 0 | 5 | 4 | 2 | 4 | 1 ...
| b | 5 | 0 | 3 | 3 | 2 | 4 ...
| c | 4 | 3 | 0 | 1 | 2 | 2 ...
| d | 2 | 3 | 1 | 0 | 1 | 1 ...
| f | 3 | 2 | 2 | 1 | 0 | 2 ...
| s | 1 | 4 | 2 | 1 | 2 | 0 ...
+---+---+---+---+---+---+---

Может ли это работать на тебя? Вы могли бы даже иметь отрицательные числа, чтобы показать, что один ключ находится слева от другого. ПЛЮС, вы можете поместить 2-целочисленную структуру в каждую ячейку, где второе целое положительно или отрицательно, чтобы показать, что вторая буква вверх или вниз от первой. Позвони моему патентному поверенному, быстро!

Постройте карту от клавиш до позиций на идеализированной клавиатуре. Что-то вроде:

'q' => {0,0},
'w' => {0,1},
'a' => {1,0},
's' => {1,1}, ...

Тогда вы можете принять "расстояние" в качестве математического расстояния между двумя точками.

Основная идея заключается в создании карты персонажей и их положений на клавиатуре. Затем вы можете использовать простую формулу расстояния, чтобы определить, насколько близко они находятся.

Например, рассмотрим левую сторону клавиатуры:

  1 2 3 4 5 6
  q w e r t
  a s d f g
  z x c v b

символ a имеет позицию [2, 0] и характер b имеет позицию [3, 4], Формула для их расстояния друг от друга:

sqrt((x2-x1)^2 + (y2-y1)^2);

Так что расстояние между a а также b является sqrt((4 - 0)^2 + (3 - 2)^2)

Вам понадобится немного усилий, чтобы отобразить ключи в прямоугольную сетку (мой пример не идеален, но дает вам идею). Но после этого вы можете построить карту (или словарь), и поиск будет простым и быстрым.

Я разработал функцию для той же цели в PHP, потому что хотел посмотреть, могу ли я использовать ее для анализа строк, чтобы выяснить, могут ли они быть спамом.

Это для клавиатуры QWERTZ, но ее легко изменить. Первое число в массиве $keys - приблизительное расстояние слева, а второе - номер строки сверху.

      function string_distance($string){
    $keys=array(
        'q'=>array(1,1),
        'w'=>array(2,1),
        'e'=>array(3,1),
        'r'=>array(4,1),
        't'=>array(5,1),
        'z'=>array(6,1),
        'u'=>array(7,1),
        'i'=>array(8,1),
        'o'=>array(9,1),
        'p'=>array(10,1),
        'a'=>array(1.25,2),
        's'=>array(2.25,2),
        'd'=>array(3.25,2),
        'f'=>array(4.25,2),
        'g'=>array(5.25,2),
        'h'=>array(6.25,2),
        'j'=>array(7.25,2),
        'k'=>array(8.25,2),
        'l'=>array(9.25,2),
        'y'=>array(1.85,3),
        'x'=>array(2.85,3),
        'c'=>array(3.85,3),
        'v'=>array(4.85,3),
        'b'=>array(5.85,3),
        'n'=>array(6.85,3),
        'm'=>array(7.85,3)
    );
    $string=preg_replace("/[^a-z]+/",'',mb_strtolower($string));
    for($i=0;$i+1<mb_strlen($string);$i++){
        $char_a=mb_substr($string,$i,1);
        $char_b=mb_substr($string,$i+1,1);
        $a=abs($keys[$char_a][0]-$keys[$char_b][0]);
        $b=abs($keys[$char_a][1]-$keys[$char_b][1]);
        $distance=sqrt($a^2+$b^2);
        $distances[]=$distance;
    }
    return array_sum($distances)/count($distances);
}

Вы можете использовать это следующим образом.

      string_distance('Boat') # output 2.0332570942187
string_distance('HDxtaBQrGkjny') # output 1.4580596252044

Я использовал многобайтовые функции, потому что думал о расширении их для других символов. Его можно было бы расширить, проверив регистр символов.

Другие вопросы по тегам