Модели пишут на чистом Python растеризатор: он превращает описание сцены из прямоугольников, кругов, эллипсов, многоугольников и линий в пиксели. В сцене есть прозрачность, градиенты и аффинные преобразования. Картинку каждой модели сравнивают попиксельно с эталоном на 202 сценах и проверяют двумя замерами скорости.
29 октября 2026. 7 прогонов, 5 моделей, ещё 1 исключён из рейтинга.
Это одна и та же сцена 320×200, увеличенная вдвое: закат с градиентом, полупрозрачные горы, звёзды с правилами заливки nonzero и evenodd, повёрнутый прямоугольник, скошенный круг и линии. Переключатель «Отличия от эталона» подсвечивает красным пиксели, которые не совпали с эталоном.








Правильно нарисовали все.Все шесть моделей, которые сдали код, прошли 202 сцены из 202 и нарисовали контрольную сцену пиксель в пиксель с эталоном. Задача проще первой, и её ловушки (полуоткрытые границы, правила заливки, короткие записи цвета, округление на половине) никого не поймали.
Различает их скорость кода.Opus-агент рисует 400 фигур за 0,10 секунды, Qwen за 0,14, Kimi за 0,20, DeepSeek Flash за 0,27, GPT за 0,28. Эталон делает это за 0,45, так что пять моделей из шести написали код быстрее нашего. Opus через API не отсекал фигуры по рамке и не уложился в лимит.
Быстрый код не значит быстрый ответ.Qwen написал второй по скорости растеризатор, но думал над ним 27,5 минуты. DeepSeek Flash ответил за 2 минуты 20 секунд, и его код всего вдвое медленнее.
Глубина размышления снова решила спор двух Opus.Агентом Opus думал около 10 минут и написал самый быстрый код. Через API с адаптивным мышлением он ответил за 34 секунды почти без рассуждения: код правильный, но медленный.
Шлюз мешает длинным ответам.Партнёрский шлюз дважды оборвал поток посреди рассуждения: один раз у GPT, несколько раз у Grok. У прямых API провайдеров таких обрывов не было.
| Место | Модель | Тесты | Ловушки | Случайные | Ошибки | Скорость | Время | Рассуждение | Всего токенов | Токенов/с | Строк кода | С правкой |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 🥇 1 | Claude Opus 5.5 (агент) | 202 (100.0%) | 46/46 | 150/150 | 6/6 | 2/2 | 10 мин 29 с | 72K* | 82K | 130* | 777 | — |
| 🥈 2 | Claude Opus 5.5 (агент, effort max) | 202 (100.0%) | 46/46 | 150/150 | 6/6 | 2/2 | 53 мин 16 с | 350K* | 355.6K | 111* | 602 | — |
| 🥉 3 | Qwen3.8-Max | 202 (100.0%) | 46/46 | 150/150 | 6/6 | 2/2 | 27 мин 25 с | 55.9K | 66.5K | 40 | 1229 | — |
| 4 | Kimi K3.1 Pro | 202 (100.0%) | 46/46 | 150/150 | 6/6 | 2/2 | 11 мин 42 с | 18K | 21.2K | 30 | 403 | — |
| 5 | DeepSeek Flash (V4.1) | 202 (100.0%) | 46/46 | 150/150 | 6/6 | 2/2 | 2 мин 20 с | 23.3K | 26.5K | 190 | 426 | — |
| 6 | GPT-6.1 Sol | 202 (100.0%) | 46/46 | 150/150 | 6/6 | 2/2 | 4 мин 28 с | скрыто | 11.6K | 43 | 348 | — |
| 7 | Claude Opus 5.5 (effort max) | 202 (100.0%) | 46/46 | 150/150 | 6/6 | 1/2 | 34 с | 0 | 3.8K | 111 | 287 | — |
В колонке «С правкой» указан результат того же кода после исправления одной-двух строк, он нужен только для понимания. Звёздочка означает оценку. «Токенов/с» показывает, как быстро модель пишет: все токены ответа, включая рассуждение, делённые на полное время ответа.
От отправки задания до последнего символа ответа. Зависит и от загрузки серверов провайдера.
claude-opus-5-5claude-opus-5-5effort: max за 34 секунды написал код, который не уложился во второй замер. Протокол соблюдён: одно чтение задания и одна запись решения.qwen3.8-maxkimi-k3.1-prodeepseek-flashgpt-6.1-solclaude-opus-5-5Нужно написать функцию render(scene), которая возвращает картинку как список строк пикселей (r, g, b). Пиксель закрашивается, если его центр лежит внутри фигуры. Фигуры бывают пяти видов: прямоугольник с полуоткрытыми границами, круг, эллипс, многоугольник с правилами заливки nonzero и evenodd и толстая линия. Цвет задаётся в форматах #rgb, #rgba, #rrggbb и #rrggbbaa, у фигуры может быть opacity, линейный градиент и аффинное преобразование. Цвета смешиваются по формуле floor(src*α + dst*(1-α) + 0.5).
Напиши на Python 3.12 растеризатор двумерной сцены: один модуль, только стандартная библиотека. Сторонние библиотеки (PIL, numpy и любые другие) использовать нельзя.
## Интерфейс
```python
def render(scene: dict) -> list[list[tuple[int, int, int]]]:
...
```
Функция возвращает картинку как список строк сверху вниз. Каждая строка это список пикселей слева направо, каждый пиксель это кортеж `(r, g, b)` из целых чисел от 0 до 255. Элемент `result[j][i]` соответствует пикселю в столбце `i` и строке `j`.
## Сцена
```python
{
"width": 320, "height": 200, # размер холста в пикселях
"background": "#0b1d3a", # цвет фона
"shapes": [ {...}, {...} ] # фигуры, рисуются по порядку, каждая следующая поверх предыдущих
}
```
## Координаты и пиксели
Ось x направлена вправо, ось y вниз. Пиксель `(i, j)` занимает квадрат от `i` до `i+1` по x и от `j` до `j+1` по y. Пиксель закрашивается фигурой, если **центр пикселя** `(i + 0.5, j + 0.5)` лежит внутри фигуры. Сглаживания нет.
## Цвета
Цвет задаётся строкой: `#rgb`, `#rgba`, `#rrggbb` или `#rrggbbaa`, шестнадцатеричные цифры в любом регистре. В коротких формах каждая цифра удваивается (`#a3f` означает `#aa33ff`). Если альфа не указана, она равна 255. У фона альфа игнорируется, фон всегда непрозрачный. Любая другая строка считается ошибкой.
## Фигуры
У каждой фигуры есть поле `type` и поле `fill` (цвет или градиент). Необязательные поля: `opacity` (число от 0 до 1, по умолчанию 1) и `transform` (см. ниже). Все координаты фигуры заданы в её локальной системе.
- `rect`: поля `x`, `y`, `w`, `h`. Точка внутри, если `x <= px < x + w` и `y <= py < y + h`. При `w <= 0` или `h <= 0` фигура пустая.
- `circle`: поля `cx`, `cy`, `r`. Точка внутри, если `(px - cx)² + (py - cy)² <= r²`.
- `ellipse`: поля `cx`, `cy`, `rx`, `ry`. Точка внутри, если `((px - cx) / rx)² + ((py - cy) / ry)² <= 1`. При `rx <= 0` или `ry <= 0` фигура пустая.
- `polygon`: поле `points` (список точек `[x, y]`, не меньше трёх, многоугольник замкнут) и необязательное `fill_rule`: `"nonzero"` (по умолчанию) или `"evenodd"`. Принадлежность точки определяется лучом из неё вправо. Ребро `(x0, y0) → (x1, y1)` пересекает луч, если `y0 <= py < y1` или `y1 <= py < y0`, и при этом `x0 + (py - y0) * (x1 - x0) / (y1 - y0) > px`. Каждое такое ребро добавляет к числу оборотов `+1`, если `y1 > y0`, иначе `-1`. Для `nonzero` точка внутри, если сумма не равна нулю, для `evenodd` точка внутри, если число пересекающих рёбер нечётное.
- `line`: поля `x1`, `y1`, `x2`, `y2`, `width`. Точка внутри, если расстояние от неё до отрезка не больше `width / 2`. Если концы совпадают, получается круг.
## Преобразование
`transform` задаётся шестью числами `[a, b, c, d, e, f]` и переводит локальную точку `(x, y)` в точку холста `(a*x + c*y + e, b*x + d*y + f)`. Чтобы проверить пиксель, его центр переводится обратным преобразованием в локальные координаты, и проверка идёт там. Поэтому круг под масштабом становится эллипсом, а толщина линии масштабируется вместе с ней. Если преобразование вырожденное (`a*d - b*c == 0`), фигура не рисуется. Без `transform` локальные координаты совпадают с координатами холста.
## Градиент
```python
{"type": "linear", "x1": 0, "y1": 0, "x2": 100, "y2": 0, "stops": [[0, "#000"], [0.5, "#f00"], [1, "#fff"]]}
```
Координаты градиента тоже локальные. Для точки `p` параметр `t` равен скалярному произведению `(p - p1)` на `(p2 - p1)`, делённому на `|p2 - p1|²`, и обрезается до отрезка `[0, 1]`. Если `p1` совпадает с `p2`, то `t = 0`. Точки остановки `stops` идут по возрастанию смещения. Если `t` не больше первого смещения, берётся первый цвет. Если не меньше последнего, берётся последний. Иначе берутся соседние остановки с `o_i <= t <= o_{i+1}`, и каждый канал, включая альфу, интерполируется линейно, без округления на этом шаге. Если две соседние остановки стоят в одной точке, берётся цвет второй. Пустой список `stops` считается ошибкой.
## Наложение цветов
Для закрашиваемого пикселя берётся цвет заливки `(r, g, b, a)` в этой точке. Непрозрачность равна `α = a / 255 * opacity`. Каждый канал холста заменяется на `floor(src * α + dst * (1 - α) + 0.5)`, где `dst` это текущее целое значение канала. Результат ограничивается отрезком от 0 до 255.
## Ошибки
Неверный цвет, неизвестный тип фигуры, многоугольник меньше чем из трёх точек и градиент без остановок должны вызывать `ValueError`.
## Производительность
Холст 800×600 с 400 небольшими фигурами и холст 640×480 с несколькими крупными полупрозрачными фигурами и градиентом должны рисоваться не дольше 4 секунд каждый на обычном ПК.
## Формат ответа
Ответь ТОЛЬКО кодом модуля в одном блоке ```python.
#abc и #f808, самопересекающаяся звезда с разными правилами заливки, вершины ровно на центрах пикселей, вырожденное преобразование, круг под масштабом, который становится эллипсом, толщина линии под масштабом, градиенты с обрезкой, со ступенькой и с совпадающими точками, а также смешивание цветов ровно на половине, где round() в Python даёт другой ответ.ValueError: неверные цвета, неизвестный тип фигуры, многоугольник из двух точек, градиент без остановок.enable_thinking, у GPT и Grok reasoning_effort: high, Opus через API получал thinking: adaptive и effort: max через нативный /v1/messages, Kimi и DeepSeek работали в режиме по умолчанию.effort: max добавлен 29.10.2026, после основного прогона, по тому же протоколу: одно чтение задания и одна запись решения, без запуска кода. Его запустили, чтобы сравнить с Opus через API на том же effort: max: через партнёрский шлюз модель рассуждает заметно меньше.Эти прогоны не попали в рейтинг: результат определила не модель, а условия запуска. Ответы и код сохранены в папке.
| Модель | Разработчик | ID | Доступ | Лимит ответа |
|---|---|---|---|---|
| Claude Opus 5.5 (агент) | Anthropic | claude-opus-5-5 | субагент Claude Code, чистый контекст, без запуска кода | — |
| Claude Opus 5.5 (агент, effort max) | Anthropic | claude-opus-5-5 | субагент Claude Code, effort: max, чистый контекст, без запуска кода | — |
| Kimi K3.1 Pro | Moonshot AI | kimi-k3.1-pro | API api.moonshot.ai (через VPN роутера) | 128K |
| GPT-6.1 Sol | OpenAI | gpt-6.1-sol | партнёрский шлюз, reasoning_effort: high | 128K |
| Qwen3.8-Max | Alibaba | qwen3.8-max | API token-plan.maas.qwencloudapi.com | 131.1K |
| Claude Opus 5.5 (effort max) | Anthropic | claude-opus-5-5 | партнёрский шлюз, нативный /v1/messages, thinking: adaptive, effort: max | 128K |
| DeepSeek Flash (V4.1) | DeepSeek | deepseek-flash | API api.deepseek.com | 384K |
| Grok 4.7 | xAI | grok-4.7 | партнёрский шлюз, reasoning_effort: high | 128K |