August 5, 2021

codingame puzzle: folding a note

Я решил еще один пазл на codingame, на этот раз medium. Он очень простой, главное там - не запутаться. Но ради прикола я решил его двумя способами, честным и нечестным.

https://www.codingame.com/training/medium/folding-a-note

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

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

Складывание записки будет происходить в определенном порядке, пока на каждом слое не окажется только один символ:

Первое складывание будет справа налево (то есть правая половина записки сгибается поверх левой половины.

Второе складывание (если произойдет) будет снизу вверх.

Третье складывание (если произойдет) будет слева направо.

Четвертое складывание (если произойдет) будет сверху вниз.

Последующие складывания, если они произойдут, продолжат цикл в этом порядке.

Пример: вы получаете записку:

12

34

После первого сгиба справа налево у записки есть два слоя:

2 4

и

1 3

После второго и последнего сгиба снизу вверх у записки есть 4 слоя, каждый из которых содержит по одному символу, и, таким образом, окончательное сообщение получается путем чтения слоев сверху вниз: 3421

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

Создатели пазла облегчили задачу - длина у квадратного текста на входе может быть только степенью двойки, причем небольшой - 1, 2, 4, 8, 16.

Я сделал честное тупое решение с использованием трехмерных массивов. Первое измерение - слои, в которые складывается записка, второе - строки, третье - символы в строке. При помощи этих массивов я проимитировал складывание записки.

Получилось все достаточно компактно, задача прошла тесты:

https://gist.github.com/Manjago/763ad674e83839e2b624fab1a4d2a815

Я посмотрел, как народ задачу решает - они оторвались, использовали списки, стеки и даже очереди. И всякие хитрые кастомные унарные операции для складывания записки.

Мне тоже захотелось извратиться, но я решил сделать еще тупее.

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

Для каждого из четырех случаев (длина квадрата текста - 2, 4, 8, 16) я сделал текст из уникальных символов, скормил его своему решению, а потом пробежался по ответу и нашел исходную позицию каждого символа.

Полученный список координат я захардкодил в массив и сделал простейшее решение, которое получает текст записки, никакое складывание не имитирует, а просто пробегается по ней в соответствии с инструкциями из захардкоженного массива (неизвестно откуда взявшегося ( ͡ʘ ͜ʖ ͡ʘ) ). Решение ожидаемо прошло все автоматические тексты (но code review кожаного мешка оно бы, конечно же, не прошло бы): https://gist.github.com/Manjago/201617dc9678c4a25647a54bd465d258

Таким образом, я немного продвинулся в своем развитии на codinggame: