Вайб-кодинг

Keep calm and feel the vibe

Привет! Сегодня у нас короткий пост про вайб-кодинг.

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

Если вы еще здесь то начнем 🙂

Проблема (несуществующая)

У нас в офисе есть универсальный пазл с головоломкой которую можно решать каждый день 365 дней в году. Он находится на кухне и помогает скоротать время в момент чаепития.

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

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

Выглядит всё как приключение на 5 минут. Ну что, погнали! 🏃‍♂️‍➡️

Попытка решения №1

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

Этот язык мне очень нравится хотя на нем я самостоятельно написал наверное менее сотни строк.

Но в этот раз я почему-то решил начать с Python.

Первым делом я сфотографировал пазл со всеми его деталями:

Пазл

Открыл Cursor, выбрал в чате claude-4-sonnet, приложил туда фотографию и написал вот такой промт:

1
2
3
I have a challenge to fill this board with "bricks" and make cells related to current date unfilled. 
For example today it should be filled excluding 26 and "Май"
Please write a Python 3 script that will provide schema for every date

Сразу скажу что промт неоптимальный и неправильный.

Тем не менее Claude честно попытался решить эту задачу и сгенерировал скрипт который он назвал Calendar Puzzle Solver.

В первой версии скрипта он накосячил с фигурками и просто заполнял поле фигурами произвольных форм.

На что резонно получил вот такой комментарий:

1
Please fix your solution. You should use only provided limited bricks set.

Получив следующий результат я понял что Claude неверно интерпретировал картинку и неправильно определил доступный сет фигурок.

Следующий мой промт был такой, с попыткой в ASCII-арт 😁:

1
2
3
4
5
6
7
8
9
10
11
Here is a set of bricks:
* L piece: 5 cells, equal lenghts
* Long L piece - 4 cells line + 1 cell
* 2x3 piece (6 cells)
* 2x3 piece without one corner cell (5 cells)
* 2x3 piece without one central cell (5 cells)
* Z piece (5 cells)
* AAA
AA picece (5 cells)
* AAAA
A piece (5 cells)

На этот раз я почему-то получил в качестве решения скрипт который ожидал 44 ячейки притом что их всего лишь 43,

На то он получил новый промт.

1
Please fix program. It expectecs 44 total cells, but board has only 43 cells - 12 for months and 31 for days

В этот раз я получил скрипт который по заверениям Claude точно должен работать. Я запустил его и не дождался окончания работы скрипта за 5 минут. Очевидно решение нерабочее.

Подвисший python-скрипт

Так так так, кажется я зашел в тупик. Самое время открыть новый чат.

Попытка решения №2

Ну и не нужно

На этом моменте я удалил весь код и написал новый стартовый промт и также приложил картинку с пазлом.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
I have a challenge to fill this board with "bricks" and make cells related to current date unfilled. For example today it should be filled excluding 26 and "Май"
Please write a Python 3 script that will provide schema for every date
Board has 43 cells - 12 for months, 31 for days

Bricks:

A
A
AAA - 5 cells

A
A
A
AA - 5 cells

AA
AAA - 5 cells

AAA
AAA - 6 cells

A A
AAA - 5 cells

AA
A
AA - 5 cells

A
A
AA
A - 5 cells

A
A
AA
A - 5 cells

На этот раз клод меня почти понял и после первого решения пришлось подправить только одну фигуру.

1
2
3
4
5
6
Please fix Piece 6
# Piece 6: Z-shape (5 cells)
# AA
# A
# AA
[(0, 0), (0, 1), (1, 1), (2, 1), (2, 2)],

Насколько я помню эта версия скрипта также работала очень долго и не смогла решить задачу.

Поэтому я решил что пора немного подебажить.

1
Please print configuration of board on script run. I want to be sure that board has correct dimensions

И еще немного

1
And please also show bricks

Также добавить статистику

1
And please also count time that spent for finding solution

И поддержку аргументов

1
How to run script for another date?

В результате я получил довольно информативный скрипт который тем не менее работал очень долго и не решал мою задачу 😁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
python ./main.py
BOARD CONFIGURATION:
==================================================
0 1 2 3 4 5 6
0: Янв Фев Март Апр Май Июнь .
1: Июль Авг Сент Окт Нояб Дек .
2: 1 2 3 4 5 6 7
3: 8 9 10 11 12 13 14
4: 15 16 17 18 19 20 21
5: 22 23 24 25 26 27 28
6: 29 30 31 . . . .

Board Statistics:
- Total grid size: 7x7 = 49 positions
- Valid calendar cells: 43
- Month cells: 12
- Day cells: 31
- Empty/Invalid positions: 6
- Expected filled cells per solution: 41 (total - current date)

BRICK PIECES CONFIGURATION:
==================================================

Piece 1: L-shape (5 cells):
A . .
A . .
A A A
Coordinates: [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)]

Piece 2: Long L (5 cells):
A .
A .
A .
A A
Coordinates: [(0, 0), (1, 0), (2, 0), (3, 0), (3, 1)]

Piece 3: Short L (5 cells):
A A .
A A A
Coordinates: [(0, 0), (0, 1), (1, 0), (1, 1), (1, 2)]

Piece 4: Rectangle (6 cells):
A A A
A A A
Coordinates: [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]

Piece 5: T-shape (5 cells):
A . A
A A A
Coordinates: [(0, 0), (0, 2), (1, 0), (1, 1), (1, 2)]

Piece 6: Z-shape (5 cells):
A A .
. A .
. A A
Coordinates: [(0, 0), (0, 1), (1, 1), (2, 1), (2, 2)]

Piece 7: P-shape (5 cells):
A .
A .
A A
A .
Coordinates: [(0, 0), (1, 0), (2, 0), (2, 1), (3, 0)]

Piece 8: Modified P (5 cells):
A .
A .
A A
. A
Coordinates: [(0, 0), (1, 0), (2, 0), (2, 1), (3, 1)]

Total pieces: 8
Total cells in all pieces: 41
Expected coverage: 41 cells

==================================================
Using current date: 6 Июнь

Solving calendar board for: 6 Июнь
Available pieces: 8 pieces
Piece sizes: [5, 5, 5, 6, 5, 5, 5, 5] cells each

Попытка решения #3

На этом этапе я задал себе вопрос - «а зачем тут нужен Python?»

Итак, срочно переписываем все на Go. В этом случае хотя бы есть шанс дождаться заверешения работы программы 😁

Тем более с го есть возможность нагрузить все ядра CPU, а не только одно 🤣

Вставляем в промт последнюю версию полученного скрипта на Python и добавляем такой текст:

1
Please rewrite this script in go and use parallel calculations

Запускаем программу и видим результам уже через 11 секунд и 10 млн. попыток, а не спустя вечность как это было с питоном.

Правда решение не нашлось 💩

1
2
✗ No solution found for 6 Июнь (took 11.7612 seconds)
Total attempts: 10069962

Что ж, самое время разьяснить условия мсье Клоду более подробно.

1
Unfortunately it can't found solutions. All bricks can be rotated 90 degrees and flipped

Ура! Текущее решение работает! Просим клода пофиксить нейминг для фигур и написать README.md.

1
Please generate a descriptive README
1
2
3
Please update names of piece 3, because it is not square, it is cutted rectangle

And fix name of piece 8 because it's not a line

В итоге получаем рабочую программу которая мнгновенно решает задачу и нагружает все доступные ядра CPU.

Оно работает!

Здесь цифрами от 1 до 8 у нас помечены фигуры, а x это пустые клетки.

Судя по скрину программа подобрала решение для сегодняшней головоломки всего лишь за 0.2 секунды и 13 тысяч попыток!

При этом было задействовано 11 ядер CPU 🚀

Ну что ж, неплохо! Дальше мы просто инициализируем git-репозиторий и выкатываем наше поделие на GitHub - https://github.com/rhamdeew/calendar_solver

Бонус вариант

CLI-утилита это конечно круто, но недостаточно удобно. Давайте же сделаем Web GUI!

Причем чтобы было еще интереснее портируем наше решение на WebAssembly!

На этом моменте я осмелел достаточно чтобы написать промт в духе:

1
2
1. Extract core logic into separate file
2. Create WASM app in `web` directory that re-use logic from p.1

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

Ну что ж, тогда перестаем дружить с клодом и идем к новому приятелю - gemini-2.5-pro!

Новый укороченный промт:

1
Extract solver logic into `solver.go` file. I want to re-use it.

Gemini в отличие от Claude прекрасно справился с этой задачей. Логика вынесена в solver.go, аппка прекрасно собирается и работает точно так же 💪

Теперь попробуем доделать все остальное в одном чате:

1
Create `web` directory and implement similar solution written on Go but with web GUI using htmlx, tailwind  and WebAssembly

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

Понятно, откатываемся 💩

Важный момент - хоть в Cursor и реализована система чекпоинов к которым можно откатываться все же надежнее коммитить каждый шаг. Лишние коммиты потом можно отребейзить, а вот случайно попорченный код восстанавливать не так удобно.

Кстати, похоже что зря я гнал на Claude что он не смог вынести логику из одного файла в другой.

Такое ощущение что он просто работает сегодня с большими перебоями. Дело не в задаче в общем 🙂

Делаем шаг назад и просим Gemini чуть поменять структуру файлов

1
2
3
I use `solver.go` as a package. Please move it into directory with name that follows Go conventions and best practices.

Move main.go into `cli` directory

Итак, гемини отработал и сказал что все прекрасно работает.

Разбираться в том как теперь собирать приложение мне лень, поэтому спросим это у нашего нового друга.

1
How to build cli app?

И заодно попросим написать мейкфаил

1
2
3
4
5
6
Please generate Makefile with:

- build_cli
- run_cli

targets

Так, вроде бы все хорошо, но кажется чего-то не хватает. Может ТЕСТОВ? 🤔

1
Write tests for cli app and add `test_cli` target

Так, теперь у нас есть код cli-приложения с корректной структурой и даже есть тесты.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
make test_cli
Testing CLI application...
go test -v ./cli
=== RUN TestGetMonthName
=== RUN TestGetMonthName/Янв
=== RUN TestGetMonthName/1
=== RUN TestGetMonthName/12
=== RUN TestGetMonthName/янв
=== RUN TestGetMonthName/март
=== RUN TestGetMonthName/invalid
=== RUN TestGetMonthName/13
=== RUN TestGetMonthName/#00
--- PASS: TestGetMonthName (0.00s)
--- PASS: TestGetMonthName/Янв (0.00s)
--- PASS: TestGetMonthName/1 (0.00s)
--- PASS: TestGetMonthName/12 (0.00s)
--- PASS: TestGetMonthName/янв (0.00s)
--- PASS: TestGetMonthName/март (0.00s)
--- PASS: TestGetMonthName/invalid (0.00s)
--- PASS: TestGetMonthName/13 (0.00s)
--- PASS: TestGetMonthName/#00 (0.00s)
=== RUN TestMainCLI
=== RUN TestMainCLI/Specific_Date
=== RUN TestMainCLI/Test_Only
=== RUN TestMainCLI/Invalid_Month
=== RUN TestMainCLI/No_args
--- PASS: TestMainCLI (23.72s)
--- PASS: TestMainCLI/Specific_Date (4.85s)
--- PASS: TestMainCLI/Test_Only (9.28s)
--- PASS: TestMainCLI/Invalid_Month (0.00s)
--- PASS: TestMainCLI/No_args (9.46s)
PASS
ok puzzle_solver/cli 23.887s

Приступаем в генерации web-приложения на WebAssembly.

1
2
3
Create `web` directory and implement similar solution written on Go but with web GUI using htmlx, tailwind and WebAssembly

Use solver/solver.go for core functionality

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

Также я попросил его добавить Makefile со всеми необходимыми целями для сборки и запуска обоих версий приложения.

Запускаем веб версию:

1
make web

Выглядит красиво!

Но работает некорректно:

Судя по одинаковому с cli-версией количеству попыток для подбора решение правильное, а вот отображение решения какое-то кривое.

Снова идем в чат и жалуемся:

1
Please fix your solution. It displays incorrect board with incorrect block positions, but attempts count similar to cli solution. I think calculations is correct, rendering not correct.

Gemini снова думает, но рождает почему-то такое же решение 🤔

Жалуемся еще

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
No, your board is incorrect.

Correct board configuration


BOARD CONFIGURATION:
==================================================
0 1 2 3 4 5 6
0: Янв Фев Март Апр Май Июнь .
1: Июль Авг Сент Окт Нояб Дек .
2: 1 2 3 4 5 6 7
3: 8 9 10 11 12 13 14
4: 15 16 17 18 19 20 21
5: 22 23 24 25 26 27 28
6: 29 30 31 . . . .


And correct solution


Solution for 6 Июнь:
==============================
1 6 8 8 8 X .
1 6 6 6 8 8 .
1 1 1 6 5 X 5
2 4 4 4 5 5 5
2 4 4 4 3 3 3
2 7 7 7 7 3 3
2 2 7 . . . .

Результат:

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

Также заодно похвалим Gemini (и впустую израсходуем токены).

1
2
3
4
5
6
Thanks! It looks good!

Pleae make small UI changes:

1. Display text inside cell with opacity 50%, smaller font size and padding
2. Switch colors for black cells - display white cells with black text

Новый результат:

Все это конечно круто, но я хочу лайв-демо прямо на гитхабе.

Идем в новый чат.

1
I want to push this repo to GitHub and want to make index.html accessible from web as a live demo. How to do it?

На что Gemini предлагает вручную копировать билд в docs. Минус вайб 💩

1
Is there a way to do it using GitHub Actions? I don't want to manually copy every build to `docs` dir

Gemini сказал что все сделает. Плюс вайб 👍

На этом этапе почти все заработало, но нужно было еще включить GitHub Pages в настройках репозитория.



Итог

Потрачено конечно чуть больше чем 5 минут, но результат стоит того 🙂

Live demo: https://rhamdeew.github.io/calendar_solver/