VI, 31 25 байт
O@0kdd<C-v><C-a>Y<C-v><C-x>gg@a<Esc>"add<C-a>Y<C-x>@a
<C-?>відповідає Control + ?, і <Esc>до Escapeочевидно. Кожен з них рахується по 1 байту (див. Мета ).
Вхідні дані
Вхідний файл повинен містити 1 ціле число на рядок + 1 порожній рядок в кінці, наприклад:
1
2
3
4
5
Ми можемо бачити кожен рядок вхідного файлу як елемент масиву, такий як 1 :: 2 :: 3 :: 4 :: 5 :: [], наприклад, у деяких мовах (наприклад, caml).
Запуск
Ви можете почати vi із наступної команди та ввести обведення рішення обведенням:
vi -u NONE input
Ви також можете скористатися цим одноклассником:
vi -u NONE -c ':exec "norm O@0kdd\<C-v>\<C-a>Y\<C-v>\<C-x>gg@a\<Esc>\"add\<C-a>Y\<C-x>@a"' -c ":w output" -c ':q' input
Це має створити файл outputіз правильним результатом із вхідного файлу input.
Пояснення
Щоб запровадити рішення, я спочатку представляю 19-байтовий розчин, що працює лише для масивів без 0. У цьому рішенні використовується рекурсивний макрос, який використовується з невеликими модифікаціями в кінцевому рішенні:
Yqa@0ddYgg@aquggY@a
Пояснення часткового рішення
Y # yank first line (first integer + line break) to "0 register
qa # start recording a macro ("a register)
@0 # jump n lines, where n is the content of the "0 register
dd # delete the current line (n+1th line)
Y # yank current line (integer after the previously deleted line)
gg # go back to the first line
@a # recurse on macro "a"
q # finish recording the macro
u # cancel modifications done by the execution of the macro
gg # go back to the first line
Y@a # apply the recorded macro with first parameter equal to the first integer
Хитрість тут полягає у використанні "0регістру для зберігання поточного цілого числа (і розрив рядка, дуже важливий). Тому команда @0дозволяє стрибати nрядки (називати nзначення "0). Якщо стрибок перевищує кількість рядків у файлі, макрос вийде з ладу, тому програма зупиниться (поза межами меж масиву, як потрібно).
Але це рішення не працює, якщо вхід містить 0. Дійсно, якщо "0значення регістру дорівнює 0, то @0стрибне один рядок (через розрив рядка), не так, 0як нам сподобалось. Отже, наступна команда ( dd) не видалить 0-е ціле число, але 1-е (не правильне).
Достовірним рішенням для обробки 0є завжди нарощувати ціле число до того, як його з’єднати, і зменшити його відразу після. Таким чином, @0команда буде стрибати n+1рядки ( nце поточне ціле число, яке було збільшено). Після kцього необхідно перейти до рядка n(попередній рядок). Використовуючи цей трюк, порожній рядок потрібен в кінці вхідного файлу, щоб уникнути стрибків за межі масиву (таким чином, закінчуючи програму), оскільки ми завжди стрибаємо n+1рядки, перш ніж переходити до попереднього рядка.
Пояснення остаточного рішення
O # insert a new line at the beginning of the file, enter insert mode to write the macro content
@0 # jump n lines
k # go to the previous line
dd # delete this line
<C-v><C-a> # type Control+A (C-v is needed because we are in insert mode) to increment the current integer
Y # yank the incremented integer
<C-v><C-x> # decrement the current integer
gg # go to the first line
@a # recurse on macro "a"
<Esc> # exit insert mode : at this step, the first line of the file contains the macro content @0kdd^AY^Xgg@a
"add # copy @0kdd^AY^Xgg@a line to the register "a and delete the line
<C-a> # increment the first integer
Y # yank it (into "0)
<C-x> # decrement the first integer
@a # apply macro in a" (initial @0 will jump n+1 lines, since we incremented the first integer before calling the macro)
Запис вмісту макросу в файл перед реєстрацією дозволяє зберегти кілька байтів:
- уникає писати
qa...qта скасовувати всі зміни після реєстрації
- уникає
:let @a="...")
Правки
№1
- записати вміст макросу в перший рядок (замість останнього рядка)
- змінити вхід (1 порожній рядок в кінці)
- додати один-лайнер для тестування в командному рядку