Надвигается очередной конец очередного года, в связи с чем люди неравнодушные к своей работе — наверняка собираются принимать участие в состязаниях «Advent of Code» в своих стеках. За последние несколько месяцев существенно ожесточились споры на предмет вайбкодинга (даже термин ублюдский придумали). Мне пришла в голову тривиальная мысль: а что, если вовлечь в соревнование ваших любимых стажё^W искусственных помощников?
Я лично собираюсь решать AoC по старинке, но при этом оставляю право AI посостязаться со мной в этом соревновании и даже обойти меня в нем. В комментариях к этому тексту я предлагаю публиковать решения, выполненные лично вами, или вашими раба^W помощниками, на всех возможных языках программирования. В англоязычном интернете — полно форумов, на которых люди делятся решениями и обсуждают их; хабр (ну, как минимум тот, про который мы иногда вспоминаем в кондитерском смысле) — идеальное место для подобных обсуждений на русском языке.
Я знаю, что этот текст — неформат для обычного ИИ-высера, которые заполонили этот сайт в последнее время, но мне по счастью насрать как на плюсики, так и на карму, — поэтому я все-таки решил опубликовать этот «плейсхолдер» для дальнейшей (надеюсь) интересной дискуссии про разные подходы и реалиализации в комментариях.
Чтобы проактивные дурачки из администрации меня не забанили сразу, вот решение первой задачки прошлого года на эликсире.
Текст задачи на русском
--- День 1: Историческая истерия ---
Главный историк всегда присутствует на большом рождественском спуске Санты на санях, но его уже несколько месяцев никто не видел! По последним данным, он шарится вокруг Северного полюса. Группа старших историков заставила вас присоединиться к экспедиции по поиску этого странного деда в красном тулупе.
[…]
Вы ещё даже не вышли на маршрут, а группа старших эльфийских историков уже столкнулась с проблемой: их список мест, которые нужно проверить, в данный момент пуст. В конце концов кто-то решает, что лучше всего начать с кабинета главного историка.
Ворвавшись в кабинет, все подтверждают, что главного историка действительно нигде нет. Вместо него эльфы находят множество заметок и списков исторически значимых мест! Похоже, это то, что главный историк планировал сделать перед уходом. Может быть, эти заметки помогут определить, в каких местах сто́ит искать?
В кабинете начальника исторически значимые места обозначены не названиями, а уникальными номерами, которые называются идентификатор места. Чтобы ничего не упустить, Историки разделились на две группы, каждая из которых обыскивает кабинет и пытается составить свой полный список идентификаторов мест.
Есть только одна проблема: если просто сопоставить два списка (ввод данных для головоломки), то быстро становится ясно, что списки не очень похожи. Может быть, вы сможете помочь Историкам привести их в соответствие?
Например:
/** я не знаю, как убрать слева нумерацию строк */
3 4
4 3
2 5
1 3
3 9
3 3
Возможно, разница в списках невелика! Чтобы это выяснить, сопоставьте числа и измерьте расстояние между ними. Сопоставьте наименьшее число в левом списке с наименьшим числом в правом списке, затем второе по величине число в левом списке с вторым по величине числом в правом списке и так далее.
В каждой паре определите насколько далеко друг от друга расположены два числа. Вам нужно будет сложить все эти расстояния. Например, если вы объедините 3 из левого списка с 7 из правого списка, расстояние между ними будет 4; если вы объедините 9 с 3, расстояние между ними будет 6.
В приведенном выше примере пары и расстояния будут следующими:
Наименьшее число в левом списке —
1, а наименьшее число в правом списке —3. Расстояние между ними —2.Второе по величине число в левом списке —
2, а второе по величине число в правом списке — ещё одно3. Расстояние между ними —1.Третье по величине число в обоих списках —
3, поэтому расстояние между ними равно0.Следующие числа, которые нужно объединить в пары, — это
3и4, расстояние между ними составляет1.Пятые по величине числа в каждом списке —
3и5, расстояние между ними составляет2.Наконец, наибольшее число в левом списке —
4, а наибольшее число в правом списке —9; они находятся на расстоянии5друг от друга.
Чтобы найти общее расстояние между левым и правым списками, сложите расстояния между всеми найденными парами. В приведённом выше примере это 2 + 1 + 0 + 1 + 2 + 5, то есть общее расстояние составляет 11!
Ваши левые и правые списки содержат множество идентификаторов местоположений. Каково общее расстояние между вашими списками?
Вот моё наивное решение:
input =
"""
3 4
4 3
2 5
1 3
3 9
3 3
"""
input
|> String.split(~r/\s/, trim: true)
|> Enum.map(&String.to_integer/1) # ошибку проверить бы
|> Enum.chunk_every(2)
|> Enum.reduce([[], []], fn [l, r], [ll, rr] -> [[l | ll], [r | rr]] end)
|> Enum.map(&Enum.sort/1) # серьёзно? мап сразу после редьюса, лузер?
|> Enum.zip() # у тебя редьюс, а ты лепишь третий проход
|> Enum.sum_by(fn {l, r} -> abs(l - r) end) # суммы в четвертом проходе?!
#⇒ 11
Тут куча вещей сделана неаккуратно (см. комментарии), но оно работает (еще можно заменить редьюс на Enum.map(&List.to_tuple/1) |> Enum.unzip() |> Tuple.to_list() и сделать все еще «читаемее» и еще уродливее. Давайте посмотрим, что сделает ну скажем Gemini:
defmodule Day01 do
@doc """
Solves Day 1, Part 1: Calculates the total distance between two lists of location IDs.
The input is expected to be a string where each line contains two space-separated
location IDs: the left list number followed by the right list number.
The total distance is found by:
1. Sorting both the left and right lists independently.
2. Pairing up elements at the same index in the sorted lists.
3. Summing the absolute difference of each pair.
"""
def solve(input) do
# 1. Parse the input string into two lists (Left and Right)
{left_list, right_list} =
input
# Split the input into lines, handling different line endings
|> String.split(["\n", "\r\n"], trim: true)
# Split each line into two strings (the left and right number)
|> Enum.map(fn line -> String.split(line, " ", trim: true) end)
# Convert the strings to integers and create a tuple of {left, right}
|> Enum.map(fn [l, r] -> {String.to_integer(l), String.to_integer(r)} end)
# Separate the list of {L, R} tuples into two lists (L and R)
|> Enum.unzip()
# 2. Sort both lists independently
sorted_left = Enum.sort(left_list)
sorted_right = Enum.sort(right_list)
# 3. Pair up the sorted lists and calculate the total distance
sorted_left
# Pair the corresponding elements from the two sorted lists
|> Enum.zip(sorted_right)
# Calculate the absolute difference for each pair {l, r}
|> Enum.map(fn {l, r} -> abs(l - r) end)
# Sum up all the distances
|> Enum.sum()
end
end
Ну, примерно то же самое, но с вре́менными переменными вместо литого пайпа, зато с комментариями и ажно целым модулем, готовым к продакшену. В общем, справилась.
Но это первое задание первого дня 2024 года. То есть простое, и эта тварь уже сто раз видела решения. А что будет, если решений ллмка пока не видела? Вот и посмотрим.