Ввод будет состоять из следующих символов:
^
: Подняться на одинv
: Спуститься вниз▲
илиk
: поднимись на два▼
илиj
: идти вниз два
Например, следующий вход:
^^▲^v▼▲^^v
будет производить следующий вывод:
^
^ ^ v
▲ v ▲
^ ▼
^
Escape-последовательности, которые перемещают курсор, например \e[B
, не допускаются. Вы должны произвести вывод, используя пробелы и переводы строки.
Вот еще несколько тестов.
▲v^v^v^v^v^v^v^v▲
▲
▲ ^ ^ ^ ^ ^ ^ ^
v v v v v v v v
^^^^^^^▲▲▲▼▼▼vvvvvv
▲
▲ ▼
▲ ▼
^ ▼
^ v
^ v
^ v
^ v
^ v
^ v
v^^vv^^vvv^v^v^^^vvvv^^v^^vv
^ ^ ^
^ v ^ v ^ v ^
v v v ^ ^ ^ v ^ ^ v
v v v v ^ v v
v
j
дважды спускаться иk
вдвое больше.Ответы:
Pyth, 27 байт
Попробуйте онлайн: демонстрация или тестовый набор
Я использую
k
иj
вместо▲
и▼
. Есть много ведущих и конечных пустых строк. Вы должны искать совсем немного, чтобы найти изображение. Вот 34 байта версия, которая удаляет все начальные и конечные пустые строки.Попробуйте онлайн: демонстрация или тестовый набор
Объяснение:
источник
Не читается ,
219921452134210420872084 байтПоддерживает оба
k
/j
так и▲
/▼
синтаксис.В доброй нечитаемой традиции, вот программа, отформатированная пропорциональным шрифтом, чтобы скрыть различие между апострофами и двойными кавычками:
Это был удивительный вызов. Спасибо за публикацию!
объяснение
Чтобы понять, что может и не может сделать нечитабельный, представьте, что Brainfuck имеет бесконечную ленту в обоих направлениях, но вместо указателя памяти, перемещающего одну ячейку за раз, вы можете получить доступ к любой ячейке памяти, разыменовав указатель. Это очень удобно в этом решении, хотя другие арифметические операции, в том числе по модулю, должны выполняться вручную.
Вот программа в виде псевдокода с комментариями директора:
Вот вам и логика программы. Теперь нам нужно перевести это на Unreadable и использовать еще несколько интересных трюков для игры в гольф.
Переменные всегда численно разыменовываются в Unreadable (например,
a = 1
становится чем-то вроде*(1) = 1
). Некоторые числовые литералы длиннее других; самое короткое - 1, затем 2 и т. д. Чтобы показать, насколько длиннее отрицательные числа, вот числа от -1 до 7:Ясно, что мы хотим выделить переменную # 1 той, которая чаще всего встречается в коде. В первом цикле while это определенно
mod5
происходит 10 раз. Но нам больше не нужноmod5
после первого цикла while, поэтому мы можем перераспределить ту же область памяти для других переменных, которые мы будем использовать позже. Этоptr2
и естьptr3
. Теперь на переменную ссылаются всего 21 раз. (Если вы пытаетесь подсчитать количество вхождений самостоятельно, не забудьте подсчитать что-то вродеa++
дважды, один раз для получения значения и один раз для его установки.)Есть только одна другая переменная, которую мы можем использовать повторно; после того, как мы вычислили значения по модулю,
ch
больше не нужны.up
иdn
подходить столько же раз, так что все в порядке. Давайте слитьсяch
сup
.Это оставляет в общей сложности 8 уникальных переменных. Мы могли бы разместить переменные от 0 до 7, а затем начать блок памяти (содержащий символы и номера строк) с 8. Но! Так как 7 в коде имеет ту же длину, что и -1, мы могли бы также использовать переменные от -1 до 6 и начать блок памяти с 7. Таким образом, каждая ссылка на начальную позицию блока памяти немного короче в коде! Это оставляет нас со следующими заданиями:
Теперь это объясняет инициализацию в самом верху: это 5, потому что это 7 (начало блока памяти) минус 2 (обязательное приращение в первом условии while). То же самое касается двух других вхождений 5 в последнем цикле.
Обратите внимание, что, поскольку 0 и 4 имеют одинаковую длину в коде,
ptr
иminLine
может быть выделена либо наоборот. ... Или они могли?Что насчет загадочных 2 во втором-последнем цикле while?Разве это не должно быть 6? Мы хотим только уменьшить числа в блоке данных, верно? Как только мы достигнем 6, мы за пределами блока данных, и мы должны остановиться! Это была бы уязвимость безопасности ошибки ошибки переполнения буфера!
Хорошо, подумай о том, что произойдет, если мы не остановимся. Уменьшаем переменные 6 и 4. Переменная 6 есть
mod4
. Это используется только в первом цикле while и больше здесь не нужно, так что никакого вреда. Как насчет переменной 4? Как вы думаете, должна ли переменная 4 бытьptr
или должна бытьminLine
? Это верно,minLine
больше не используется в этой точке либо! Таким образом, переменная # 4 есть,minLine
и мы можем безопасно уменьшить ее и не нанести ущерба!ОБНОВЛЕНИЕ 1! Гольф от 2199 до 2145 байтов, понимая, что также
dn
может быть объединен с , хотя все еще используется в вычислении значения для ! Новое назначение переменной теперь:mod5
mod5
dn
ОБНОВЛЕНИЕ 2! Проигрывал от 2145 до 2134 байтов, понимая, что, поскольку
mod5
теперь он находится в той же переменной, что иdn
, которая считается в 0 в цикле while,mod5
больше не нужно явно инициализироваться равным 0.ОБНОВЛЕНИЕ 3! Гольф от 2134 до 2104 байтов, осознав две вещи. Во-первых, хотя идея «отрицательного по модулю» того стоила
mod5
, то же самое рассуждение неприменимо к тому,mod4
что мы никогда не проверяемmod4+2
и т. Д. Следовательно, переходmod4 ? mod4+1 : -3
кmod4 ? mod4-1 : 3
значению приводит к 2110 байтов. Во-вторых, такmod4
как всегда 0 или 2, мы можем инициализироватьmod4
2 вместо 0 и обратить две троичные (mod4 ? 3 : 1
вместоmod4 ? 1 : 3
).ОБНОВЛЕНИЕ 4! Проигрывая от 2104 до 2087 байтов, осознав, что цикл while, который вычисляет значения по модулю, всегда выполняется по крайней мере один раз, и в таком случае Unreadable позволяет вам повторно использовать значение последнего оператора в другом выражении. Таким образом, вместо того,
while --ch: [...]; up = (mod5 ? mod5+1 ? [...]
чтобы теперь иметьup = ((while --ch: [...]) ? mod5+1 ? [...]
(и внутри этого цикла, мыmod4
сначала вычисляем , так чтоmod5
это последнее утверждение).ОБНОВЛЕНИЕ 5! Проигрывая от 2087 до 2084 байтов, осознав, что вместо записи констант
32
и10
(пробела и новой строки) я могу сохранить число 10 в (теперь не используемой) переменной # 2 (давайте назовем ееten
). Вместо того,ptr3 = 5
чтобы писатьten = (ptr3 = 5) + 5
, тогда32
становитсяten+22
иprint 10
становитсяprint ten
.источник
CJam, 37 байт
Это печатает пустые строки до и после желаемого вывода, что было разрешено OP .
Попробуйте онлайн в интерпретаторе CJam .
Как это работает
источник
Python 2, 102
Печатает построчно.
Прокручивает символы на входе и отслеживает текущую высоту. Высота обновляется одним из
+2, +1, -1, -2
вычисленных'kv_^j'.find(c)-2
. Там, вероятно, мод цепь, которая корочеКогда текущая высота равна номеру строки (который может быть отрицательным), мы добавляем текущий символ в строку, а в противном случае добавляем пробел. Затем мы печатаем строку. На самом деле, короче начинать высоту с текущего номера строки и вычитать изменения высоты, добавляя символ, когда значение достигает
0
.Номера строк охватывают достаточно большой диапазон, чтобы в нем оставалась последовательность вверх-два или вниз-два. На самом деле, есть много лишнего. Если бы у нас была верхняя граница длины ввода, было бы короче написать, скажем,
j=999
.Удивительно, но
i and' 'or c
был короче обычного[' ',c][i==0]
. Обратите внимание, чтоi
может быть отрицательным, что исключает некоторые обычные трюки.источник
МАТЛАБ, 116
Это начало. И,
j
иk
это делает боль в шее, так как я не могу найти способ математически отобразить от иj^vk
до[-2 -1 1 2]
MATLAB, не распознавая Unicode (очевидно, что и MATLAB вверх и вниз имеют значение 26 в. много байтов тратится на отображение.Черпая вдохновение из решения @xnors, код можно уменьшить еще на 14 символов, сопоставив управляющий символ внутри цикла for.
Есть также много байтов, потраченных впустую, пытаясь объяснить, отправляет ли входная строка шаблон ниже индекса, с которого он начинался (возможно, если бы было ограничение на длину строки, я мог бы упростить этот бит).
И в удобочитаемом виде:
источник
b=[-2 -1 1 2](a==[106 107 94 118])
работать? Работает в Октаве. Или дажеb=[-2 -1 1 2](a-94==[12 13 0 24])
если вы хотите сбрить еще один байт!==
останавливается, что работает, а также в MATLAB вы не можете поставить()
после[]
.+=
, fwiw.)JavaScript (ES6), 140
Попробуйте запустить приведенный ниже фрагмент в браузере, совместимом с EcmaScript 6 (протестировано на Firefox).
источник
GS2, 34 байта
Это правильно вычисляет выходные границы, поэтому лишние пробелы не создаются. Вот мое решение в шестнадцатеричном
Небольшое объяснение в порядке. В стеке мы имеем ввод данных пользователем в виде массива кодов ascii. Программа запускается в строковом литерале из-за
05
. Вот так.GS2, 24 байта
У меня также есть 24-байтовое решение, которое не требует особой тщательности при расчете выходного размера, и в итоге получается лишний пробел. Я предпочитаю тот с пробелом, сохраненным к минимуму все же.
источник
Crayon , 13 байт (не конкурирует)
Попробуйте онлайн!Использует настоящие стрелки, потому что почему бы и нет.
Не конкурирует, потому что Crayon намного новее, чем этот вызов.
Как это работает
Crayon - это основанный на стеке язык, разработанный для того, чтобы убивать в ASCII-искусстве. Он построен на основе двумерного выходного «холста» и «мелка», курсора, который перемещается вокруг этого холста. Все, что отправлено на вывод, рисуется на холсте в позиции карандаша, и в направлении, куда карандаш обращен. По умолчанию карандаш указывает на восток (справа).
источник
pb - 136 байт
Использует
k
иj
вместо▲
и▼
.Пара заметок:
Escape sequences that move the cursor such as \e[B are not allowed. You must produce the output using spaces and newlines.
Я следую этому правилу! pb использует понятие «кисти» для вывода символов. Кисть перемещается вокруг «холста» и может печатать символ непосредственно под ним. Однако фактическая реализация печатает символ, используя пробелы и переводы строк.You are allowed trailing spaces and/or empty lines
. Это по нескольким причинам:n
он начинается сY=3n+1
.-1
Потому , что она идет вниз3n
отY=-1
, и начиная сY=2n-1
не выполняется для входа всехk
.Вы можете посмотреть эту программу в действии на YouTube! Эта версия немного видоизменена тем, что она сводится только к
n-1
. Это работает для этого входа, но не удастся для других. Это, однако, захватить гораздо приятнее.С комментариями:
источник
Цейлон, 447 байтов
Или с разрывами строки для «читабельности»:
import ceylon.language{o=null,v=variable,s=shared}s void y(){v L c;v L f;v L l;v Integer i=0;class L(v L?p,v L?n){s v String t="";s L u=>p else(f=p=L(o,this));s L d=>n else(l=n=L(this,o));s void a(Character c)=>t=t+" ".repeat(i-t.size)+c.string;}f=l=c=L(o,o);for(x in process.readLine()else""){switch(x)case('^'){c=c.u;}case('v'){c=c.d;}case('▲'|'k'){c=c.u.u;}case('▼'|'j'){c=c.d.d;}else{}c.a(x);i++;}print(f.t);while(f!=l){f=f.d;print(f.t);}}
Это работает как с вводом ▲ / ▼, так и с вводом j / k (если бы нам пришлось поддерживать только один из них, программа была бы на 8 байт короче). Последняя выходная строка пуста, когда на ней была начальная позиция (т. Е. Первый вход был a
▲
или^
и мы никогда не опускались ниже этого позже). Ввод, который не является одним из указанных символов, будет просто напечатан как есть, без переключения строки:→
Вот отформатированная версия (753 байта):
Это почти прямолинейная "объектно-ориентированная" программа ... (локальный) класс
L
(строковый буфер) хранит строку текста (int
), а также (обнуляемые) указатели на next (n
) и previous (p
) линия. Атрибуты (не обнуляемые)u
(для вверх) иd
(для вниз) инициализируют их, если необходимо (с обратным указателем на себя), и в этом случае также отслеживают первую и последнюю строку в целом (вf
иl
переменных).Метод
a
(append) добавляет символ к этой строке, включая некоторые пробелы, которые могут понадобиться.c
текущая строка Мы анализируем входную строку (используяreadLine
в качестве входных данных должна быть одна строка), используя инструкцию switch, которая обновляет текущую строку, а затем вызывает метод append.После разбора мы перебираем строки от первой до последней, печатая каждую из них. (Это уничтожает
f
указатель, если бы он был нужен впоследствии, мы должны были бы использовать для этого отдельную переменную.)Некоторые использовали трюки для игры в гольф:
Некоторые вещи, которые в других языках были бы ключевыми словами, на самом деле являются просто идентификаторами в
ceylon.language
пакете и могут быть переименованы с помощью псевдонима импорта - мы использовали это для аннотацийshared
(используется 5 ×) иvariable
(используется 6 ×), а также для объектаnull
(используется 4 ×):(Общая информация: Средство форматирования в IDE Ceylon форматирует некоторые встроенные аннотации на языке, между ними
variable
иshared
, помещая их в одну строку с аннотированной декларацией, сравнивается с пользовательскими аннотациями, которые помещаются в отдельной строке над декларацией. делает отформатированную версию программы гольфа недоступной для чтения, поэтому я изменил импорт псевдонимов для этой версии.)this
,void
,case
,else
Фактические ключевые слова и не могут быть переименованы таким образом, иInteger
,String
иCharacter
появляются только один раз, так что нет ничего , чтобы быть достигнуто за счет импорта.Первоначально у меня также был отдельный класс ScreenBuffer (который отслеживал связанный список строковых буферов, текущий индекс и т. Д.), Но, поскольку у него был только один объект, он был оптимизирован.
Этот класс Screenbuffer также имел
up
иdown
методы, которые вызывались из парсера (и только что делалиcurrentLine = currentLine.up
соответственноcurrentLine = currentLine.down
). Это показало, что непосредственное выполнение этого в переключателе парсера короче. Это также позволило писатьcurrentLine = currentLine.up.up
(что позже сталоc = c.u.u
) вместоcurrentLine = currentLine.up;currentLine = currentLine.up
.Первоначально мы передавали текущий индекс в качестве аргумента в метод добавления (и даже в анализатор из цикла) - иметь его в переменной, содержащей функцию, короче.
Первоначально мой метод printAll использовал текущий указатель и перемещал его сначала вверх, пока текущая строка не стала пустой, а затем вниз при печати каждой строки. Это сломалось при использовании ▲ и ▼, чтобы перепрыгнуть через строки, поэтому мы должны были явно добавить что-то в эти пропущенные строки вместо этого. Отслеживание первой / последней строки оказалось проще (хотя и потребовалось использовать два оператора печати, потому что в Цейлоне нет цикла do-while-loop).
Изначально у меня было что-то вроде этого:
process.readLine
возвращаетсяnull
если нет строки, которую можно прочитать (потому что вход был закрыт), и компилятор Цейлона требует, чтобы я проверил это, прежде чем я получу доступinput
. Поскольку в этом случае я ничего не хочу делать, я могу эквивалентно использоватьelse
оператор, который возвращает свой первый аргумент, если не ноль, и в противном случае его второй аргумент, сохраняя переменную и оператор if. (Это также позволит нам закодировать ввод по умолчанию для тестирования:for (x in process.readLine() else "^^▲^v▼▲^^v") {
)источник
JavaScript (ES6), 228 байт
Ну, вот (довольно длинное) рекурсивное решение, которое проходит все приведенные тесты. Это был хороший вызов. Это использует
k
иj
вместо▼
и▲
.Тестовый фрагмент
Хотя сама
k,j
отправка может обрабатывать только следующие фрагменты, можно обрабатывать какk,j
и▼,▲
.источник