Stan's blog

ACM Go Lang

Тимус: задача 1510. Быстрое чтение из входного потока в Golang и "алгоритм большинства голосов Бойера - Мура"

11 февраля 2024

Задача

С текстом задания можно ознакомиться тут
Мои попытки тут

Решение

Алгоритм

Тривиальная задача заняла у меня непозволительно много времени, однако, я не сказал бы, что я его провел в пустую.
Сначала я использовал то, что пришло на ум, а именно map. Но для большого разнообразия - это не вариант. Доработка с использование стохастического подхода, когда количество разнообразных банкнот больше, скажем 10000, дало результат. Однако, для этого надо хранить всю сходную последовательность (не проблема, это 2МБ), но всегда есть вероятность отличная от 0, что алгоритм даст сбой. И сложность задачи меньше 100 наводило на мысль, что есть способ проще. Увы, сам изобрести алгоритм я не смог, хотя, после того, как узнал про него он кажется весьма очевидным. "алгоритм большинства голосов Бойера - Мура" позволяет хранить только "претендента" и его "рейтинг" и все. Алгоритм линейный.

Чтение из входного потока

Потерпев неудачу с алгоритмом, решил, все-же получить в рейтинге решений первое место. И так:
Использовать os.Stdin.Read() вместо fmt.Sacn() . дало прирост скорости в 2 раза, но 500 000 закисей считывались почти за 1 сек, что не приемлемо для решения данной задачи. Да, разбор символов и преобразование их в цифры реализован свой.

Использование bufio позволило улучшить результат на два порядка  
in := bufio.NewReaderSize(os.Stdin, 640000)
in.Read(b)
Однако, использование b, _ = in.ReadByte() вместо in.Read(b) позволило улучшить результат еще в 2 раза и занят первую строчку в рейтинге решений.   
Рейтинг решений на языка Go

Осталось попробовать уйти от использования bufio и попробовать использовать самописный буфер.
Результат с самописным буфером

Как видно, это дало еще немного прироста в скорости. Однако, результат в решениях на C/C++ не получен. Связано ли это с особенностью тестировочного автомата (например любое решение на Ruby имело минимум 0.5 сек время) или решение на Go действительно медленнее без детального разбора сказать невозможно.