Намалюй мої недоліки


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. Пояснення:

 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. Це має дві переваги:
    • На відміну від /і \, %s і |s не потребують втечі, щоб їх скопіювати.
    • Замінники рядків не містять підрядки /\, яка в іншому випадку була б керована попередніми маніпуляціями.
  • Після цього заміщення /|/\\/(раніше /|/AB\\/) тепер розшифровує |s, після чого наступне /%/|//стало /%/\//та розшифровує %s.

Структура програми на заключному етапі

На цьому етапі базова програма виконала всі її підстановки, і все, що залишилося, - це програмне кодування вхідного рядка.

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

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

    (трейлінг нового рядка), де *є або fдля оригіналу /, або bдля оригіналу \.

  • Також /␤\//xyв кінці програми є неповна команда підстановки , яка не матиме жодного ефекту, окрім забезпечення необхідних /для підстановок попередньої підпрограми.

Спільний підряд

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

  • Ці підрядки використовуються як спільний глобальний стан. Усі решта замін у програмі будуть маніпулювати ними однаково та паралельно, так що наприкінці підпрограми кожного вхідного символу /буде запущена його копія цього спільного підрядка (за винятком остаточного , який закріплює підстановки) для друку рядка для цього характер.
  • Початкова версія підрядка являє собою друк рядка, що містить просто /, що є правильним уявним "попереднім рядком", щоб викликати друк першого символу на початку його рядка.
  • Загалом, під час етапів друку спільна підрядка складається з ряду пробілів, \\або \/, нового рядка та наступного /.

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

Деякі з наведених нижче підстановок містять додаткові \елементи всередині, щоб запобігти їх узгодженню та керуванню одна від одної (включаючи інші копії в інших підпрограмах). Досягнення цього також є причиною того, що потрібно і тим, xі yіншим.

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

Після запуску останньої символьної підпрограми, що залишається від програми /␤\//xy. Оскільки це неповна заміна з відсутнім фіналом /, програма пропускає її і нормально зупиняється.


1
Правильна мова для роботи! Лол
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 Дякуємо за ваші дуже правильні зміни!
Луїс Мендо

5

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

-1 байт завдяки Kevin Cruijssen

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
Не працює для /\\/\\/.
Ніл

@Neil дякую, що вказали на це! Виправлено.
Grzegorz Puławski

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!
Grzegorz Puławski

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 Вам слід опублікувати, що як окрему відповідь, це досить інший підхід. Ваш - це приємний спосіб уникнути цього strsplit, що завжди є вбивцею. Ви також можете скористатися відомим diffinv!
користувач2390246

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 Моя версія рубіну - 2.4.1. Дякую за пропозицію щодо знаків, я про це не знав.
Пацаз

Можна зберегти ще два байти, перемістивши 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 байт завдяки цифровій травмі та 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);

Безумовно

Це для старої відповіді, перегляньте пробне онлайн-посилання для оновленого!

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тим же ефектом.
Атако

Дивовижне дякую щойно оновлене рішення!
Asleepace

Чи можете ви скористатися printf("%*s%c", n, "", c)для друку знаку з n провідними пробілами?
Цифрова травма

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



3

Сітківка , 47 байт

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

Спробуйте в Інтернеті! Посилання включає тестові випадки. Пояснення:

^|\\
 $&

Додайте пробіл на початку кожного рядка та перед кожним \.

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

Розглянемо перші два символи рядка. Якщо першим є /а, відступ потрібно зменшити; це досягається включенням попереднього простору у захоплення (який завжди існує тому, що перший етап додав його); якщо друге - це, \\то його потрібно збільшити; це досягається включенням простору, який додав перший етап у захопленні. Надавши другому символу правильний відступ, етап повторюється для другого та третього символів тощо.

m`^ 

Видаліть зайвий відступ.

Я написав 94-байтну версію, яка (як і моя відповідь на вугілля) дозволяє будь-яку комбінацію косої риси: Спробуйте в Інтернеті! Пояснення:

.$
¶$.`$* $&

Отримайте прокатку кульки, взявши останню косу рису і відступіть її в тому ж положенні на своїй лінії.

/
 /

Префіксні пробіли до всіх прямих косої риски, щоб їх можна було захопити.

+`^(.*)( /|\\)¶( *)( \\|/)
$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

Спробуйте в Інтернеті!

Найкоротший, який я міг придумати в Луа. Введення береться з командного рядка.

Для цього використовуються кілька хитрощів:

  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для логіки "if x тоді value1 else value2". Оператор
    Lua andповертає свій перший аргумент, якщо він хибний; в іншому випадку він повертає свій другий аргумент. orОператор повертає свій перший аргумент , якщо він truthy; інакше другий аргумент.
  4. pне потребує ініціалізації.
    p==sзавжди має бути помилковим у першому циклі циклу, незалежно від введення. Якщо не встановити pжодного значення перед входом у цикл (залишити його nil), це станеться і збереженням байтів.

Хто-небудь може це гольф (в Луа)?


Мені вдалося зберегти два байти за допомогою 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точно не вийде.
Джузеппе


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

Безголівки:

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 може працювати! Ось мій код, який s=""g=s.gsub g(...,".",function(c)s=g(g(g(s,"\\"," "),"/?$",c)," /","/")print(s)end)
збрив

@QuertyKeyboard Так, я також намагався зберігати gsub у змінній перед циклом, а потім використовувати її замість того, щоб писати gsub три рази, і я був так само здивований, коли побачив, що це абсолютно не має ніякої різниці. Поєднувати трюки "gsub замість циклу" та "зберігати gsub" дійсно акуратно, про це не думав! Дякую! :)
Джонатан С.

1

Pyth - 33 байти

Перша спроба, буде гольф.

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

Спробуйте його онлайн тут .





pinged @maltysen
Stan 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

EDIT: наступний коментар не працює, коли є перший символ /

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
Тейлор Скотт

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



Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.