Нарисуй мои вниз


60

Как программист, вы, вероятно, слышали о прямом и обратном слеше. Но вы слышали о падениях? Вот когда вы берете кучу слешей, соединяете их концы и рисуете их вниз.

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

\
 \
  \
  /
 /
 \
 /
 \
  \

Вот некоторые уточнения:

  • В каждой строке должен быть один слеш.

  • В первой строке будет 0 пробелов.

  • Для каждой пары слешей:

    • Если они отличаются друг от друга, они будут отображены в одном столбце. Например, \/даст:

      \
      /
      
    • Если они такие же характер, нижний в направлении указал на, что движется вправо для обратной косой черты, а перемещение влево для прямой косой черты. Так \\//даст

      \
       \
       /
      /
      
  • Каждая строка может иметь дополнительный пробел, если это не меняет внешний вид вывода. Допускается до одного трейлинга и ведущего символа новой строки. Дополнительные пробелы не допускаются !

Чтобы сделать это проще, вы можете предположить, что строка никогда не будет содержать слишком много прямых косых черт. Другими словами, ни один префикс ввода не будет содержать больше прямых косых черт, чем обратной косой черты, поэтому такой ввод, как \\////или //никогда не будет дан. Это также означает, что каждый ввод будет начинаться с обратной косой черты.

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

Вы можете выводить в любом разумном формате .

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

Примеры

#Input
\\\\\\\\\\\

#Output
\
 \
  \
   \
    \
     \
      \
       \
        \
         \
          \

#Input
\\\//\\/\//\\///

#Output
\
 \
  \
  /
 /
 \
  \
  /
  \
  /
 /
 \
  \
  /
 /
/


#Input
\/\/\/

#Output
\
/
\
/
\
/


Ответы:


20

GNU Sed, 20

s|\\|&^L|g
s|/|^H/^L^H|g

Обратите внимание, что ^Lи ^Hявляются буквальными символами формы и возврата (0x12 и 0x8).

Этот ответ работает путем перемещения курсора с помощью символов возврата и возврата. Косая черта / обратная косая черта не дополняются пробелами слева - Не уверен, что это дисквалифицирует этот ответ. Это не работает в TIO, но выглядит хорошо под общими терминалами, такими как xtermи gnome-terminal.

Воссоздайте этот сценарий sed следующим образом:

base64 -d <<< c3xcXHwmDHxnCnN8L3wILwwIfGc= > downslash.sed

Запустите его следующим образом:

$ echo '\\\//\/\\' | sed -f downslash.sed
\ 
 \ 
  \ 
  /
 /
 \ 
 /
 \ 
  \ 

$ 

Объяснение:

s|\\|&^L|g     # move cursor down after every "\"
s|/|^H/^L^H|g  # move cursor left before every "/", then after, down and left again

14

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

FS¿⁼ι/↓¶/↘ι

Попробуйте онлайн! Ссылка на подробную версию кода. Поддерживает дополнительные //с. Объяснение:

 S              Input string
F               Loop over each character
  ¿             If
    ι           Current character
   ⁼            Equals
     /          Literal /
      ↓¶        Move left
      ↓ /       Print a / downwards
         ↘ι     Else it's a \ so print that down and right

Я думаю ↓¶= "Двигайся влево" в описании не правильно.
Джонатан Аллан

@JonathanAllan Правильно (новая строка напечатана вниз = переместиться влево), хотя, вероятно, было бы яснее сказать «напечатать \n/вниз»
только для ASCII,

Я не сказал, print \n/ downпотому что чувствовал, что было бы более полезно описать эффект кода, а не его буквальный перевод.
Нил

1
(Язык в щеке: описание эффекта = MyCode - Do the spec). Теперь я понимаю, что эффект - двигаться влево; возможно, стоит сказать «Переместить влево (печатая новую строку с направлением печати вниз)».
Джонатан Аллан

Самый лаконичный и понятный из всех!
j4hangir


10

/// , 119 байт

/// не имеет команд ввода, поэтому ввод должен быть встроен в программу. Для этого входная строка просто добавляется без необходимости экранирования.

/=/\/\///M/
|%%=N/%|||=C/BA=\/\\/\/C\\=C\\/CbC=B\A\=CfC=AB=/A/%Mxy=B/|z%N|x|y% %N%x|y%%% |fzN%M%b|zN|M|%
=|/AB\\=%/|=AC

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

  • В дальнейшем ввод \\/\//будет добавлен в программу для демонстрации.
  • используется для представления новых строк во встроенном коде

Сокращения

Начало /=/\/\///M/␤|%%=N/%|||=C/BA=программы содержит замены для сокращений для игры в гольф.

  • =расширяется //, Mчтобы ␤|%%, Nчтобы %|||и Cчтобы BA.
  • После этого текущая программа становится

    /\/\\/\/BA\\//BA\\/BAbBA//B\A\//BAfBA//AB///A/%
    |%%xy//B/|z%%||||x|y% %%|||%x|y%%% |fz%|||%
    |%%%b|z%||||
    |%%|%
    //|/AB\\//%/|//ABA\\/\//
    

Входное перекодирование

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

  • Первая существенная замена /\/\\/\/BA\\/, заменяет строку /\на /BA\.
    • Базовая программа не содержит /\в настоящее время, поэтому эта замена не влияет на нее.
    • Однако это разбивает добавленную входную строку на последовательности \s, за которыми следуют последовательности /s, что вместе с символом в ABAконце базовой программы позволяет выполнять итерацию по ней со следующими заменами.
    • Включая ABAпрефикс перед ним, пример входной строки теперь становится ABA\\/BA\//.
  • Следующая замена /BA\\/BAbBA/, заменяет BA\на BAbBA.
    • Поскольку /// подстановки повторяются до тех пор, пока они больше не совпадают, это повторяет все \s входной строки, которая теперь с префиксом становитсяABAbBAbBA/BAbBA//
  • Аналогичным образом , /B\A\//BAfBA/изменения BA/в BAfBA, переборе /с.
    • Экранирование \в этой замене необходимо, так как в противном случае оно будет искажено предыдущим.
    • Вход теперь превратился в ABAbBAbBAfBABAbBAfBAfBA.
  • Далее /AB//удаляет некоторые лишние части кодировки, превращая его в AbBAbBAfBAbBAfBAfBA.
    • Это также удаляет ABиз /|/AB\\/подстановки позже в программе, которая была необходима, чтобы защитить его от вышеуказанных /\манипуляций.
    • В этот момент каждый \в исходной входной строке стал AbB, и каждый /стал AfB. ( bи fстоять вперед и назад.) В Aконце есть бродяга .
  • Следующие две замены заменяют все As и Bs фрагментами программы для запуска на заключительном этапе. В строках замены %s и |s кодируют то, что станет /s и \s соответственно. Это имеет два преимущества:
    • В отличие от /and \, %s и |s не требуют экранирования для копирования.
    • Строки замены избегают подстроки /\, которая иначе была бы искажена предыдущими манипуляциями.
  • После этого подстановка /|/\\/(ранее /|/AB\\/) теперь декодирует |s, после чего следующее /%/|//становится /%/\//и декодирует %s.

Структура программы на завершающем этапе

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

  • Каждый входной символ стал подпрограммой

    /
    \//xy*\z//\\\\x\y/ //\\\/x\y/// \fz/\\\/
    \///b\z/\\\\
    \//\/
    

    (завершающий перевод строки), где *представляет либо fоригинал /, либо bоригинал \.

  • В /␤\//xyконце программы также есть команда неполного замещения , которая не будет иметь никакого эффекта, кроме как обеспечить необходимые /для подстановок предыдущей подпрограммы.

Общая подстрока

Перед началом последней итерации по подпрограммам существует подстрока, пересекающая границу после подпрограммы каждого символа в форме \/␤/.

  • Эти подстроки используются в качестве общего глобального состояния. Все остальные подстановки в программе будут манипулировать ими одинаково и параллельно, так что в конце подпрограммы каждого входного символа /будет запущена его копия этой общей подстроки (кроме последней , которая привязывает подстановки), чтобы напечатать строку для этого характер.
  • Первоначальная версия подстроки представляет собой печать строки, содержащей just /, которая представляет собой правую воображаемую «предыдущую строку», в результате чего первый входной символ будет напечатан в начале его строки.
  • Как правило, на этапах печати общая подстрока состоит из нескольких пробелов, \\или \/новой строки, и следующего /.

Запуск символьной подпрограммы

Некоторые из следующих подстановок содержат дополнительные \s внутри, чтобы предотвратить их сопоставление и искажение друг с другом (включая другие копии в других подпрограммах). Достижение этого также является причиной того, что и то, xи другое yнеобходимо.

  • Первая подстановка в символьной подпрограмме, /␤\//xyf\z/или /␤\//xyb\z/, приводит к тому, что ␤/в конце разделяемой подстроки становится xyfzили xybz, сразу же после \/или \\.
  • Замещение /\\\\x\y/ /заменяет \\xyпробел и замена /\\\/x\y//заменяет \/xyничем.
    • Они применяются, когда предыдущий напечатанный символ ввода был \или /, соответственно.
    • Совместно используемая подстрока теперь содержит соответствующее количество пробелов для печати \следующего, за которым следует fzили bz.
  • Замена / \fz/\\\/␤\// заменяется ​ fzна \/␤/и /b\z/\\\\␤\//заменяется bzна \\␤/.
    • Они применяются, когда текущий входной символ равен /или \, соответственно.
    • Первый съедает дополнительное место для /правильного размещения.
      • Если это пространство отсутствует (т. Е. Ввод, нарушающий условие префикса), следующие подстановки будут неверно истолкованы, печатая много мусора и обычно нажимая на a ///, что является бесконечным циклом.
    • Каждый добавляет правильную команду для печати своего собственного символа и восстанавливает оригинал ␤/ в конце общей подстроки.
  • Теперь подпрограмма символа достигла своей копии общей подстроки, которая готова напечатать свою строку.

После запуска последней символьной подпрограммы остается то, что осталось от программы /␤\//xy. Так как это неполная замена с отсутствующим финалом /, программа пропускает ее и обычно останавливается.


1
Правильный язык для работы! Lol
DJMcMayhem

6

Желе , 14 байт

=”\ðḤ’+\_⁸⁶ẋżY

Полная программа печати результата.

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

Как?

=”\ðḤ’+\_⁸⁶ẋżY - Link: list of characters, s    e.g. "\\\//\\/"
 ”\            - literal '\'                         '\'
=              - equal? (call this e)                [1, 1, 1, 0, 0, 1, 1, 0]
   ð           - new dyadic chain f(e, s)
    Ḥ          - double                              [2, 2, 2, 0, 0, 2, 2, 0]
     ’         - decrement                           [1, 1, 1,-1,-1, 1, 1,-1]
      +\       - cumulative reduce with addition     [1, 2, 3, 2, 1, 2, 3, 2]
         ⁸     - chain's left argument, e            [1, 1, 1, 0, 0, 1, 1, 0]
        _      - subtract (# of leading spaces)      [0, 1, 2, 2, 1, 1, 2, 2]
          ⁶    - literal ' '                         ''
           ẋ   - repeat                              [""," ","  "," "," "," ","  ","  "]
            ż  - zip with s                          [["",'\'],[" ",'\'],["  ",'\'],["  ",'/'],[" ",'/'],[" ",'\'],["  ",'\'],["  ",'/']]
             Y - join with newlines                  ["",'\','\n'," ",'\','\n',"  ",'\','\n',"  ",'/','\n'," ",'/','\n'," ",'\','\n',"  ",'\','\n',"  ",'/']
               - implicit print - this smashes the lists (shown as "..." above) and the characters (shown as '...' above) together.




5

MATL , 23 19 18 байт

1 байт благодаря @Sanchises

fGqoEq1yd~h*YsGZ?c

Ввод - это строка, заключенная в одинарные кавычки.

Попробуйте онлайн! Или проверьте контрольные примеры: 1 , 2 , 3 .

объяснение

Рассмотрим ввод '\\\//\/\\'в качестве примера.

f      % Implicit input. Array of indices of nonzeros. Since all chars in the input
       % have nonzero code point, this gives [1 2 ... n] where n is input length
       % STACK: [1 2 3 4 5 6 7 8 9]
G      % Push input again
       % STACK: [1 2 3 4 5 6 7 8 9], '\\\//\/\\'
qo     % Subtract 1 from (the code-point) of each char and then compute modulo 2.
       % This transforms '\' into 1 and '/' into 0
       % STACK: [1 2 3 4 5 6 7 8 9], [1 1 1 0 0 1 0 1 1]
Eq     % Double, subtract 1. This transforms 0 into -1
       % STACK: [1 2 3 4 5 6 7 8 9], [1 1 1 -1 -1 1 -1 1 1]
1y     % Push 1 and duplicate from below
       % STACK: [1 2 3 4 5 6 7 8 9], [1 1 1 -1 -1 1 -1 1 1], 1, [1 1 1 -1 -1 1 -1 1 1]
d~     % Consecutive differences, logical negation: gives 1 if consecutive entries
       % are equal, 0 otherwise
       % STACK: [1 2 3 4 5 6 7 8 9], [1 1 1 -1 -1 1 -1 1 1], 1, [1 1 0 1 0 0 0 1]
h      % Horizontally concatenate
       % STACK: [1 2 3 4 5 6 7 8 9], [1 1 1 -1 -1 1 -1 1 1], [1 1 1 0 1 0 0 0 1]
*      % Element-wise multiplication
       % STACK: [1 2 3 4 5 6 7 8 9], [1 1 1 0 -1 0 0 0 1]
Ys     % Cumulative sum
       % STACK: [1 2 3 4 5 6 7 8 9], [1 2 3 3 2 2 2 2 3]
G      % Push input again
       % STACK: [1 2 3 4 5 6 7 8 9], [1 2 3 3 2 2 2 2 3], '\\\//\/\\'
Z?     % Build sparse matrix with those row indices, column indices, and values
       % STACK: [92  0  0;
                  0 92  0;
                  0  0 92;
                  0  0 47;
                  0 47  0;
                  0 92  0;
                  0 47  0;
                  0 92  0;
                  0  0 92]
c      % Convert to char. Char 0 is shown as space. Implicitly display
       % STACK: ['\  ';
                 ' \ ';
                 '  \';
                 '  /';
                 ' / ';
                 ' \ ';
                 ' / ';
                 ' \ ';
                 '  \']

Один байт немного по другому алгоритму, чтобы получить ваши индексы: попробуйте онлайн!
Sanchises

@Sanchises Спасибо за ваши очень соответствующие правки!
Луис Мендо

5

C # (.NET Core) , 74 88 82 78 77 76 + 18 байт

-1 байт благодаря Кевину Круйссену

s=>s.Select((x,i)=>$"{x}".PadLeft((x-s[0])/45-~s.Take(i).Sum(y=>y<92?-1:1)))

Выводит коллекцию строк, по одной на каждую строку. Количество байтов также включает в себя:

using System.Linq;

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

Пояснение к 77-байтному ответу:

s =>                              // Take input, a string
    s.Select((x, i) =>            // Replace every character with:
        $"{x}"                    //     The character as string
        .PadLeft(                 //     Pad with this many spaces:
            s.Take(i)             //         Take characters, in the input string, preceding current one
            .Sum(y =>             //         Sum them by:
                y < 92 ? -1 : 1   //             If it's a \ add 1, if / subtract 1
            )
            + (x - s[0]) / 45 + 1 //         If first slash is a / add one more space, if current slash is a \ add one more space (I got this through power of MATHS!)
                                  //         How I arrived at this function:
                                  //         + x / 48        If current slash is a \ add one more space
                                  //         - s[0] / 48 + 1 If the first slash is a / add one more space
        )
    )

3
Не работает /\\/\\/.
Нил

@ Нил спасибо, что указал на это! Исправлена.
Гжегож Пулавский

1
Я знаю, что это было давно, но вы можете сохранить байт, перейдя s.Take(i).Sum(y=>y<92?-1:1)+(x-s[0])/45+1на(x-s[0])/45-~s.Take(i).Sum(y=>y<92?-1:1)
Кевин Круйссен,

Хороший один @KevinCruijssen!
Гжегож Пулавски

4

05AB1E , 14 байтов

ÇÈx<ηOs-W-ISú»

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

объяснение

Ç                # convert input string to a list of ascii codes
 È               # check each for evenness
  x              # push a doubled copy
   <             # decrement
    η            # compute prefixes
     O           # sum each prefix
      s          # swap the unaltered copy of evenness to the top
       -         # subtract from the prefix-sum list
        W-       # subtract the minimum value
          IS     # push input split to a list of chars
            ú    # pad each with the number of spaces computed
             »   # join on newline

1
Не работает /\\/\\/.
Нил

Ç¥.¥0<.SηOv¹Nèy<ú, рыдая в двоичном
Волшебная Урна Осьминога

3

R , 122 121 байт

-1 байт благодаря Джузеппе

x=el(strsplit(scan(,""),""));n=seq(x);y=x>"/";for(i in n)cat(rep(" ",diffinv(y[n[-1]-1]+y[n[-1]]-1)[i]),x[i],"\n",sep="")

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

С дополнительными пробелами:

x = el(strsplit(scan(,""),""))
n = seq(x)
y = x>"/"
for(i in n) {
  cat(rep(" ", diffinv(y[n[-1]-1]+y[n[-1]]-1)[i]), x[i], "\n", sep="")
}

Объяснение: Этот ответ основан на наблюдении, что число начальных пробелов меняет каждую строку на -1, плюс количество / в предыдущей и текущей строках.

Если у нас N косых черт, переменная yявляется вектором длины N, где 1 для каждой позиции с \0, в противном случае. Поэтому, чтобы получить изменение количества ведущих пробелов в строке, мы рассчитываем y[1:(N-1)] + y[2:N] - 1. Функция diffinvпреобразует эти различия в последовательность, начиная с 0. Остальное - это просто сборка каждой строки в виде необходимого количества конечных пробелов, за которым следует соответствующая косая черта и символ новой строки.


1
да. Я выбрал совершенно другой подход для 119 байтов, что заставляет меня задуматься, можем ли мы объединить наши подходы. (хорошее использование diffinv;) Также вы можете установить y=x>")"на -1 байт
Giuseppe

@ Giuseppe Вы должны опубликовать это как отдельный ответ, это достаточно другой подход. Ваш хороший способ избежать необходимости strsplit, который всегда является убийцей. Вы также можете использовать знаменитые diffinv!
user2390246

1
Также я думаю, что если вы вставите library(methods)заголовок (который должен быть в порядке без штрафа, так как этот пакет является частью базы R), вы можете использовать el. Кроме того, diffinvоказалось так же долго, как cumsum! :)
Джузеппе

Да, я только что понял это, это не совсем работает в этом контексте
user2390246

хорошо, я нашел обходной путь , но да, это *Sвсе испортило.
Джузеппе

3

Brain-Flak , 175 байт (174 символа + 1 флаг)

Беги с -cфлагом.

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

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

объяснение

{ for each char in the input...
  (({})<(())>){({}[()]<([{}])>)}{} push 1/-1 for backslash/slash
  ((
   {}<>{}<> add the 1/-1 to a running total
   <
    ({}<>) move slash/backslash to other stack
    ((()()()()()){}) newline
   >
  )<{({}[()]<((((()()()()){}){}){})>)}>{}) spaces
  <>
}<>{} end for
reverse data order, removing one space before backslash
{({}<>)(({})(())){({}[()]<([{}]())>)}{}{<>{}<>(<{}>)}{}<>}<>

Я всегда высказываю мысли. : D
DJMcMayhem

3

Руби , 80 76 байт

-4 байта благодаря ручной работе

puts"\\";$*[i=0].chars.each_cons 2{|b,c|puts" "*(b==c ?b==?/?i-=1:i+=1:i)+c}

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

Объяснение:

puts "\\"           # Output the first backslash
$*[i=0].            # Get the first argument and set i to 0
chars.              # Go through every individual character,
each_cons 2 { |b,c| # In pairs to compare easily
                    #
    puts " " *      # Decide how many padding spaces to use based on the value
                    # of i. The expression inside the parenthesis will return
                    # i but before that, it will increment/decrement i based
                    # on what the previous character was.
                        #
    ( b==c ?            # if b == c
        b==?/ ?         #   if b == "/" (Going to the left)
            i-=1        #       return decremented i
            :           #   else        (Going to the right)
            i+=1        #       return incremented i
        :               # else
        i) +            #   return i
                    #
                c   # Finally, write the second of the characters that we're
}                   # iterating through.

1
Какая версия Ruby? 2.3.3 У меня требует скобки параметра вокруг , когда блок кода следующим образом : .each_cons(2){…}. В изменении вы можете сохранить, заменив .each_char.chars.
manatwork

@manatwork Моя рубиновая версия 2.4.1. Спасибо за предложение о символах, я не знал об этом.
Pazzaz

Вы можете сохранить еще два байта, перейдя i+=к началу вложенного троичного выражения и заканчивая его символом -1:1:0.
benj2240

3

Java 8, 121 118 110 109 102 байта

a->{String r="";int s=0,p=0,i;for(char c:a){for(i=s+=p+(p=c-63)>>5;i-->0;r+=" ");r+=c+"\n";}return r;}

-7 байт благодаря битовой магии @Nevay . :)

Объяснение:

Попробуй это здесь.

a->{                    // Method with char-array parameter and String return-type
  String r="";          //  Return-String
  int s=0,              //  Amount of spaces
      p=0,              //  Previous characters (starting at 0)
      i;                //  Index-integer
  for(char c:a){        //  Loop over the input
    for(i=s+=p+(p=c-63)>>5;
                        //   If the current does not equals the previous character
                        //    Leave `s` the same
                        //   Else-if it's a '\':
                        //    Increase `s` by 1
                        //   Else (it's a '/'):
                        //    Decrease `s` by 1
                        //   And set the previous character to the current in the process
        i-->0;r+=" ");  //   Append `r` with `s` amount of spaces               
    r+=c+"\n";          //   Append the character + a new-line to the result
  }                     //  End of loop
  return r;             //  Return result-String
}                       // End of method

1
102 байта:a->{String r="";int s=0,p=0,i;for(char c:a){for(i=s+=p+(p=c-63)>>5;i-->0;r+=" ");r+=c+"\n";}return r;}
Невай

@Nevay Спасибо. Я знал, что это может быть сокращено с помощью некоторых побитовых операций, но не мог понять это. Главным образом потому, что я забыл о том, чтобы попробовать эффекты >>/ >>>/ <<... Я только что проверил некоторые вещи с &/ |/ ~/ ^..>.>
Кевин Круйссен

3

C (GCC), 137 134 97 байт

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

• 3 байта благодаря ATaco

• 37 байтов благодаря Digital Trauma & ThePirateBay

i,d;f(char*s){char c=s[i],n=s[++i];if(c){printf("%*c%c\n",d+1,c);(c-n)?d:(c==47)?--d:++d;f(s);}}

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

использование

f("\\\\\\//\\/\\\\",0,0);

Ungolfed

Это старый ответ, просмотрите онлайн-ссылку "Попробуй!"

f(char *s, i, d) {
    char c=s[i], n=s[++i];
    if(!c) return;
    for(int j=0; j<d; j++) printf(" ");
    printf("%c\n",c);
    f(s, i, (c!=n)?d:(c=='/')?d-1:d+1);
}

Выход

введите описание изображения здесь


Вы можете заменить c=='\0'с !cтем же эффектом.
ATaco

Огромное спасибо, только что обновили решение!
Спит

Можете ли вы использовать printf("%*s%c", n, "", c)для печати символа c n пробелами?
Цифровая травма

Я уверен , что вы можете сэкономить несколько байт, заменяя (c!=n)с c-nи переставляя тройные выражения. То же самое с (c=='/'). Также вы можете заменить '/'на буквальный номер 47. Я думаю, что это всего 7 байтов.



3

Сетчатка , 47 байт

^|\\
 $&
+m`^( *)( /|\\)(/| \\)
$1$2¶$1$3
m`^ 

Попробуйте онлайн! Ссылка включает в себя тестовые случаи. Объяснение:

^|\\
 $&

Добавьте пробел в начале каждой строки и перед каждой \.

+m`^( *)( /|\\)(/| \\)
$1$2¶$1$3

Рассмотрим первые два символа строки. Если первым является a, /то отступ должен быть уменьшен; это достигается включением предшествующего пробела в захват (который всегда существует, потому что первый этап добавил его); если второе значение a, \\его необходимо увеличить; это достигается путем включения пространства, добавляемого на первом этапе в захвате. После ввода правильного отступа для второго символа этап повторяется для второго и третьего символов и т. Д.

m`^ 

Удалить лишний отступ.

Я написал 94-байтовую версию, которая (как и мой ответ на Charcoal) допускает любую комбинацию слешей: попробуйте онлайн! Объяснение:

.$
¶$.`$* $&

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

/
 /

Приставьте пробелы ко всем прямым слешам, чтобы их можно было захватить.

+`^(.*)( /|\\)¶( *)( \\|/)
$1¶$3$2¶$3$4

Повторно возьмите последнюю косую черту ввода и выровняйте ее по отдельной строке с косой чертой в строке ниже.

+ms`^(?<!^[\\/].*) (?!.*^[\\/])

Удалите все оставшиеся отступы.

G`.

Удалить теперь пустой ввод.


2

Луа , 96 байт

c=0 for s in(...):gmatch(".")do c=c+(p==s and(s=="/"and-1or 1)or 0)p=s print((" "):rep(c)..s)end

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

Самый короткий, который я мог придумать в Lua. Ввод берется из командной строки.

Это использует несколько трюков:

  1. (...):gmatch(
    Это должна быть самая короткая форма получения одной строки в программу Lua из командной строки. ...Выражение в Lua захватывает все лишние параметры в функции, которые не указаны в объявлении функции и используется для списков параметров. Поскольку основная часть Lua-программы вызывается как функция с аргументами командной строки в качестве параметров, аргументы командной строки заканчиваются на ....
    Скобки вокруг него превращают потенциально многозначное ...выражение в однозначное выражение. Рассмотрим этот (несколько удивительный) пример:
    function multipleReturnValues()
        return "abc", "def"
    end
    print(  multipleReturnValues()  ) --This prints: abc    def
    print( (multipleReturnValues()) ) --This prints: abc
  2. Синтаксическому анализатору Lua не нужны никакие разделители строк или даже пробелы между операторами, если токены двух операторов могут быть четко разделены и существует только одна интерпретация текста, который является допустимым кодом Lua.
  3. Злоупотребление and/ orдля логики «если x, тогда value1 иначе value2». Оператор
    Lua andвозвращает свой первый аргумент, если он ложный; в противном случае он возвращает второй аргумент. orОператор возвращает свой первый аргумент , если он truthy; в противном случае второй аргумент.
  4. pне требует никакой инициализации.
    p==sвсегда должен быть ложным при первом запуске цикла, независимо от ввода. Если вы не установите pкакое-либо значение перед входом в цикл (выйдете из него nil), это произойдет и сохранит байты.

Кто-нибудь может сыграть в гольф (в Lua)?


Мне удалось сохранить два байта, используя gsub вместо gmatch. c=0(...):gsub(".",function(s)c=c+(p==s and(s=="/"and-1or 1)or 0)p=s print((" "):rep(c)..s)end)
QuertyKeyboard

Ну, это не так важно. Вы могли бы легко сохранить два байта, изменив gmatch(".")их так, gmatch"."как вы делали в следующем ответе.
QuertyKeyboard

@QuertyKeyboard Это странно ... Я действительно использовал gsub точно так же, как это в первой версии этого кода, но затем переключился на gmatch, потому что он почему-то оказался короче. Я не знаю, что я сделал по-другому, к сожалению, файл перезаписан.
Джонатан С.


2

R 119 байт

function(s)for(i in 1:nchar(s))cat(rep(" ",cumsum(c(0,!diff(S<-(utf8ToInt(s)>48)*2-1))*S)[i]),substr(s,i,i),"
",sep="")

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

Это несколько отличается от ответа пользователя 2390246 . Каждый из них перебирает строку, распечатывая определенное количество пробелов и затем соответствующий /\символ.

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


Просто обдумывал это еще, я думаю , что есть ошибка в вашем алгоритме: TIO
user2390246

@ user2390246 Я это исправил! У меня были некоторые неуместные скобки, но теперь diffinvопределенно не будет работать здесь.
Джузеппе

как насчет tio.run/##HYy7DsIwEAR/…
JayCe

2

C # (.NET Core) , 60/65 байт

Я пробовал более короткую версию C #

s=>{int i=0;return s.Select(x=>"".PadLeft(x<92?--i:i++)+x);}

как там было сказано: «Это также означает, что каждый ввод будет начинаться с обратной косой черты». Или чуть дольше, которые решают запуск "/"

s=>{int i=s[0]&1;return s.Select(x=>"".PadLeft(x<92?--i:i++)+x);}

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


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

2

Луа , 88 84 байта

Улучшенная версия (-4 байта благодаря QuertyKeyboard)

s=""g=s.gsub g(...,".",function(c)s=g(g(g(s,"\\"," "),"/?$",c)," /","/")print(s)end)

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

Оригинальная версия (88 байт)

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

s=""for c in(...):gmatch"."do s=s:gsub("\\"," "):gsub("/?$",c):gsub(" /","/")print(s)end

Ungolfed:

s = ""
for c in string.gmatch((...), ".") do --for each character in the input
  --s contains the output from the previous iteration
  s = s:gsub("\\", " ") --Replace backslash with space -> indent by 1
  s = s:gsub("/?$", c) --Remove any / at the end of the string and append c to the string
  s = s:gsub(" /", "/") --Remove a single space in front of any / -> un-indent by 1
  print(s)
end

В коде есть одна интересная вещь: он (...):gmatch"."
использует некоторые причуды в парсере Lua. Когда Lua встречает кусок кода в форме func "string", он конвертирует его в func("string"). Это делается для того, чтобы можно print "string"было напечатать постоянную строку, и она работает только с одним строковым литералом после функции. Все остальное выдаст синтаксическую ошибку. Однако этот синтаксический сахар также работает с вызовами функций в середине выражения, и, что более удивительно, он прекрасно работает вместе с :синтаксическим вызовом метода вызова метода. В итоге Lua интерпретирует код следующим образом:

(...):gmatch"."
-> (...):gmatch(".")
-> string.gmatch((...), ".")

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


1
Я был разочарован, обнаружив, что мой трюк с gsub, который я прокомментировал в другом ответе, не совсем сработал для этого. На самом деле это закончилось добавлением одного байта. Однако я бы так легко не сдался. Сначала я попытался сохранить gsub как переменную, чтобы сократить код. К моему удивлению, мой код был точно таким же количеством байтов - 88. Однако я понял, что с сохранением gsub мой трюк с gsub теперь может работать! Вот мой код, который сбрил 4 байта:s=""g=s.gsub g(...,".",function(c)s=g(g(g(s,"\\"," "),"/?$",c)," /","/")print(s)end)
QuertyKeyboard

@QuertyKeyboard Да, я также пытался сохранить gsub в переменной перед циклом и затем использовать его вместо записи gsub три раза, и я был так же удивлен, увидев, что это не имеет абсолютно никакого значения. Комбинировать трюки «gsub вместо цикла» и «store gsub» действительно здорово, не подумайте об этом! Спасибо! :)
Джонатан С.

1

Pyth - 33 байта

Первая попытка, будет гольф.

jsMC,*L;+ZsM._*VqVtzztMxL"/ \\"zz

Попробуйте это онлайн здесь .





пингуемые @maltysen
Стэн Strum

@StanStrum на данный момент, вы можете просто опубликовать его как свой собственный ответ
Maltysen

1

Perl, 40 + 2 байта

/\//&&$.--,say($"x$.,$_),/\\/&&$.++for@F

Вам нужен -Fфлаг.


1

Perl, 34 38 + 1 байт

обрабатывать два случая

s,(/)|.,$"x($1?$c&&--$c:$c++).$&.$/,ge

работать с -pопцией

s,(/)|.,$"x($1?--$c:$c++).$&.$/,ge

РЕДАКТИРОВАТЬ: следующий комментарий не работает, когда первый символ /

s,(/)|.,$"x($1?$c--:++$c).$&.$/,ge

однако вывод будет смещен на один символ справа, если первый символ \


1
Не работает /\\/\\/.
Нил

С обновленным вопросом ваше оригинальное 34решение теперь совершенно верно
Тон Хоспел

1

VBA (Excel), 181 байт

Sub q()
a = Cells(1, 1)
For x = 1 To Len(a)
c = Mid(a, x, 1)
If c = "\" Then: Debug.Print b & c: b = b + " "
If c = "/" Then: b = Left(b, Len(b) - 1): Debug.Print b & c
Next
End Sub

1
Вы можете значительно уменьшить это, не изменяя свой алгоритм, используя преимущества автоформатирования Excel VBA и используя [...]нотацию: я уменьшил ее до 128 байт Sub q For x=1To[Len(A1)] c=Mid([A1],x,1) If c="\"Then Debug.?b;c:b=b+" " If c="/"Then b=Left(b,Len(b)-1):Debug.?b;c Next End Sub
Тейлор Скотт,

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



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