С Днем Рождения V!


72

Спасибо @KritixiLithos за помощь в решении этой проблемы!


V - это язык программирования, который я написал, чтобы я мог использовать и расширять vim для задач, связанных с использованием кода. Самый первый коммит был 3 марта 2016 года, то есть сегодня V исполняется один год! Woo-Hoo

За первый год существования V было 176 коммитов от четырех разных участников, 140 ответов от 12 разных пользователей и слишком много неработающих дублирующих операторов, чтобы сосчитать . У него есть онлайн-переводчик , великодушно поддерживаемый @Dennis, который с декабря работал почти 8 000 раз .

Давайте вызовем отпраздновать день рождения V! Поскольку большинство функций в V разработаны с учетом работы со строками и , просто кажется естественным, что любой вызов празднованию V должен быть связан с ascii art. Таким образом, ваша задача на сегодня - принять слово в качестве входных данных и изменить это слово в форме буквы V. Например, вход «Hello» должен дать следующий V:

Hello         olleH
 Hello       olleH
  Hello     olleH
   Hello   olleH
    Hello olleH
     HellolleH
      HellleH
       HeleH
        HeH
         H

Вот некоторые подробности о том, как должен выглядеть ваш V. Если длина входной строки составляет n символов, значение V должно быть n*2высотой строки. Самая первая строка должна состоять из:

<input string><(n*2) - 1 spaces><input string reversed>

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

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

Happy:

Happy         yppaH
 Happy       yppaH
  Happy     yppaH
   Happy   yppaH
    Happy yppaH
     HappyppaH
      HapppaH
       HapaH
        HaH
         H

Birthday:

Birthday               yadhtriB
 Birthday             yadhtriB
  Birthday           yadhtriB
   Birthday         yadhtriB
    Birthday       yadhtriB
     Birthday     yadhtriB
      Birthday   yadhtriB
       Birthday yadhtriB
        BirthdayadhtriB
         BirthdadhtriB
          BirthdhtriB
           BirthtriB
            BirtriB
             BiriB
              BiB
               B

V!:

V!   !V
 V! !V
  V!V
   V

~:

~ ~
 ~

Конечно, поскольку это , стандартные лазейки запрещены, и ваша цель - написать максимально короткую программу для выполнения этой задачи. Удачного игры в гольф!


Что бы это ни стоило, у меня есть слабость к ответам vim, поэтому воображаемые бонусные баллы за использование vim или V, хотя любой язык приемлем. :)


Могу ли я печатать один нулевой символ (0x00) после каждой новой строки?
Wheat Wizard

@wheatwizard Хм. Это немного странно, но я думаю, это нормально, если результат визуально одинаков.
DJMcMayhem

21
5-й день рождения будет чем-то другим! (Римскими цифрами)
Альберт Реншоу

5
Наилучшие пожелания V-языку от Ви :-)
Ви Ви

Ответы:


44

MATL , 21 14 байт

MATL поздравляет V с днем ​​рождения!

tnEXyY+c3MZvZ)

Попробуйте онлайн!

объяснение

Рассмотрим вход

'Hello'

длины n=5. Код вычисляет двумерную свертку этой строки с единичной матрицей размера 2*n,

[1 0 0 0 0 0 0 0 0 0;
 0 1 0 0 0 0 0 0 0 0;
 0 0 1 0 0 0 0 0 0 0;
 0 0 0 1 0 0 0 0 0 0;
 0 0 0 0 1 0 0 0 0 0;
 0 0 0 0 0 1 0 0 0 0;
 0 0 0 0 0 0 1 0 0 0;
 0 0 0 0 0 0 0 1 0 0;
 0 0 0 0 0 0 0 0 1 0;
 0 0 0 0 0 0 0 0 0 1]

Результат свертки, преобразованный в char и с char 0, показанным как пробел, равен

['Hello         ';
 ' Hello        ';
 '  Hello       ';
 '   Hello      ';
 '    Hello     ';
 '     Hello    ';
 '      Hello   ';
 '       Hello  ';
 '        Hello ';
 '         Hello']

Затем столбцы [1, 2, ..., 2*n-1, 2*n, 2*n-1, ..., 2, 1]выбираются из этой матрицы символов, давая желаемый результат:

['Hello         olleH';
 ' Hello       olleH ';
 '  Hello     olleH  ';
 '   Hello   olleH   ';
 '    Hello olleH    ';
 '     HellolleH     ';
 '      HellleH      ';
 '       HeleH       ';
 '        HeH        ';
 '         H         ']

Код комментария

t      % Implicitly input string. Duplicate
nE     % Length, say n. Multiply by 2
Xy     % Identity matrix of that size
Y+     % 2D convolution. This converts chars to ASCII codes
c      % Convert to char
3M     % Push 2*n, again
Zv     % Push symmetric range [1, 2, ..., 2*n, 2*n-1, ..., 1]
Z)     % Apply as column indices. This reflects the first 2*n columns
       % symmetrically, and removes the rest. Implicitly display

Очень интересный подход! +1
сешумара

3
@seshoumara Спасибо! Как говорит Flawr, свертка является ключом к успеху :-)
Луис Мендо

38

V , 24, 23 , 20 байтов

3Ù2Ò Íî
Xæ$òâÙHãêxx>

Попробуйте онлайн!

Гораздо короче теперь, когда V имеет «обратный» оператор .

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

00000000: 33d9 32d2 20cd ee0a 58e6 24f2 e2d9 48e3  3.2. ...X.$...H.
00000010: ea78 783e                                .xx>

Объяснение:

3Ù                  " Make three extra copies of this current line
  2Ò                " Replace each character on this line and the next line with spaces
     Íî             " Join all lines together
X                   " Delete one space
 æ$                 " Reverse the word under the cursor

На данный момент буфер выглядит так:

Happy         yppaH

Нет, мы рекурсивно построим треугольник вниз.

ò                   " Recursively:
 â                  "   Break if there is only one non-whitespace character on this line
  Ù                 "   Make a copy of this line
   H                "   Move to the first line
    ã               "   Move to the center of this line
     ê              "   Move to this column on the last line
      xx            "   Delete two characters
        >           "   Indent this line

Здесь я хочу показать одну из моих любимых функций V. Многим командам требуется аргумент. Например, >команда будет отступать переменное число строк в зависимости от аргумента:

>>    " Indent this line (this command is actually a synonym for '>_')
>j    " Indent this line and the line below
>k    " Indent this line and the line above
6>>   " Indent 6 lines
>}    " Indent to the end of this paragraph
>G    " Indent to the last line
...   " Many many many more

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

òâÙHãêxx>>ò

Второе òнеявно заполнено. Круто то, что неявно завершенные команды применяют несколько уровней по глубине, поэтому, даже если мы только написали >, V неявно предоставит _свой аргумент и будет отступать текущую строку.


Я работал над этим, но я думаю, что вам более уместно ответить!
nmjcman101

29

Brainfuck , 152 байта

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

++++++++++[->+>+++<<]>>++>>+>>>,[[<]<<+>>>[>],]<[<]<<-[->+>>[>]>++++[-<++++++++>]<[<]<<]>[->++<]>[-<+>]<[<[-<+<.>>]<[->+<]>+>->>[.>]<[-]<[.<]<<<<<.>>>>]

С комментариями

++++++++++
[->+>+++<<] Insert 0 into the first buffer (Which we don't care about) 10 into the second and 30 into the thrd
>>++    Raise the third buffer to 32 making us our space
>   This buffer is reserved for the Insertable spaces counter
>
+>>>    Raise our incrementer This will be used to fill the other half of the string with spaces
,[  Read a byte
    [<]<<   Move to the back of the string buffer which is our incrementer
    +       increment it
    >>>[>]      And move to the next space of the string
    ,       And then read a new byte
]
<[<]<<-     Decrement the incrementer and begin to add spaces
[
    -       Decrement the incrementer
    >+      Raise the incrementer in the padding
    >>[>]   Move to a new part of the string buffer
    >++++[-<++++++++>]< Write a space
    [<]<<   Move all the way back to the string counter
]
BEGIN WRITING!!
>
[->++<]>[-<+>]<Double the incrementer
[
    <[  Move to the space counter
        -<+<.>> Decrement the space counter increment the temporary one to the left of it then print the space we stored to the left of that then return
    ]<[->+<]>+> Move the temporary space counter back
    -   Decrement the incrementer
    >>[.>]  Print every character from left to right
    <[-]    Snip the end off this
    <[.<]   Print every character from right to left
    <   Move back ot the incrementer
    <<<<.>>>> Print a newline aswell
]

Попробуйте онлайн!


23

> <> , 221 байт

Я потратил путь слишком много времени на это. С Днем Рождения, V!

l:2*01           p84*/v
 !@:$-1         /!?:$<
  1.v/ ^       v\~~>a
   vv\}o<     >ao  /
    1\/84/   :}o:$-
     \\!?<: l;!?\v
      p10-1:g10r\
       >  :>?\vv
        v:$-1/~
         </r+*
          </~
           l

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

python3 fish.py v.fish -s "ppcg" --tick 0.05 --play

что приводит к анимации ниже.

пример

Пример бега рыбы

(это занимает чуть меньше двух минут)

объяснение

Поскольку интересная часть этого ответа заключает его в Vформу, вот объяснение, которое ему соответствует. Мы используем следующую номерную версию для справки.

1. l:2*01           p84*/v
2.  !@:$-1         /!?:$<
3.   1.v/ ^       v\~~>a
4.    vv\}o<     >ao  /
5.     1\/84/   :}o:$-
6.      \\!?<: l;!?\v
7.       p10-1:g10r\
8.        >  :>?\vv
9.         v:$-1/~
10.         </r+*
11.          </~
12.           l

Иногда стрелки (→ ↓ ←) используются для указания направления, в котором достигается фрагмент.

  1. Инициализация

       1.→l:2*01           p84*/v
       2.  !@:$-1   X     /!?:$<
       3.   1.            \~~>a
    

    Первая строка переведет 2n в [0,1], оставит n в стеке и добавит один пробел. Затем мы поднимаемся и переходим ко второй строке справа, где мы начинаем идти налево. Есть цикл для добавления n + 1 пробелов. Это работает следующим образом.

                    Initial:                 "ppcg4 "
    !@:$-1 /!?:$<
               $     Swap.                   "ppcg 4"
              :      Duplicate.              "ppcg 44"
             ?       If more spaces to add:
        -1            Subtract 1.            "ppcg 3"
       $              Swap.                  "ppcg3 "
      :               Duplicate.             "ppcg3  "
     @                Rotate top 3.          "ppcg 3 "
    !                 Jump over stored value
                             and wrap around.
                    Else:
            /         Go to next part.
    

    После этого он возвращается к строке 3. Там удаляются два верхних элемента стека (0 и пробел) ( ~~), и мы переходим к позиции Xat [10,1] ( a1.), продолжая движение вправо. Мы поднимаемся в /, переходим к строке 7 и запускаем основной цикл программы.

  2. Основной цикл ( 2n раз)

     6.              ;!?\
     7.       p10-1:g10r\   ←
    

    Это условие цикла. Во-первых, стопка обращена для печати. Затем мы получаем счетчик из [1,0] ( 01g) и сохраняем уменьшенную версию ( :1-01p). Обернувшись вокруг и столкнувшись с проблемой, мы сталкиваемся с условием завершения программы. Если мы не закончим, мы перейдем к первому циклу печати.

    • Первая печатная петля (левая половина)

      5.    1\   /   :}o:$-
      6.     \\!?<: l         ←
      

      Мы начинаем с длины на вершине стека и выполняем следующий код, пока верхний элемент не равен 0.

      1-$:o}
      
      1-        Subtract 1.    "ppcg3"
        $       Swap.          "ppc3g"
         :      Duplicate.     "ppc3gg"
          o     Output.        "ppc3g"
           }    Rotate right.  "gppc3"
      

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

    • Подготовка правой половины

      5.  →    /84/   
      6.       \     
      7.            :    
      8.            >
      9.         v:$-1/~
      10.         </r+*
      11.          </~
      12.           l
      

      Это была одна из самых сложных частей для подбора. Ниже приведена версия, в которой нет указаний на то, что происходит.

                   Initial stack:   "    gcpp0"
      84*+r~
      84*          Push 32 == " ".  "    gcpp0 "
         +         Add 32 and 0.    "    gcpp "
          r        Reverse.         " gcpp    "
           ~       Remove top.      " gcpp   "
      

      Затем мы нажимаем длину того, что должно быть напечатано, и запускаем второй цикл печати (с первоначальным дубликатом, не являющимся частью цикла).

    • Вторая печатная петля (правая половина)

      3.     / ^ 
      4.     \}o<
      5.    
      6.           ↓   
      7.           
      8.       >  :>?\vv
      9.        v:$-1/~ 
      

      Выполняемый код полностью такой же, как и в первом цикле печати, с o}размещением немного дальше, потому что были доступные места. По окончании у нас осталось несколько дел, прежде чем мы сможем снова проверить инвариант основного цикла. После выполнения ~строки 9 мы оборачиваемся вертикально, заканчивая следующим фрагментом кода.

                      ↓
      2.          X     / 
      3.  1.v/             >a
      4.              >ao  /
      

      Сначала aoбудет напечатан перевод строки. Затем мы подпрыгиваем и достигаем точно такого же места после инициализации, а именно, прыжка к X.


Вы, вероятно, должны сделать версию для гольфа основной версией
Destructible Lemon

1
@DestructibleWatermelon пост больше посвящен V-версии, поскольку было гораздо сложнее сформировать все в определенной форме с ограниченным количеством доступных байтов. Поэтому объяснение будет следовать для версии V, а не простой. Я мог бы сделать действительно гольф позже.
PidgeyUsedGust

Это золото просто золото
Кристофер

Я ценю, что этот ответ на языке, название которого состоит исключительно из повернутых «V».
Sellyme

19

Brain-Flak , 486 + 1 = 489 байт

С Днем Рождения V от Brain-Flak!

Также спасибо 0 ', который предоставил часть кода, используемого в этом ответе

+1 из-за -cфлага, который требуется для входа и выхода ASCII

((([]<{({}<>)<>}<>([]){({}[()]<(([][()])<{({}[()]<({}<>)<>>)}{}><>)<>({}<<>{({}[()]<({}<>)<>>)}{}><>)(({})<>)<>>)}{}([][][()]){({}[()]<((((()()()()){}){}){})>)}{}<>{({}<>)<>}<>>){}[()])<{((({})<((({}){}())){({}[()]<(({}<(({})<>)<>>)<(({}<({}<>)<>>[()])<<>({}<<>{({}[()]<({}<>)<>>)}{}>)<>>){({}[()]<({}<>)<>>)}{}<>>)>)}{}{}((()()()()()){})(<()>)<>>)<{({}[()]<({}<>)<>>)}{}{}{}{({}<>)<>}<>>[()])}{}>()())([][()]){{}(({}[()])<{({}[()]<((((()()()()){}){}){})>)}{}{({}<>)<>}{}>)([][()])}{}<>

Попробуйте онлайн!

Без сомнения, это самая трудная вещь, которую я когда-либо делал в Brain-Flak.

Brain-Flak общеизвестно ужасен при дублировании и обращении строк, и эта задача состоит только из дублирования и обращения строк.

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

объяснение

Основная идея заключается в том, что мы сначала создадим верхнюю часть V, и каждая итерация удалит два символа из середины и добавит пробел в начало.

На практике это становится довольно сложно.

Существуют алгоритмы для копирования и реверсирования, поэтому я использовал один из них для создания обратной копии кода в оффстаке. После того, как я это сделал, я помещаю 2n-1пробелы поверх оригинального стека и перемещаю его обратно в стек, чтобы создать бутерброд.

Тест 1

Теперь у нас есть верхний ряд. Теперь мы хотим удалить два символа с начала и добавить пробел вперед. Это оказывается самой сложной частью. Причина этого заключается в том, что нам необходимо сохранить два значения: одно для глубины текущего фрагмента, а другое для глубины до центра V, где должно произойти удаление.

Это трудно.

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

Так как же это исправить? Короче говоря, мы не очень; мы пока игнорируем пробелы и исправляем их позже, мы добавим нули в код, чтобы пометить, куда пробелы должны идти, но в остальном мы ничего не будем делать.

Таким образом, на каждой итерации мы делаем копию последней итерации и помещаем ее в стек. Мы используем глубину, которую мы сохранили, чтобы разделить это пополам, чтобы у нас была левая половина V в правом стеке и правая половина V в левом стеке. Мы удаляем два элемента и соединяем их вместе. Мы добавили новую строку для хорошей меры и начали следующую итерацию. Каждый раз, когда глубина до центра V уменьшается на единицу, и когда она достигает нуля, мы останавливаем цикл.

Теперь у нас есть большая часть V построена. Однако нам не хватает надлежащих пробелов, и наш V в настоящее время немного (читай: полностью) с ног на голову.

Тест 2

Таким образом, мы перевернем это. Чтобы перевернуть его на другой стек, нам нужно переместить каждый элемент по одному. Поскольку мы перемещаем элементы, мы проверяем нули. Если мы сталкиваемся с одним из них, мы должны вернуть места туда, где они должны быть. Мы бросаем ноль и добавляем кучу пробелов. Откуда мы знаем, сколько? Мы отслеживаем; переворачивание стека в отличие от дублирования или реверсирования - очень неинтенсивная задача, поэтому у нас фактически есть память для хранения и доступ к дополнительному счетчику для отслеживания количества добавляемых пробелов. Каждый раз, когда мы добавляем несколько пробелов, мы уменьшаем счетчик на единицу. Счетчик должен достичь нуля на последней новой строке (в верхней части буквы V), и, таким образом, мы готовы к печати.

Наконец, мы убираем несколько вещей и закрываем программу для неявного вывода.

Тест 3


Очень впечатляет, что вам удалось заставить его работать вообще! Как вы думаете, вы могли бы сохранить байты, оставив их в обратном порядке и добавив -rфлаг?
DJMcMayhem

@DJMcMayhem Я так не думаю. Процесс перестановки и вставка пробелов происходят одновременно, поэтому, если я добавлю -rфлаг, мне нужно будет на самом деле поменять его в другой раз. Там, где я нахожусь, уже поздно, но я думаю, что завтра я постараюсь существенно поиграть в эту игру. Если я смогу решить проблему с пробелами, я обязательно буду использовать -rфлаг.
Wheat Wizard

16

Желе , 15 12 байт

⁶ṁ⁸;;\Uz⁶ŒBY

Попробуйте онлайн!

Как это устроено

⁶ṁ⁸;;\Uz⁶ŒBY  Main link. Argument: s (string)

⁶ṁ            Mold ' ' like s, creating a string of len(s) spaces.
  ⁸;          Prepend s to the spaces.
    ;\        Cumulative concatenation, generating all prefixes.
      U       Upend; reverse each prefix.
       z⁶     Zip/transpose, filling empty spots with spaces.
         ŒB   Bounce; map each string t to t[:-1]+t[::-1].
           Y  Join, separating by linefeeds.

Это 12 символов, но есть ли какая-нибудь кодировка, в которой он будет выглядеть как 12 байтов?
kasperd

1
Да, Jelly использует свою собственную кодовую страницу .
Деннис


16

JavaScript (ES6), 108 106 98 94 байтов

f=
s=>s.repeat((j=l=s.length*4)*2).replace(/./g,_=>--j?s[j+j<l?j-i:l-i-j]||` `:(j=l,++i,`
`),i=1)
<input oninput=o.textContent=f(this.value)><pre id=o>


Вы могли бы сделать пост, объясняющий это? Я немного смущен заменой и регулярными выражениями.
Джейкоб Перси

@JacobPersi Они - красная сельдь. Все , что нужно это выходная область размера n*2от n*4( в том числе новых строк в конце каждой строки). Затем я вычисляю символ, который должен появиться в каждой ячейке.
Нил

Приятно! Вы можете сбрить байт, удалив символ новой строки между f=и s=>.
yummypasta

@yummypasta Это f=только часть фрагмента, а не ответ. Как таковой, он не включен в число байтов.
Нил

11

Retina , 51 47 байт

С Днем Рождения!

Число байтов предполагает кодировку ISO 8859-1.

$
$.`$* 
$
¶$`
O$^r`.\G

;{*`.¶

(\S.*).¶.
 $1¶

Попробуйте онлайн!

объяснение

$
$.`$* 

Это добавляет nпробелы (где nдлина строки), сопоставляя конец строки, получая длину строки $.`и повторяя пробел, который много раз с $*.

$
¶$`

Мы дублируем всю строку (разделенную переводом строки), снова сопоставляя конец строки и вставляя саму строку с помощью $`.

O$^r`.\G

Это переворачивает вторую строку путем сопоставления справа налево ( r), затем сопоставляя один символ за раз ( .), но убедившись, что они все смежные ( \G). Таким образом, матчи не могут пройти через перевод строки. Это тогда используется в стадии сортировки. Используя метод sort-by ( $), но заменяя каждое совпадение пустой строкой, фактическая сортировка не выполняется. Но из-за этой ^опции, спички в конце меняются местами, переворачивая всю вторую строку.

;{*`.¶

Эта стадия предназначена для вывода и также влияет на остальную часть программы. {оборачивает оставшиеся этапы в цикл, который повторяется до тех пор, пока эти этапы не изменят строку (что произойдет, потому что последний этап больше не будет соответствовать). ;Выход отключает в конце программы. На *очереди этого этапа в сухую перспективе это означает , что этап обработку и результат выводится, но после предыдущей строки восстанавливается.

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

(\S.*).¶.
 $1¶

Наконец, этот этап превращает каждую строку в следующую. Это делается путем вставки пробела перед первым непробельным символом, удаления последнего символа в первой строке, а также первого символа во второй строке. Этот процесс останавливается, когда в первой строке остается только один непробельный символ, соответствующий последней строке выходных данных.


Хотелось бы объяснить, как это работает. Я знаю, что синтаксис sed менее компактен, но мой черновик в два раза длиннее. Обратная строка и соединение первой выходной строки - это большая часть.
Сешумара

@seshoumara Конечно, вы идете.
Мартин Эндер

Благодарю. Теперь я знаю, что Sed-скрипт двойной длины - это неплохо :)) из-за дополнительных s///символов, которые складываются, из-за более длинного обращения строк и других операций, в которых нет тонкости Retina. Хорошо читать. +1
сешумара

9

05AB1E , 12 байтов

Dgð×J.p€ûR.c

Попробуйте онлайн!

объяснение

D             # duplicate input
 g            # length of copy
  ð×J         # append that many spaces to input
     .p       # get a list of all prefixes
       €û     # turn each into a palindrome
         R    # reverse the list
          .c  # pad each line until centered

Или для того же подсчета байтов с другого направления.

Âsgú.sí€ûR.c

объяснение

             # push a reversed copy of input
 s            # swap the input to the top of the stack
  g           # get its length
   ú          # prepend that many spaces
    .s        # get a list of all suffixes
      í       # reverse each
       €û     # turn each into a palindrome
         R    # reverse the list
          .c  # pad each line until centered

2
Если вы отступа комментарии пошагово, то даже источник выглядит как V :)
aross

9

Japt, 22 20 16 14 + 2 байта

Джапт желает V успешных лет игры в гольф!

²¬£²îU²ç iYU)ê

Требуется -Rфлаг. Проверьте это онлайн!

объяснение

Это использует çи îфункции я добавил несколько дней назад:

²¬£²îU²ç iYU)ê    Implicit: U = input string
²                 Double the input string.
 ¬                Split into chars.
  £               Map each char X and index Y by this function:
     U²             Take the input doubled.
       ç            Fill this with spaces.
         iYU        Insert the input at index Y.
    î       )       Mask: repeat that string until it reaches the length of
   ²                the input doubled.
                    This grabs the first U.length * 2 chars of the string.
             ê      Bounce the result ("abc" -> "abcba").
                  Implicit: output result of last expression, joined by newlines (-R flag)

Техника Денниса на байт длиннее:

U+Uç)å+ mw y mê

5

GNU sed , 110 100 + 1 (флаг r) = 101 байт

Изменить: 9 байтов короче благодаря Райли

Как еще один язык манипулирования строками, sed желает V всего наилучшего!

h;G
:;s:\n.: \n:;t
h;:r;s:(.)(\n.*):\2\1:;tr
H;x
s:\n\n ::
:V
h;s:\n::p;g
s:^: :;s:.\n.:\n:
/\n$/!tV

Попробуйте онлайн!

Объяснение: предполагается, что ввод - последний тестовый случай ('V!'). Для ясности я покажу пространство шаблонов на каждом шаге, заменив пробелы символами «S».

h;G                       # duplicate input to 2nd line: V!\nV!
:;s:\n.: \n:;t            # shift each char from 2nd line to 1st, as space: V!SS\n
h;:r;s:(.)(\n.*):\2\1:;tr # save pattern space, then loop to reverse it: \nSS!V
H;x                       # append reversed pattern to the one saved V!SS\n\n\nSS!V
s:\n\n ::                 # convert to format, use \n as side delimiter: V!SS\nS!V
:V                        # start loop 'V', that generates the remaining output
h;s:\n::p;g               # temporarily remove the side delimiter and print pattern
s:^: :;s:.\n.:\n:         # prepend space, delete char around both sides: SV!S\n!V
/\n$/!tV                  # repeat, till no char is left on the right side
                          # implicit printing of pattern left (last output line)

@Riley Ответ обновлен, спасибо!
Сешумара

4

Python, 110 байт

Попробуйте онлайн!

Я уверен, что это не оптимально, но по крайней мере это довольно Pythonic:

def f(s):n=len(s)*2-1;return''.join(i*' '+s[:n+1-i]+(n-2*i)*' '+s[n-i-1::-1]+'\n'for i in range(n))+n*' '+s[0]

4

Джольф, 31 байт

Джольф с неохотой поздравляет В с днем ​​рождения!

RΜwzΒώlid+γ_pq_ l+*␅Hi0ΒΒ␅ L_γ1S

Попробуй это здесь! должно быть 0x05.

объяснение

RΜzΒώlid+γ_pq_ l+*␅Hi0ΒΒ␅ L_γ1S  i = input
     li                                  i.length
    ώ                                2 * 
   Β                             Β =
  z                              range(1, Β + 1)
 Μ     d                         map with: (S = index, from 0)
                +                 add:
                 *␅H               S spaces
                    i              and the input
               l                  slice (^) from
                     0Β            0 to Β
           pq_         Β␅         pad (^) with spaces to the right
         γ_                       γ = reverse (^)
        +                 L_γ1    γ + behead(γ)
R                             S  join with newlines

4

Древесный уголь , 29 байт

С Днем Рождения V, от твоего приятеля, разочаровывающего язык искусства ASCII!

SσF…·¹Lσ«Fι§σκMι←↖»Fσ«Pσ↖»‖O→

Попробуйте онлайн!

объяснение

Наша стратегия: печатать левую половину буквы V, начиная снизу и двигаясь вверх слева; затем отразить это.

Sσ                                    Input σ as string
                                       The bottom len(σ) half-rows:
   F…·¹Lσ«           »               For ι in inclusive range from 1 to length(σ):
            Fι                          For κ in range(ι):
               §σκ                         Print character of σ at index κ
                  Mι←                   Move cursor ι spaces leftward
                      ↖                  Move cursor one space up and left
                                       The top len(σ) half-rows:
                        Fσ«    »      For each character ι in σ:
                            Pσ          Print σ without moving the cursor
                               ↖         Move cursor one space up and left
                                 ‖O→  Reflect the whole thing rightward, with overlap

(Если бы только древесный уголь имел нарезку строк ... увы, похоже, это еще не было реализовано.)


Хотя в Charcoal не было среза строки, он имелся CycleChop, что можно использовать для извлечения заголовка строки, что позволило сэкономить 4 байта. Тем не менее, есть лучший подход, который экономит 9 байтов. Еще несколько сбережений, которые, я думаю, также работали в то время: Reflectзначения по умолчанию отражают справа, сохраняя еще один байт, и одна из переменных предопределена для первого ввода, сохраняя два байта.
Нил

4

Пип , 32 25 байт

a.:sX#aL#a{OaDQaPRVaaPUs}

Принимает входную строку в качестве аргумента командной строки. Попробуйте онлайн!

объяснение

                           a is 1st cmdline arg, s is space (implicit)
     #a                    Len(a)
   sX                      Space, string-multiplied by the above
a.:                        Concatenate that to the end of a
       L#a{             }  Loop len(a) times (but NB, a is now twice as long as it was):
           Oa                Output a (no trailing newline)
             DQa             Dequeue one character from the end of a
                PRVa         Print reverse(a) (with trailing newline)
                    aPUs     Push one space to the front of a

4

R с пакетом stringi, 225 байт

library(stringi)
f=function(){
s=scan(,'',1,sep="\n")
m=2*nchar(s)
l=stri_pad(sapply(1:m-1,function(x)substr(paste(paste(rep(" ",x),collapse=""),s),1,m)),m,"right")
r=substr(stri_reverse(l),2,m)
message(paste0(l,r,"\n"))}
f()

Если вы запускаете R в интерактивном коде, после вставки моего ответа просто введите что-нибудь. Вам понадобится установить пакет stringi R (надеюсь, это не противоречит правилам).

Объяснение:

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

library(stringi)
make_V <- function(){                  # declaring the function
  string <- scan(, '', n=1, sep="\n")  # reading input
  max_length <- 2*nchar(string)        # number of chars in each half row

  # creating the left side of the V

  left <- stri_pad(                    
            sapply(1:max_length-1,     # for each row
                   function(x){     
                    substr(            
                      paste0(
                        paste0(rep(" ", x),
                               collapse=""), string), # add spaces to left side
                           1,
                           max_length) # cut the unneeded end
                    }),
            width=max_length,
            side="right")              # add spaces to the right side

  # creating the right side of the V

  right <- substr(stri_reverse(left), 2, max_length)

  # print it without any symbols before the strings 
  message(paste0(left, right, "\n"))
}

# run the function
make_V()

Добро пожаловать на сайт! :)
DJMcMayhem

4

Рубин, 92 89 85 байт

s=gets.chomp
s<<" "*n=s.size*2
n.times{s=s[0..(n-1)]
puts s+s.reverse[1..-1]
s=" "+s}

Мой процесс состоял в том, чтобы удалить первый символ из правой половины каждой строки после изменения первой половины. Нравится:

Hello     |    olleH
 Hello    |   olleH 
  Hello   |  olleH  
   Hello  | olleH   
    Hello |olleH    
     Hello|lleH     
      Hell|leH      
       Hel|eH       
        He|H        
         H|         

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


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

Спасибо! На этой странице есть много интересных вещей, но я, кажется, уже делаю много из них. Я понял, что могу сохранить некоторые байты с помощью побочных эффектов и порядка операций.
user3334690

1
Я предполагаю, что [Ruby] - это просто Ruby, более или менее известный язык программирования?
Rɪᴋᴇʀ

Вы можете сэкономить 8 байт , сделав это лямбда-выражением .
Иордания

4

Пакет, 186 185 байт

@set e=@set 
%e%/ps=
%e%t=%s%
%e%r=
:l
%e%s=%s% 
%e%r= %r%%t:~-1%
%e%t=%t:~,-1%
@if not "%t%"=="" goto l
:g
%e%r=%r:~1%
@echo %s%%r%
%e%s= %s:~,-1%
@if not "%r%"=="" goto g

Линии 1 и 6 имеют завершающий пробел. Редактировать: 1 байт сохранен благодаря @ ConorO'Brien.


1
Вот запутанный способ сохранить байт . (создайте псевдоним для @set и удалите @echo off, вставляя по @мере необходимости.
Конор О'Брайен,

@ ConorO'Brien Спасибо, я бы никогда не подумал, что 8 setсекунд сэкономят мне достаточно байтов, чтобы это стоило того.
Нил

3

Haskell , 76 байт

vявляется основной функцией, принимая Stringаргумент и давая Stringрезультат.

v i=unlines.r$i++(' '<$i)
r""=[]
r s|t<-init s=(s++reverse t):map(' ':)(r t)

Попробуйте онлайн!

Примечания:

  • i это начальный аргумент / вход.
  • sизначально iс length iпробелами
  • v iзвонки r s, а затем соединяет строки результатов.
  • rвозвращает список Stringстрок.
  • tэто sс последним символом отрубили.
  • Рекурсия r tсоздает строки, кроме первой, минус начальный пробел в каждой строке.

2
+1 за наименование основной функции v. : D
DJMcMayhem

1
@DJMcMayhem: не называя основной функцией является один байт больше: unlines.r.((++)<*>(' '<$)).
Ними

1
@nimi Полагаю, ему понравилось, какое имя я выбрал. Технически лямбда-связи ... Когда я писал ответ, я не знал, что вы могли бы использовать объявления верхнего уровня для некоторых функций, но не называть основную функцию. Хотя я видел, как кто-то другой делал это, я нахожу это несколько тревожным. В эти дни это работает в GHCi по крайней мере.
Орджан Йохансен

3

Желе , 13 байт

⁶ṁ;@µḣJUz⁶ŒBY

Попробуйте онлайн!

Как?

⁶ṁ;@µḣJUz⁶ŒBY - Main link: string s
⁶             - space character
 ṁ            - mould like s: len(s) spaces
  ;@          - concatenate s with that
    µ         - monadic chain separation (call that t)
      J       - range(length(t))
     ḣ        - head (vectorises): list of prefixes from length to all
       U      - upend: reverse each of them
        z     - transpose with filler:
         ⁶    -     space: now a list of the left parts plus centre
          ŒB  - bounce each: reflect each one with only one copy of the rightmost character
            Y - join with line feeds
              - implicit print

Как и умы, мыслят великолепно. : P
Деннис

О боже, я не думал о совокупной конкатенации! У угля есть направление V, может быть, какое-то расследование поблизости ...
Джонатан Аллан

3

Рубин, 85 83 байта

редактировать: удалены лишние пробелы

s=ARGV[0];s+=' '*s.length;s.length.times{|i|puts s+s[i..-2].reverse;s=' '+s[0..-2]}

На самом деле мне было довольно сложно сыграть в гольф в Ruby. После добавления пробела он расширяется до довольно читабельного фрагмента кода:

s = ARGV[0]
s+=' ' * s.length

s.length.times do |i|
  puts s + s[i..-2].reverse
  s = ' ' + s[0..-2]
end

1
Вы могли бы немного сэкономить, установив s.length в переменную, как я? Кроме того, я думаю, вы должны рассмотреть размер вместо длины?
user3334690

Делаем то, что предложил @ user3334690, и перемещаем оператор .times, 79 байт:s=ARGV[0];(s+=' '*s.size).size.times{|i|puts s+s[i..-2].reverse;s=' '+s[0..-2]}
Конор О'Брайен,

Вы можете сохранить пять байтов, сделав это лямбда- выражением .
Иордания

3

MATLAB (R2016b), 223 183 байта

r=input('');l=nnz(r)*2;for i=1:l;m=l+1-2*i;c={' '};s=cell(1,i-1);s(:)=c;x=cell(1,m);x(:)=c;e=r;y=flip(r);if(m<1);e=r(1:2*end-i+1);y=r(l/2+end-i:-1:1);end;disp(cell2mat([s e x y]));end

Первый раз Код Гольф. Советы приветствуются!

Выход программы:

MATLAB Код Гольф

Редактировать:

Сохранено 40 байтов благодаря Луису Мендо.


2
Добро пожаловать в PPCG и приятного первого ответа! К сожалению, я ничего не знаю о MATLAB, поэтому я не могу помочь вам в этом, но, возможно, вы найдете некоторые полезные советы :-)
ETHproductions

1
Ввод строки, включая кавычки, разрешен по умолчанию. Так что вы можете удалить 's'из input. Кроме того, я не понимаю, почему вы используете evalc(disp(...)), но я думаю, что вы можете просто использовать cell2mat этот путь
Луис Мендо

1
Кроме того, flipкороче end:-1:1, смотрите здесь
Луис Мендо

3

PHP, 95 92 85 80 78 77 байт

Примечание: используется кодировка IBM-850

for($s.=strtr($s^$s=$argn,~ ,~▀);~$s[$i++];)echo$s,strrev($s=" $s"^$s^$s),~§;
          # Note that this ^ char is decimal 255 (negating it yields "\0")

Запустите так:

echo "Hello" | php -nR 'for($s.=strtr($s^$s=$argn,"\0",~▀);~$s[$i++];)echo$s,strrev($s=" $s"^$s^$s),~§;'
> Hello         olleH 
>  Hello       olleH  
>   Hello     olleH   
>    Hello   olleH    
>     Hello olleH     
>      HellolleH      
>       HellleH       
>        HeleH        
>         HeH         
>          H          

объяснение

for(
  $s.=strtr(             # Set string to the input, padded with spaces.
    $s^$s=$argn,         # Input negated with itself, leads to string with
                         # only null bytes with the same length.
    ~ ,                  # Replace null bytes...
    ~▀                   # ... with spaces.
  );
  ~$s[$i++];             # Iterate over the string by chars, works because 
                         # there are just as many lines as the padded
                         # string has chars.
)
  echo                   # Output!
    $s,                  # The string.
    strrev(              # The reverse of the string.
      $s=" $s"^$s^$s     # After each iteration, prefix string with a
    ),                   # space, and trim the last character.
    ~§;                  # Newline.

Tweaks

  • Сэкономили 3 байта, избавившись от символа pad (по str_padумолчанию пробел, что нам и нужно)
  • Сохранено 7 байт с использованием бинарных операций над строкой для ее усечения вместо substr
  • Сохранение 5 байтов путем поворота строки при печати реверса. Предотвращает необходимость печати пробела, но приводит к завершающему пробелу в каждой строке.
  • Сохранение 2 байтов путем заполнения строки с использованием более сложного, но более короткого метода.
  • Сохраненный байт из-за того, что нет необходимости учитывать ~"0"регистр (ASCII 207), так как все входные данные можно считать печатными ascii (Thx @Titus)

echo$s,strrev($s=" $s"^$s^$s),~§;экономит 5 байтов.
Титус

@ Titus, спасибо. Обычно избежать конечные пробелы, но ОП сказал , что это приемлемо
aross

~$s[$i++]достаточно (входные данные для печати ASCII, и так $s
Тит

@ Titus, спасибо, хороший улов. Я , как правило, код на безопасной стороне
aross

2

JavaScript (ES6), 169 157 байт

(-10 байтов благодаря Конору О'Брайену)

V=(j,i=0,p="")=>i<(f=j.length)*2?V(j,-~i,p+" ".repeat(i)+j.slice(0,f-i*(i>f))+" ".repeat(i<f?(f-i)*2-1:0)+[...j.slice(0,f+~i*(i>=f))].reverse().join``+`
`):p

Рекурсивное решение. Я новичок в JavaScript, поэтому, пожалуйста, будьте осторожны! Любые советы по гольфу очень ценятся. :)

И, конечно же, очень поздравляю вас с днем ​​рождения V!

Тестовый фрагмент


1
Это очень хорошо! Как правило, s.split("")может быть изменено на [...s]и a.join("")может a.joinсопровождаться парой кавычек. Вы можете сохранить дополнительные 3 байта, заменив [r='repeat']и [r]повторив обычное, то же самое с slice.
Конор О'Брайен

@ ConorO'Brien Спасибо за советы! Они очень ценятся. :)
Р. Кап

2

CJam , 26 байт

С днем ​​рождения от твоего старого приятеля CJam!

q_,2*:L,\f{LS*+m>L<_W%(;N}

Попробуйте онлайн!

объяснение

q                           Push the input
 _,2*:L                     Push 2 times the length of the input, store it in L
       ,                    Take the range from 0 to L-1
        \                   Swap top stack elements
         f{                 Map over the range, using the input as an extra parameter
           LS*+               Append L spaces to the input
               m>             Rotate the resulting string right i positions (where i is the
                               current number being mapped)
                 L<           Take the first L characters of the string
                   _W%        Duplicate it and reverse it
                      (;      Remove the first character from the copy
                        N     Add a newline
                         }  (end of block)
                            (implicit output)

2

PowerShell, 126 байтов, 124 байта

$l=($s="$args")|% Le*;$r=-join$s[-1..-$l];0..($l*2-1)|%{' '*$_+($s+' '*$l).substring(0,$l*2-$_)+(' '*$l+$r).substring($_+1)}

Вызовите его с одним параметром, например .\V.ps1 Hello.

Изменить: 2 байта сохранены с подсказкой от AdmBorkBork


1
Попробуйте его в Интернете! ссылка, на случай, если вам интересно.
Деннис

О, я не знал об этом маленьком инструменте, спасибо!
Тор

Всем привет! Пара маленьких гольфов на передней панели. Возьмите входные данные как строку и используйте инкапсуляцию для передачи переменной. Сохраняет два байта. $l=($s="$args")|% Le*;
AdmBorkBork

Ничего себе, не знал о тех двух гольфах, спасибо!
Тор


2

JavaScript (ES6), 94 байта

f=(s,y=0,x=0,l=s.length*2-1)=>(s[(x>l?l*2-x:x)-y]||' ')+(x<l*2?f(s,y,x+1):y<l?`
`+f(s,y+1):'')

Контрольные примеры


2

J, 44 байта

(([(,}.@|.)@{."1-@i.@[|."0 1(,#&' ')~)~+:@#)

1
Хм, я не могу понять, как запустить это онлайн. Попробуйте онлайн! Я просто называю это неправильно? (Я
новичок

@DJMcMayhem Это функция, а не программа. tio.run/nexus/…
Деннис

Гольф: |."0 1до |."{(сохранено 2 байта)
Конор О'Брайен

Кроме того, вам не нужно иметь внешние скобки.
Конор О'Брайен
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.