Набор однозначных букв и цифр для ввода пользователем

Существует ли существующее подмножество буквенно-цифровых символов, которое легче читать? В частности, существует ли подмножество с меньшим количеством символов, которые визуально неоднозначны, и путем удаления (или приравнивания) определенных символов мы уменьшаем человеческую ошибку?

Я знаю, что "визуально двусмысленный" несколько противоречит выражению, но довольно очевидно, что D, O и 0 все одинаковы, а 1 и я тоже похожи. Я хотел бы максимизировать размер набора альфа-чисел, но свести к минимуму количество символов, которые могут быть неверно истолкованы.

Единственным прецедентом, о котором я знаю для такого набора, является система

Ответ 1

В основном черпает вдохновение в этой ветке ux, упомянутой @rwb,

  • Несколько программ используют похожие вещи. Список в вашем посте, похоже, очень похож на те, которые используются в этих программах, и я думаю, что этого должно быть достаточно для большинства целей. Вы всегда можете добавить избыточность (исправление ошибок), чтобы "простить" мелкие ошибки; это потребует от вас разметки кодов (см. расстояние Хемминга).
  • Нет ссылок на конкретный метод, используемый при составлении списков, кроме проб и ошибок с людьми (что отлично подходит для не-ocr: ваши пользователи люди)
  • Возможно, имеет смысл использовать группировку символов (скажем, группы по 5) для увеличения контекста ("первый символ во второй из 5 групп")
  • Неоднозначность можно устранить, используя вместо символов полные существительные (из словаря с несколькими подобными; здесь может быть полезно слово-расстояние-редактирования). Люди могут путать "1" с "i", но немногие путают "один" со "льдом".
  • Другой вариант - превратить ваш код в (фальшивое) слово, которое можно прочитать вслух. Марковская модель может помочь вам в этом.

Ответ 2

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

0 1 2 3 4 5 6 7 8 9 A B C D E F     Hexadecimal
H M N 3 4 P 6 7 R 9 T W C X Y F     Replacement

В наборе замещения рассмотрим следующее:

Все используемые символы имеют основные отличительные черты, которые будут опущены только по-настоящему ужасным шрифтом.

Гласные буквы E я O U не позволяют случайно произнести слова.

Наборы символов, которые потенциально могут быть очень похожи или идентичны в некоторых шрифтах, полностью исключаются (ни один из символов в любом наборе не используется вообще):

0 O D Q 
1 I L J
8 B 
5 S
2 Z

Избегая этих символов полностью, надежда состоит в том, что пользователь вводит правильные символы, а не пытается исправить неправильно введенные символы.

Для наборов менее похожих, но потенциально запутанных символов, мы используем только один символ в каждом наборе, мы надеемся, наиболее отличительный:

Y U V 

Здесь используется Y, так как он всегда имеет нижний вертикальный разрез и засечку в сериновых шрифтах

C G         

Здесь C используется, так как кажется менее вероятным, что C будет введен как G, чем наоборот

X K         

Здесь используется X, поскольку он более согласован в большинстве шрифтов

F E         

Здесь F используется, так как это не гласный

В случае подобных наборов запись любого символа в наборе может быть автоматически преобразована в тот, который фактически используется (первый из них указан в каждом наборе). Обратите внимание, что E не должен автоматически преобразовываться в F, если может использоваться шестнадцатеричный ввод (см. Ниже).

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

Если символы, которые также присутствуют в стандартном шестнадцатеричном формате, используются в наборе замещения, они используются для одного и того же значения base-16. Теоретически может поддерживаться смешанный ввод шестнадцатеричных и замещающих символов, если E не будет автоматически преобразован в F.

Поскольку это просто замена символа, его легко преобразовать в/из шестнадцатеричного.

Верхний регистр лучше всего подходит для "канонической" формы для вывода, хотя в нижнем регистре также выглядит разумно, за исключением "h" и "n", который должен быть относительно ясен в большинстве шрифтов:

h m n 3 4 p 6 7 r 9 t w c x y f

Ввод может, конечно, быть нечувствительным к регистру.

Существует несколько подобных систем для базы 32, см. http://en.wikipedia.org/wiki/Base32 Однако они, очевидно, должны ввести более похожие символы, в обмен на дополнительно на 25% больше информации для каждого персонажа.

По-видимому, следующий набор был также использован для ключей продуктов Windows в базе 24, но снова имеет больше похожих символов:

B C D F G H J K M P Q R T V W X Y 2 3 4 6 7 8 9

Ответ 3

Это была бы общая проблема в OCR. Таким образом, для конечного решения, где в кодировании OCR контролируется - специализированные шрифты были разработаны для решения проблемы "визуальной двусмысленности", о которой вы упоминаете. См.: http://en.wikipedia.org/wiki/OCR-A_font

в качестве дополнительной информации: вы можете знать о Base32 Encoding - где символ для цифры "1" не используется, поскольку он может "путать" пользователей с символом для алфавита "l".

Ответ 4

То, что вы ищете, - это однозначный, эффективный человеко-компьютерный код. Я рекомендую кодировать все данные с буквальными (значимыми) словами, в частности именами.

Я разрабатываю программное обеспечение для этого - и наиболее эффективно. Я называю это WCode.
Технически его просто кодировка Base-1024 - в которой вы используете слова вместо символов.

Вот ссылки:
Презентация: https://docs.google.com/presentation/d/1sYiXCWIYAWpKAahrGFZ2p5zJX8uMxPccu-oaGOajrGA/edit
Документация: https://docs.google.com/folder/d/0B0pxLafSqCjKOWhYSFFGOHd1a2c/edit
Проект: https://github.com/San13/WCode (Подождите, пока я начну загружать...)

Ответ 5

Мой набор из 22 однозначных символов:

c,d,f,h,j,k,m,n,p,r,t,v,w,x,y,2,3,4,5,6,8,9

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

Мои требования:

  1. Без заглавных букв: предполагается, что они используются в URI и набираются людьми, у которых может не быть большого опыта ввода, для которых даже клавиша Shift может замедлить их и вызвать неопределенность. Я также хочу, чтобы кто-то мог сказать "все строчные", чтобы уменьшить неопределенность, поэтому я хочу избегать прописных букв.

  2. Мало или нет гласных: простой способ избежать ненормативной лексики или удивительных слов - просто опустить большинство гласных. Я думаю, что держать "у" в порядке.

  3. Устранить неоднозначность последовательно: я открыт для использования некоторых неоднозначных символов, при условии, что я использую только один символ из каждой группы (например, из строчных s, прописных S и пять, я мог бы использовать только пять); таким образом, на бэкэнде я могу просто заменить любой из этих неоднозначных символов одним правильным символом из их группы. Таким образом, входная строка "3Sh" будет заменена на "35h", прежде чем я найду ее соответствие в своей базе данных.

  4. Требуется только для создания токенов: мне не нужно кодировать информацию, как это делают base64 или base32, поэтому точное количество символов в моем наборе не имеет большого значения, кроме того, что я хочу быть как можно большим. Это нужно только для получения случайных токенов идентификатора типа UUID.

  5. Настоятельно предпочитаю не двусмысленность: я думаю, что для кого-то гораздо дороже ввести токен и что-то пошло не так, чем для того, чтобы кто-то набрал более длинный токен. Конечно, есть компромисс, но я хочу сильно предпочесть не двусмысленность, а краткость.

Я определил группы персонажей, которых можно смущать:

  • А /4
  • б /6/G
  • 8/B
  • C/C
  • F/F
  • 9/г/кв
  • i/I/1/l/7 - слишком неоднозначно для использования; обратите внимание, что европейский "1" может выглядеть очень похоже на многих людей "7"
  • K/K
  • o/O/0 - слишком двусмысленно, чтобы использовать
  • P/P
  • S/S/5
  • V/V
  • ж/Вт
  • X/X
  • г/г
  • г /Z/2

Однозначные символы:

Я думаю, что это оставляет только 8 совершенно однозначных строчных/цифровых символов без гласных:

d,h,j,m,n,r,t,3

Добавляя по одному символу от каждой из этих неоднозначных групп (и пытаясь отдать предпочтение символу, который выглядит наиболее отчетливо, избегая прописных букв), получим 22 символа:

c,d,f,h,j,k,m,n,p,r,t,v,w,x,y,2,3,4,5,6,8,9

Анализ:

Используя эмпирическое правило, достаточно UUID с числовым эквивалентным диапазоном из N возможностей, чтобы избежать коллизий для экземпляров sqrt (N):

  • 8-значный UUID, использующий этот набор символов, должен быть достаточным, чтобы избежать коллизий примерно для 200 000 экземпляров
  • 16-значный UUID, использующий этот набор символов, должен быть достаточным, чтобы избежать коллизий примерно для 50 миллиардов экземпляров.

Ответ 6

Это зависит от того, насколько большой вы хотите, чтобы ваш набор был. Например, просто набор {0, 1}, вероятно, будет работать хорошо. Аналогично набор цифр. Но, вероятно, вам нужен набор, который примерно в два раза меньше исходного набора символов.

Я не сделал этого, но вот предложение. Выберите шрифт, выберите начальный набор символов и напишите код, чтобы сделать следующее. Нарисуйте каждый символ, чтобы он поместился в квадрат n-на-n черно-белых пикселей, для n = 1 (скажем) 10. Отрежьте все белые строки и столбцы с края, так как нас интересует только черная область. Это дает вам список из 10 кодов для каждого символа. Измерьте расстояние между любыми двумя символами, сколько из этих кодов отличается. Оцените, какое расстояние приемлемо для вашего приложения. Затем выполните поиск грубой силы для набора символов, которые находятся далеко друг от друга.

В принципе, используйте script, чтобы имитировать косоглазие над символами и посмотреть, какие из них вы можете рассказать отдельно.

Ответ 7

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

def base20encode(i):
    """Convert integer into base20 string of unambiguous characters."""
    if not isinstance(i, int):
        raise TypeError('This function must be called on an integer.')     
    chars, s = '012345689ACEHKMNPRUW', ''
    while i > 0:
        i, remainder = divmod(i, 20)
        s = chars[remainder] + s
    return s


def base20decode(s):
    """Convert string to unambiguous chars and then return integer from resultant base20"""
    if not isinstance(s, str):
        raise TypeError('This function must be called on a string.')
    s = s.translate(bytes.maketrans(b'BGDOQFIJLT7KSVYZ', b'8C000E11111X5UU2'))
    chars, i, exponent = '012345689ACEHKMNPRUW', 0, 1
    for number in s[::-1]:
        i += chars.index(number) * exponent
        exponent *= 20
    return i


base20decode(base20encode(10))