В контексте игр симуляция работы светофора тоже исторически относится к ИИ — это же конечный автомат всё-таки :)
Интеллектуально это или нет — можно легко определить просто поставив человека (как эталон интеллектуальности) в те же самые условия что и ИИ — и сравнить результат.
Такая разновидность теста Тьюринга — посадить человека в изолированную коробку-светофор и дать ему часы. Сравнить результаты. :)
Вот если кроме часов в светофоре ещё стоит камера или какие-то дополнительные датчики — то в таких условиях ИИ соревноваться с человеком сложнее.
P.S. Если SQL скрипт играет в шахматы/шашки/крестики-нолики не хуже среднестатистического обывателя, почему бы не назвать его интеллектуальным? :)
Да! Вы можете предложить более интеллектуальный результат сортировки чисел? :)
Конкретно в игровом ИИ в результате сортировки ингда были бы ещё и ошибки для пущей «человечности» :)
Да, чтобы называться Искусственным Интеллектом безусловно нужно больше циклов, условий и хешей :)
Первая статья по-моему хорошо получилась, с картинками. Поздравления автору!
Увы, «интеллектуальность» зависит лишь от полученных результатов по сравнению с человеческими. В случае поставленной задачи нахождения пути — результат близок к человеческому, естественному. Да, можно сказать что сама задача не особо интеллектуальная, однако:
— алгоритм отмечает обработанные узлы (обучается)
— алгоритм работает на разных связных графах (адаптивность)
— итерации поиска по смежным узлам продолжаются до успеха (итеративность)
P.S. На нейросети тоже можно сказать «банальный алгоритм без какой-либо изящности» :)
A* — это уже достаточно интеллектуально :)
В контексте игр бот и есть ИИ.
Интеллектуальность ИИ в играх заключается в том, чтобы с ботами было интересно играть — и это достаточно сложная задача. Например для ботов не сложно идеально перемещаться и стрелять без промаха. Бот может всегда видеть и слышать игрока, но при этом должен вести себя так, чтобы игроку было интересно его побеждать.
ИИ, который всегда обыгрывает человека в шахматы — достижение чисто научное.
В контексте же развлекательных игр — бот, который попадает в голову игроку в движении из пистолета с 500 метров — это провал. Задача победить человека любой ценой там не стоит — она давно решена классическими методами. В играх задачи ИИ идут гораздо дальше чем просто победить :)
Это смотря как считать что лучше. Многие операции можно выполнять параллельно/одновременно, и хотя суммарное число операций при этом будет больше, по времени это будет быстрее.
Возможность сделать красиво целых 5 языков — это замечательно.
Кстати комментарий очень полезный — он как раз наглядно показывает зачем и почему Fluent :). Удачи в этом нелёгком деле.
P.S. При работе только с аутсорсом преимущества Fluent не так хорошо выражены. На примере с plural gettext явно выдаёт нужное количество форм на перевод, но всё равно иногда (не часто) переводчиков приходится дополнительно просить, чтобы различные формы вообще использовали в переводе o_O.
P.P.S. Доля сообщений/текстов, требующих дополнительной языко-зависимой логики построения обычно не так велика, чтобы это было какой-то острой проблемой, но всё зависит от типа приложений.
Про «селекторы» я имел ввиду, что для того, чтобы логика построения в Fluent работала, разработчики всё равно должны передать число, род в саму систему — в контекст сообщения. Вместо явной привязки к конкретному сообщению эти дополнительные данные привязываются к сущности в Fluent являющимися контекстом для сообщений. Разработчик должен откуда-то взять род/число/социальный статус/возраст (и прочие «селекторы») и передать их в Fluent — должен знать что они там нужны (пусть даже и не понимать как и зачем они используются).
Но в обоих случаях у программиста обычно нет знаний такого количества человеческих языков, чтобы во всех нужных местах подставить селекторы и прочее.
Переводчик не сможет использовать селектор по роду/числу, если этих данных у него нет. А передать их может только разработчик.
Не все компании могут себе позволить держать штатных переводчиков/локализаторов :(.
Разработчик всё равно должен передать все «селекторы» из кода, просто дальнейшая логика работы по построению сообщения сброшена на «локализаторов/переводчиков/UX-writerов». Гибкость Fluent усложняет оценку затрат на переводы и тестирование/контроль качества.
Для всяких энтузиастов и опенсорса это хорошее решение, но в мире коммерческих переводов, где цена зависит от объема текста — маловероятно что переводчики будут заморачиваться с логикой без дополнительных капиталовложений. Почему переводчик на русский должен писать целую пачку сообщений с учётом комбинаций числа и рода, в то время когда в английском это была лишь пара строк?
(Переведут «Сообщений: X» и хватит :) )
gettext довольно строго регламентирует plural, изначально требуя все формы, необходимые с учётом языка. Хотя это и дубово — это фиксированный и заранее известный объем работы для переводчиков и QA. А вот креатив с Fluent уже не так прост и предсказуем.
Да, можно форматировать дату на любой локали, которая поддерживается ОС независимо от текущей. Это никак не относится к gettext, обычно это стандартная библиотека.
Не обязательно локаль браузера/ОС соответствует локали сайта/продукта, и получается мешанина из, например, английского текста и китайской даты.
Эмм… я не писал о том что нужно обязательно использовать текущую локаль браузера/ОС. Обычно ОС поддерживает вполне солидный набор локалей, можно выбрать наиболее подходящую, не обязательно текущую/по умолчанию.
При взаимодействии с другими программами в GNU/Linux например скорее всего они (другие программы) будут использовать текущую локаль системы и для консистентности продукт должен работать так-же
Ну тогда по технической части мелкие неточности, кроме уже указанных
Идентификатор сообщения: исходная строка
Обычно да, но есть ещё msgctx точнее было бы написать контекст + исходная строка
не умеет работать с форматированием дат и чисел
Fluent активно использует стандартизованные библиотеки и алгоритмы CLDR, ICU
В большинстве случаев форматированием дат и чисел уже занимаются функции ОС/браузера/окружения, которые как раз и используют ICU(CLDR) и gettext этому никак не мешает. В том же JavaScript этим обычно занимается Intl, и он существует независимо от Fluent.
Шаблоны сообщений: необходимы (.pot)
Но ведь .ftl и есть тот самый шаблон. Непосредственно для переводчиков сам .pot не нужен — после генерации и обновления .po файлов его можно удалить, его не хранят.
Технически он есть, вот такой временный генерируемый файл. Но после настройки сборки о существовании .pot или .mo можно забыть и работать только с обновляемыми .po
Не раскрыта тема устаревших переводов, .po может их хранить/накапливать и «воскрешать» в случае необходимости — вот такая «память переводов» из коробки :)
Это к gettext лишь косвенно относится (там нет форматтера аргументов, используется стандартный) и зависит от языка программы — в Python прекрасно работают ключи.
В gettext использует три формата файлов — *.po, *.pot и *.mo. Это влияет на внедрение gettext в производственный цикл, добавляя этапы вроде извлечения и компиляции сообщений.
По факту .po и .pot это один и тот-же формат, .pot и .mo автоматически генерируемые, их не нужно хранить в репозитории. Компиляция это ещё и проверка синтаксиса, а автоматическое извлечение сообщений — это наиболее полезная функция в gettext.
xgettext + msgmerge это как-раз то, что избавляет от головной боли при работе с большим числом сообщений. Пока Fluent сам по себе не предлагает решения этих проблем, с каждым id нужно возиться вручную.
P.S. Fluent гораздо лучше .po в качестве формата, но xgettext отнюдь не так плох, и исторически хорошо себя зарекомендовал как достаточно простое и удобное решение, для большинства случаев вполне достаточное. Лучшее враг хорошего :)
Алгоритм быстрого возведения в степень можно написать по-разному :)
Например, множитель возводится в квадрат и в зависимости от того, выставлен ли бит умножает результат, работает от младшего бита к старшему, например 2^10 r=1 (результат), m=2(множитель)
10 в двоичной это 1010, идя по битам от младшего к старшему 0101
0 m=2, r=1
1 m=4, r=r*m=4
0 m=16, r=4
1 m=256, r=r*m=1024
Т.е. 2^10 = 2^2*2^8
В двоичном виде степень меняется так:
0,10,010,1010
В приведённом алгоритме же порядок прохода битов от старшего к младшему, множитель не меняется, а сам результат возводится в квадрат, если бит 1 то ещё и домножается на множитель.
1 m=2, r=r*r*m=2
0 m=2, r=r*r=4
1 m=2, r=r*r*m=32
0 m=2, r=r*r=1024
Т.е. 2^10=(((2)^2)^2*2)^2
В двоичном виде степень меняется так:
1,10,101,1010
Всё верно, возведение в квадрат это дописать к степени в двоичном виде 0 справа, а если там должна быть единица то ещё домножить.
Однако я ожидал увидеть там немного другую реализацию — без нахождения старшего бита :).
Я про них и писал :), но не всегда можно получить нулевую ставку.
Кроме того бесплатный 100% match как правило означает что на контекст переводчик тупо забивает, что и было изначальной проблемой.
Не понимаю, откуда взялось «принудительно заставлять обновлять»?
1 Я писал про fuzzy, которым можно «закрыть» изменения старым переводом
2 Потом этот fuzzy всё равно переводчики будут смотреть, и возможно даже что-то переведут
3 Скрывать любые пусть даже мелкие правки от переводчиков нет смысла
На практике конфликты достаточно редки и повторное использование вполне оправдано, при генерации в .po файле можно перечислить все файлы с указанием строк, где msgid использовался и это помогает определить — допустимо ли повторное использование или нужно разделить по контексту.
Автоматически раздавая всем вхождениям уникальный контекст получаем 100500 «OK» и «Cancel» на перевод и перевод каждого нового «OK» оплачивается отдельно :)
Вопрос ответственности.
Могут как заменить, так и не заменить — это вполне в компетенции переводчиков. Я категорически против того, чтобы эту ответственность забирать у переводчиков — менять текст и решать, что переводчикам об этом знать не обязательно(ведь русский перевод же не изменится).
Фактически разработчик меняя текст берёт на себя ответственность за использование старых переводов, а в его ли это компетенции?