Desenhar minhas barras invertidas

60

Como programador, você provavelmente já ouviu falar de barras e barras invertidas. Mas você já ouviu falar de desvantagens? É quando você pega um monte de barras, conecta suas extremidades e as desenha descendo.

Para o desafio de hoje, você deve escrever um programa ou função que use uma string que consiste puramente de barras e produza todas as barras desenhadas para baixo em uma linha que os conecta. Isso ficará muito mais claro se você vir um exemplo. Dada a string \\\//\/\\, você deve gerar:

\
 \
  \
  /
 /
 \
 /
 \
  \

Aqui estão alguns esclarecimentos:

  • Deve haver uma barra por linha.

  • A primeira linha terá 0 espaços à esquerda.

  • Para cada par de barras:

    • Se forem diferentes, serão desenhados na mesma coluna. Por exemplo, \/dará:

      \
      /
      
    • Se eles tiverem o mesmo caractere, o inferior estará na direção apontada , que está se movendo para a direita para uma barra invertida e para a esquerda para uma barra invertida. Então \\//vai dar

      \
       \
       /
      /
      
  • Cada linha pode ter espaços em branco extras, contanto que isso não altere a aparência visual da saída. Até uma nova linha à direita e à frente também é aceitável. Espaços extras não são permitidos !

Para simplificar, você pode assumir que a string nunca conterá muitas barras. Em outras palavras, nenhum prefixo da entrada conterá mais barras do que barras invertidas; portanto, uma entrada como \\////ou //nunca será fornecida. Isso também significa que cada entrada começará com uma barra invertida.

Se sua entrada for tomada como uma string literal, você poderá escapar das barras invertidas, se isso for necessário. Você também nunca precisará manipular uma entrada que esteja vazia ou contenha caracteres que não sejam uma barra.

Você pode imprimir em qualquer formato razoável .

Como de costume, esse é um desafio do , portanto, tente tornar a solução mais curta possível, mesmo se você escolher um idioma em que isso seja bastante difícil. Pontos de bônus por explicar qualquer técnica interessante usada para remover bytes!

Exemplos

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

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

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

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


#Input
\/\/\/

#Output
\
/
\
/
\
/
DJMcMayhem
fonte
9
As barras invertidas para fazer uma quantidade irritante de escapar lol ...
totallyhuman

Respostas:

20

GNU Sed, 20

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

Observe que ^Le ^Hsão caracteres literais de avanço de formulário e backspace (0x12 e 0x8).

Essa resposta funciona movendo o cursor usando caracteres de retrocesso e avanço de formulário. As barras / barras invertidas não são preenchidas à esquerda com espaços - Não tenho certeza disso desqualifica esta resposta. Isso não funciona no TIO, mas parece bom em terminais comuns como xterme gnome-terminal.

Recrie esse script sed da seguinte maneira:

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

Execute-o da seguinte maneira:

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

$ 

Explicação:

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

Carvão , 13 12 11 bytes

FS¿⁼ι/↓¶/↘ι

Experimente online! Link é a versão detalhada do código. Suporta //s extras . Explicação:

 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
Neil
fonte
Eu acho que ↓¶= "Mover para a esquerda" na descrição não está certo.
Jonathan Allan
@JonathanAllan Isso mesmo (nova linha impresso para baixo = mover para a esquerda), embora provavelmente seria mais claro para dizer "imprimir \n/down"
ASCII única
Eu não disse print \n/ downporque achava mais útil descrever o efeito do código do que sua tradução literal.
Neil
11
(Língua na bochecha: descrevendo o efeito = MyCode - Do the spec). Entendo agora, embora o efeito seja mover para a esquerda; pode valer a pena dizer "Mover para a esquerda (imprimindo uma nova linha com uma direção de impressão para baixo)".
Jonathan Allan
Mais conciso e auto-explicativo de todos!
J4hangir
14

Python 2 , 55 54 51 57 53 bytes

-3 bytes (e uma correção de bug) graças a Felipe Nardi Batista

i=0
for c in input():i-=c<'<'*i;print' '*i+c;i+=c>'<'

Experimente online!

Cajado
fonte
56 bytes
Mr. Xcoder
10

/// , 119 bytes

/// não possui comandos de entrada, portanto, a entrada deve ser incorporada no programa. Para este, a sequência de entrada é simplesmente anexada, sem necessidade de escape.

/=/\/\///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

Como funciona

  • A seguir, uma entrada de \\/\//será anexada ao programa para demonstração.
  • é usado para representar novas linhas no código embutido.

Abreviações

O início /=/\/\///M/␤|%%=N/%|||=C/BA=do programa contém substituições de abreviações de golfe.

  • =expande para //, Mpara ␤|%%, Npara %|||e Cpara BA.
  • Depois disso, o programa atual se torna

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

Recodificação de entrada

O próximo estágio transforma a sequência de entrada anexada em um formato mais utilizável. Como ele consiste inteiramente nos dois caracteres de comando de ///, isso toma alguns cuidados para evitar confundir o programa base.

  • A primeira substituição substancial /\/\\/\/BA\\/, substitui a string /\por /BA\.
    • O programa base não contém /\no momento, portanto, essa substituição não o afeta.
    • No entanto, isso divide a sequência de entrada anexada em sequências de \s seguidas por sequências de /s, que, juntamente com o ABAno final do programa base, possibilitam a iteração através das seguintes substituições.
    • Incluindo o ABAprefixo antes dele, a sequência de entrada de exemplo agora se torna ABA\\/BA\//.
  • A próxima substituição /BA\\/BAbBA/, substitui BA\por BAbBA.
    • Como as substituições /// são repetidas até que não correspondam mais, isso itera através de todos os \s da sequência de entrada, que com o prefixo agora se tornaABAbBAbBA/BAbBA//
  • Da mesma forma, /B\A\//BAfBA/muda BA/para BAfBA, iterando através dos /s.
    • O escape \nessa substituição é necessário, pois, caso contrário, seria mutilado pela anterior.
    • A entrada foi transformada agora ABAbBAbBAfBABAbBAfBAfBA.
  • Em seguida, /AB//remove algumas partes supérfluas da codificação, transformando-as em AbBAbBAfBAbBAfBAfBA.
    • Isso também remove um ABda /|/AB\\/substituição posteriormente no programa, necessário para protegê-lo da /\manipulação acima .
    • Nesse ponto, todas \as strings de entrada originais se tornaram AbBe todas /se tornaram AfB. ( be ffique para trás e para frente.) Há um desvio Ano final.
  • As próximas duas substituições de substituir todos os As e Bs com fragmentos de programa para executar na fase final. Nas cadeias de substituição, %s e |s codificam o que se tornará /s e \s, respectivamente. Isso tem dois benefícios:
    • Ao contrário /e \, os %s e |s não precisa escapar a ser copiado.
    • As seqüências de substituição evitam conter a subcadeia /\, que de outra forma teria sido destruída pelas manipulações anteriores.
  • Depois disso, a substituição /|/\\/(anteriormente /|/AB\\/) agora decodifica os |s, após o que o seguinte /%/|//se tornou /%/\//e decodifica os %s.

Estrutura do programa na fase final

Nesse ponto, o programa base executou todas as suas substituições e tudo o que resta é a codificação do programa da sequência de entrada.

  • Cada caractere de entrada se tornou um subprograma

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

    (nova linha à direita), onde *representa fum original /ou bum original \.

  • Há também um comando de substituição incompleto /␤\//xyno final do programa, que não terá efeito, exceto para fornecer um necessário /para as substituições do subprograma anterior.

Subcadeia compartilhada

Antes do início da iteração final através dos subprogramas, há uma substring cruzando o limite após o subprograma de cada caractere do formulário \/␤/.

  • Essas substrings são usadas como um estado global compartilhado. Todas as substituições restantes no programa as manipularão de forma idêntica e paralela, de modo que, no final do subprograma de cada caractere de entrada, sua cópia dessa subcadeia compartilhada (exceto a final /, que ancora as substituições) seja executada para imprimir a linha correspondente. personagem.
  • A versão inicial da substring representa a impressão de uma linha contendo just /, que é a "linha anterior" imaginária correta para fazer com que o primeiro caractere de entrada seja impresso no início de sua linha.
  • Em geral, durante as etapas de impressão, a substring compartilhada consiste em vários espaços \\ou \/uma nova linha e uma sequência /.

Executando um Subprograma de Caracteres

Várias das seguintes substituições contêm \s extras para evitar que elas sejam correspondidas e mutiladas (incluindo outras cópias em outros subprogramas). Alcançar esta é também a razão pela qual ambos xe ysão necessários.

  • A primeira substituição em um subprograma de caracteres, /␤\//xyf\z/ou /␤\//xyb\z/, faz ␤/com que o final da subseqüência compartilhada se torne xyfzou xybz, imediatamente após o \/ou \\.
  • A substituição /\\\\x\y/ /substitui \\xypor um espaço, e a substituição /\\\/x\y//substitui \/xypor nada.
    • Eles se aplicam quando o caractere de entrada anterior impresso foi a \ou /, respectivamente.
    • A substring compartilhada agora contém o número apropriado de espaços para imprimir um \próximo, seguido por fzou bz.
  • A substituição / \fz/\\\/␤\//substitui ​ fzpor \/␤/e /b\z/\\\\␤\//substitui bzpor \\␤/.
    • Eles se aplicam quando o caractere de entrada atual é /ou \, respectivamente.
    • O primeiro ocupa um espaço extra para colocar /corretamente.
      • Se esse espaço estiver ausente (por exemplo, entrada que viole a condição de prefixo), as seguintes substituições serão mal interpretadas, imprimindo muito lixo e geralmente atingindo a ///, que é um loop infinito.
    • Cada um deles adiciona o comando correto para imprimir seu próprio caractere e restaura o original ␤/no final da substring compartilhada.
  • O subprograma de caracteres agora alcançou sua cópia da substring compartilhada, que está pronta para imprimir sua linha.

Após a execução do último subprograma de caracteres, o que resta do programa é /␤\//xy. Como esta é uma substituição incompleta com final ausente /, o programa a ignora e para normalmente.

Ørjan Johansen
fonte
11
O idioma certo para o trabalho! Lol
DJMcMayhem
6

Gelatina , 14 bytes

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

Um programa completo imprimindo o resultado.

Experimente online!

Quão?

=”\ðḤ’+\_⁸⁶ẋż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.
Jonathan Allan
fonte
6

Haskell , 49 bytes

scanl(\x c->drop(sum[1|'/'<-c:x])(' '<$x)++[c])[]

Experimente online!

dianne
fonte
5

JavaScript (ES8), 66 59 63 bytes

7 bytes salvos graças a Justin Mariner
+4 bytes para corrigir /\\/\\/(notado por Neil )

f=([a,...z],b=a<'0')=>a?a.padStart(b+=k=a>'/')+`
`+f(z,b-!k):''

Experimente online!


fonte
5

MATL , 23 19 18 bytes

1 byte de desconto graças a @Sanchises

fGqoEq1yd~h*YsGZ?c

Entrada é uma cadeia de caracteres entre aspas simples.

Experimente online! Ou verifique os casos de teste: 1 , 2 , 3 .

Explicação

Considere a entrada '\\\//\/\\'como um exemplo.

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: ['\  ';
                 ' \ ';
                 '  \';
                 '  /';
                 ' / ';
                 ' \ ';
                 ' / ';
                 ' \ ';
                 '  \']
Luis Mendo
fonte
Um byte de distância por um algoritmo um pouco diferente para obter seus índices: Experimente online!
Sanchises 15/09
Obrigado por suas edições muito apropriadas!
Luis Mendo
5

C # (.NET Core) , 74 88 82 78 77 76 + 18 bytes

-1 byte graças a Kevin Cruijssen

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

Produz uma coleção de strings, uma para cada linha. A contagem de bytes também inclui:

using System.Linq;

Experimente online!

Explicação para resposta de 77 bytes:

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
        )
    )
Grzegorz Puławski
fonte
3
Não funciona para /\\/\\/.
Neil
@ Neil obrigado por apontar isso! Fixo.
Grzegorz Puławski
11
Eu sei que já faz um tempo, mas você pode salvar um byte, alterando s.Take(i).Sum(y=>y<92?-1:1)+(x-s[0])/45+1para #(x-s[0])/45-~s.Take(i).Sum(y=>y<92?-1:1)
911 Kevin Cruijssen
Nice one @KevinCruijssen!
Grzegorz Puławski
4

05AB1E , 14 bytes

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

Experimente online!

Explicação

Ç                # 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
Emigna
fonte
11
Não funciona para /\\/\\/.
Neil
Ç¥.¥0<.SηOv¹Nèy<ú, soluçando em binário
Magic Octopus Urn
3

R , 122 121 bytes

-1 byte graças a Giuseppe

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="")

Experimente online!

Com espaço em branco extra:

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="")
}

Explicação: Esta resposta é baseada na observação de que o número de espaços à esquerda altera cada linha por -1, mais o número de /linhas anteriores e atuais.

Se tivermos barras N, a variável yé um vetor de comprimento N, com 1 para cada posição com \, 0 caso contrário. Portanto, para obter a alteração no número de espaços à esquerda por linha, calculamos y[1:(N-1)] + y[2:N] - 1. A função diffinvconverte essas diferenças em uma sequência, começando com 0. O restante é apenas uma questão de montar cada linha como o número necessário de espaços à direita, seguidos pela barra relevante e uma nova linha.

user2390246
fonte
11
Hã. Adotei uma abordagem bastante diferente para 119 bytes, o que me faz pensar se poderíamos combinar nossas abordagens. (bom uso de diffinv;) Também é possível definir y=x>")"-1 byte
Giuseppe
@ Giuseppe Você deve postar isso como uma resposta separada, é uma abordagem bastante diferente. A sua é uma ótima maneira de evitar ter que fazer strsplit, o que é sempre um assassino. Você também pode fazer uso dos famosos diffinv!
user2390246
11
Também acho que se você colocar library(methods)no cabeçalho (o que deve ser bom sem penalidade, já que esse pacote faz parte da base R), você pode usar el. Além disso, diffinvacabou por ser apenas enquanto cumsum! :)
Giuseppe
Sim, eu estava percebendo isso também, ele não funciona muito bem nesse contexto
user2390246
bem, eu vim com uma solução alternativa , mas sim, isso *Sestraga tudo.
Giuseppe
3

Brain-Flak , 175 bytes (174 caracteres + 1 sinalizador)

Corra com a -cbandeira.

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

Experimente online!

Explicação

{ 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
{({}<>)(({})(())){({}[()]<([{}]())>)}{}{<>{}<>(<{}>)}{}<>}<>
MegaTom
fonte
Eu sempre votei contra o cérebro. : D
DJMcMayhem
3

Ruby , 80 76 bytes

-4 bytes graças ao manatwork

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

Experimente online!

Explicação:

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.
Pazzaz
fonte
11
Qual versão do Ruby? A 2.3.3 Eu tenho exige parêntese em torno de parâmetro quando bloco de código a seguir: .each_cons(2){…}. Na alteração, você pode salvar substituindo .each_char.chars.
manatwork 14/09/17
@manatwork Minha versão do ruby ​​é 2.4.1. Obrigado pela sugestão sobre caracteres, eu não sabia disso.
Pazzaz 14/09/17
Você pode salvar outros dois bytes movendo i+=para o início da expressão ternária aninhada e finalizando-a com -1:1:0.
benj2240
3

Java 8, 121 118 110 109 102 bytes

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 bytes graças à mágica bit a bit do @Nevay . :)

Explicação:

Experimente aqui.

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
Kevin Cruijssen
fonte
11
102 bytes: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 14/09
Obrigado @Nevay. Eu sabia que poderia ser reduzido com algumas operações bit a bit, mas não conseguia descobrir. Principalmente porque eu esqueci de experimentar os efeitos de >>/ >>>/ <<... eu só tinha verificado algumas coisas com &/ |/ ~/ ^..>.>
Kevin Cruijssen
3

C (GCC), 137 134 97 bytes

Experimente online!

• 3 bytes graças ao ATaco

• 37 bytes graças ao Digital Trauma e 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);}}

Nada muito sofisticado, apenas uma função recursiva simples que pega uma string e imprime as barras, observe que a entrada precisa escapar primeiro das barras invertidas.

Uso

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

Ungolfed

Esta é a resposta antiga, consulte o link Experimente online para atualizar uma!

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);
}

Resultado

insira a descrição da imagem aqui

Adormecido
fonte
Você pode substituir c=='\0'por !cpara o mesmo efeito.
ATaco 14/09
Agradecimentos impressionantes acabaram de atualizar a solução!
Asleepace
Você pode usar printf("%*s%c", n, "", c)para imprimir o caractere c com n espaços à esquerda?
Digital Trauma
Eu tenho certeza que você pode salvar alguns bytes, substituindo (c!=n)com c-ne reorganizando expressões ternários. O mesmo com (c=='/'). Além disso, você pode substituir '/'pelo número literal 47. Eu acho que são 7 bytes no total.
11
78 bytes
somente ASCII
3

C, 60 bytes

i;f(char*s){for(i=1;*s;s++)printf("%*c\n",*s%2?--i:i++,*s);}

Experimente online!

orlp
fonte
-1 no link TIO: P
somente ASCII
TIO
somente ASCII
@ ASCII-only you welcome ()
Stan Strum
3

Retina , 47 bytes

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

Experimente online! O link inclui casos de teste. Explicação:

^|\\
 $&

Adicione um espaço no início de cada linha e antes de cada \.

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

Considere os dois primeiros caracteres da sequência. Se o primeiro é a /, o recuo precisa ser diminuído; isso é conseguido incluindo o espaço anterior na captura (que sempre existe porque o primeiro estágio foi adicionado); se o segundo for um \\, ele precisará ser incrementado; isso é alcançado incluindo o espaço que o primeiro estágio adicionou na captura. Tendo dado ao segundo caractere o travessão correto, o estágio é repetido para o segundo e terceiro caracteres etc.

m`^ 

Retire o recuo extra.

Eu escrevi uma versão de 94 bytes que (como minha resposta do carvão vegetal) permite qualquer combinação de barras: Experimente on-line! Explicação:

.$
¶$.`$* $&

Faça a bola rolar pegando a última barra e recuando-a para a mesma posição em sua própria linha.

/
 /

Prefixe espaços para todas as barras para que elas possam ser capturadas.

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

Pegue repetidamente a última barra da entrada e alinhe-a em sua própria linha com a barra na linha abaixo.

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

Exclua qualquer recuo restante.

G`.

Exclua a entrada agora vazia.

Neil
fonte
2

Lua , 96 bytes

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

Experimente online!

O mais curto que eu poderia encontrar em Lua. A entrada é retirada da linha de comando.

Isso usa alguns truques:

  1. (...):gmatch(
    Essa deve ser a forma mais curta de obter uma única string em um programa Lua a partir da linha de comando. A ...expressão em Lua captura qualquer parâmetro em excesso para uma função que não está especificada na declaração da função e é usada para varargs. Como o corpo principal de um programa Lua é chamado como uma função com os argumentos da linha de comando como seus parâmetros, os argumentos da linha de comando terminam em ....
    Os parênteses em torno dele transformam a ...expressão potencialmente com vários valores em uma expressão de valor único. Considere este exemplo (um tanto surpreendente):
    function multipleReturnValues()
        return "abc", "def"
    end
    print(  multipleReturnValues()  ) --This prints: abc    def
    print( (multipleReturnValues()) ) --This prints: abc
  2. O analisador Lua não precisa de nenhum terminador de linha, nem mesmo de espaço em branco entre instruções, desde que os tokens das duas instruções possam ser claramente separados e haja apenas uma interpretação do texto que seja um código Lua válido.
  3. Abusando and/ orpara a lógica "if x, value1 else value2".
    O andoperador de Lua retorna seu primeiro argumento se for falso; caso contrário, ele retornará seu segundo argumento. O oroperador retorna seu primeiro argumento, se for verdade; caso contrário, o segundo argumento.
  4. pnão precisa de nenhuma inicialização.
    p==ssempre precisa ser falso na primeira execução do loop, independentemente da entrada. Não definir pnenhum valor antes de inserir o loop (deixando-o nil) fará com que isso aconteça e salve bytes também.

Alguém pode jogar isso (em Lua)?

Jonathan S.
fonte
Consegui salvar dois bytes usando gsub em vez de usar 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
Bem, não que isso importe. Você poderia facilmente salvar dois bytes alterando gmatch(".")para gmatch"."como você fez na sua próxima resposta.
QuertyKeyboard
@QuertyKeyboard Isso é estranho ... Na verdade, usei o gsub exatamente assim na primeira versão deste código, mas depois mudei para o gmatch porque, de alguma forma, ficou mais curto. Não sei o que fiz de diferente, porém, o arquivo foi substituído infelizmente.
Jonathan S.
2

R , 119 bytes

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="")

Experimente online!

Isso difere um pouco da resposta do usuário2390246 . Cada um itera sobre a string, imprimindo um certo número de caracteres de espaço e, em seguida, o /\caractere apropriado .

No entanto, evitei dividir a sequência, optando por substituir os caracteres pelo valor de codificação UTF-8, o que me permite fazer aritmética nos números diretamente, o que me salvou em apenas alguns bytes.

Giuseppe
fonte
Acabei de ponderar isso um pouco mais, acho que há um erro no seu algoritmo: TIO
user2390246
@ user2390246 Eu consertei! Eu tinha alguns parênteses fora de lugar, mas agora diffinvdefinitivamente não vai funcionar aqui.
Giuseppe
que sobre tio.run/##HYy7DsIwEAR/...
Jayce
2

C # (.NET Core) , 60/65 bytes

Eu tentei a versão C # mais curta

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

como foi afirmado: "Isso também significa que todas as entradas começarão com uma barra invertida". Ou um pouco mais, o que resolve o início "/"

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

Experimente online!

Dan
fonte
Bem vindo ao site! :)
DJMcMayhem
2

Lua , 88 84 bytes

Versão aprimorada (-4 bytes graças ao QuertyKeyboard)

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

Experimente online!

Versão original (88 bytes)

Outra tentativa em Lua, desta vez com uma abordagem completamente diferente usando manipulação de string em vez de uma variável de contador.

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

Há uma coisa interessante no código: (...):gmatch"."
isso usa algumas peculiaridades no analisador Lua. Quando Lua encontra um pedaço de código no formulário func "string", ele o converte em func("string"). Isto é para que se possa escrever print "string"para imprimir uma string constante e ela só funcione com uma única string literal após a função. Qualquer outra coisa dará um erro de sintaxe. No entanto, esse açúcar sintático também funciona com chamadas de função no meio de uma expressão e, mais surpreendente, funciona muito bem junto com o :método chamado açúcar sintático. Então, no final, Lua interpretará o código assim:

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

Se alguém puder pensar em uma maneira de remover uma das três chamadas gsub, informe-me.

Jonathan S.
fonte
11
Fiquei decepcionado ao descobrir que o meu truque gsub que comentei na sua outra resposta não funcionou muito bem para esta. Na verdade, acabou adicionando um byte. No entanto, eu não desistiria tão facilmente. Primeiro, tentei armazenar o gsub como uma variável para encurtar o código. Para minha surpresa, meu código era exatamente a mesma quantidade de bytes - 88. No entanto, percebi que, com o gsub sendo salvo, meu truque com o gsub agora poderia funcionar! Aqui está o meu código que raspou 4 bytes:s=""g=s.gsub g(...,".",function(c)s=g(g(g(s,"\\"," "),"/?$",c)," /","/")print(s)end)
QuertyKeyboard 14/09
@QuertyKeyboard Sim, eu também tentei armazenar o gsub em uma variável antes do loop e depois usá-lo em vez de escrever o gsub três vezes, e fiquei surpreso ao vê-lo fazendo absolutamente nenhuma diferença. Combinar os truques "gsub em vez de loop" e "store gsub" é realmente legal, não pensei nisso! Obrigado! :)
Jonathan S.
1

Perl, 40 + 2 bytes

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

Você precisa da -Fbandeira.


fonte
1

Perl, 34 38 + 1 bytes

para lidar com os dois casos

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

para ser executado com -popção

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

EDIT: o seguinte comentário não funciona quando o primeiro caractere é /

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

no entanto, a saída será deslocada para um caractere à direita se o primeiro caractere for \

Nahuel Fouilleul
fonte
11
Não funciona para /\\/\\/.
Neil
Com a pergunta atualizada, sua 34solução original agora é perfeitamente válida
Ton Hospel
1

VBA (Excel), 181 bytes

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
remoel
fonte
11
Você pode golfe este para baixo significativamente sem alterar o algoritmo, tirando partido da natureza autoformatting de Excel VBA e pelo uso de [...]notação: Eu tenho-o para 128 Bytes 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
Taylor Scott
Obrigado por jogar meu script. Eu aprendi algo com isso e aplicarei no futuro. :) Não sabia que posso usar isso para buscar dados diretamente nas células. Obrigado novamente :)
remoel
1

Pitão , 24 21 bytes

Porto da resposta de Rod .

VQ=-Z<N\<+*ZdN=+Z>N\<

Experimente online!

Felipe Nardi Batista
fonte
Inválido, imprime [espaço inicial extra na primeira linha se a sequência começar \. BTW, onde está o seu código?
Sr. Xcoder 14/17
@ Mr.Xcoder fixo
Felipe Nardi Batista
1

Dyalog APL, 31 bytes

{↑⍵,¨⍨' '/¨⍨{⍵-⍨+1+2×⍵}⍵='\'}

Experimente aqui!

dzaima
fonte
{↑⍵↑¨⍨a-1-+\¯1*a←⍵='\'}
NGN