Топографические строки

23

Вот несколько примеров ввода, поэтому я могу объяснить, в чем проблема:

((1 2)(3 (4 5) moo)) (i (lik(cherries)e (woohoo)))

Думайте об этой строке текста как о топографической карте некоторых гор. Каждый набор скобок иллюстрирует одну единицу высоты.

Если мы «рассмотрим» это со стороны, чтобы мы увидели горы вертикально, мы увидим:

          4 5                cherries    woohoo  
  1 2  3       moo       lik          e
                      i

Получив одну из этих топографических карт, выведите карту, но в вертикальном масштабе, как показано выше. Разделите различные элементы на карте с количеством символов до следующего элемента. Например, на выходе есть 4 пробела между mooи i. Аналогично, во входе между mooи есть 4 символа i.

Код, который делает это с наименьшим количеством символов, выигрывает.

beary605
источник
Можно ли предположить, что высота всегда будет положительной? Например, ввод ((1 2))))))))))3должен быть недействительным, если запрещены отрицательные высоты.
Кристиан Лупаску,
@ w0lf: да, круглые скобки всегда будут совпадать.
beary605

Ответы:

10

J, 87 79 72 70 67 57 56 символов

'( ) 'charsub|.|:(+/\@('('&=-')'&=)(],~' '$~[)"0])1!:1[1

Берет ввод с клавиатуры. Пример:

   '( ) 'charsub|.|:(+/\@('('&=-')'&=)(],~' '$~[)"0])1!:1[1
((1 2)(3 (4 5) moo)) (i (lik(cherries)e (woohoo)))
          4 5                cherries    woohoo
  1 2  3       moo       lik          e
                      i

Объяснение:

Это объяснение основано на первой версии моей программы:

|.|:('( ) 'charsub x)((' '$~{.@]),[{~{:@])"1(('('&([:+/=)-')'&([:+/=))\,.i.@#)x=.1!:1[1

x=.1!:1[1взять ввод с клавиатуры и положить его на xпотом

(('('&([:+/=)-')'&([:+/=))\,.i.@#)создает список всех индексов в string ( i.@#) и stitches ( ,.) вместе с результатом (('('&([:+/=)-')'&([:+/=))\глагола.

(('('&([:+/=)-')'&([:+/=))\этот глагол применяется ко всем префиксам строки (так на входе helloбыло бы применить к h, he, hel, hell, и hello. Он представляет собой вилку , которая подсчитывает количество открытых скобок , ('('&([:+/=)а затем вычитает число близких скобок ')'&([:+/=). Это дает мне список of Indends в строку и уровень, на котором должен находиться символ с этим индексом в выходных данных. При простом вводе это дает мне следующее:

   (('('&([:+/=)-')'&([:+/=))\,.i.@#)x=.1!:1[1
(one(two(three)))
1  0
1  1
1  2
1  3
2  4
2  5
2  6
2  7
3  8
3  9
3 10
3 11
3 12
3 13
2 14
1 15
0 16

((' '$~{.@]),[{~{:@])"1это глагол, который берет список, который я только что сгенерировал, а также вывод ('( ) 'charsub x)(который просто заменяет строку, заменяя все скобки пробелами внутри x). Он берет хвост каждого элемента списка {:@]и использует его как индекс в строке, чтобы получить символ [{~{:@]. Затем к нему добавляется ,число пробелов, указанное в заголовке каждого элемента в списке (' '$~{.@]). На предыдущем примере это дает мне:

   ('( ) 'charsub x)((' '$~{.@]),[{~{:@])"1(('('&([:+/=)-')'&([:+/=))\,.i.@#)x=.1!:1[1
(one(two(three)))

 o
 n
 e

  t
  w
  o

   t
   h
   r
   e
   e

Затем я переставляю массив |:и обращаюсь к нему, |.чтобы получить желаемый результат.

Gareth
источник
6

GolfScript 69

0:§;{.'()'?))3%(.§+:§' ':s*\@s\if\n}%n/.{,}%$)\;:μ;{.,μ\-s*\+}%zip n*

Онлайн демо здесь .

Объяснение:

0:§;                # declare the variable §, representing the 
                    # current vertical level and initialize it at 0

{                   # iterate for each char in the string:

    .'()'?))3% (    # add on the stack the amount by which
                    # the current vertical level should be 
                    # adjusted:
                    #   * +1 if the character is '('
                    #   * -1 if the character is ')'
                    #   * 0 otherwise

    .§+:§           # adjust the value of §

    ' ':s*          # add as many spaces as § tells us
                    # and save the space in variable s

    \@s\if\         # return current char, if it's printable,
                    # or a space if it's '(' or ')'

    n               # add a newline char

}%

n/                  # split by newline char; now we have 
                    # an array of strings on the stack.
                    # Each string is a vertical line of the
                    # final output.

.{,}%$)\;:μ;        # Iterate through the strings and find the
                    # maximum length

{
    .,μ\-s*\+       # Add spaces at the end to make all the strings 
                    # the same length
}%

zip                 # Transpose the strings

n*                  # Join the transposed strings by newline characters
Кристиан Лупаску
источник
@ Гарет Да, мы оба делаем :)
Кристиан Лупаску
Хотите добавить объяснение, как это работает?
Тимви
@Timwi Я отредактировал свой ответ, чтобы включить объяснение
Кристиан Лупаску
5

APL (59)

⊖↑{⊃,/T\¨⍨⍵×P=0}¨R∘=¨(⍴T)∘⍴¨⍳⌈/R←1++\P←+/¨1 ¯1∘ר'()'∘=¨T←⍞

Я предположил, что «база» должна быть пригодной для использования. (т.е. (a(b))c(d)действует). Если в этом нет необходимости, можно сохранить два символа.

Объяснение:

  • T←⍞: сохранить строку ввода в T
  • '()'∘=¨T: для каждого символа в T посмотрите, является ли это открывающей или закрывающей скобкой. Это дает список списков логических значений.
  • 1 ¯1∘ר: умножить второй элемент в каждом из этих списков на -1 (поэтому открывающая скобка равна 1, закрывающая - -1, а любой другой символ - 0).
  • +/¨: взять сумму каждого внутреннего списка. Теперь у нас есть значение ∆y для каждого символа.
  • P←: магазин в П.
  • R←1++\P: взять промежуточный итог P, давая высоту для каждого символа. Добавьте один к каждому символу, чтобы символы за скобками находились в первой строке.
  • (⍴T)∘⍴¨⍳⌈/R: для каждого возможного значения y составьте список длиной до T, состоящий только из этого значения. (т.е. 1111 ..., 2222 .... и т. д.)
  • R∘=¨: для каждого элемента в этом списке посмотрите, равен ли он R. (Для каждого уровня у нас теперь есть список нулей и единиц, соответствующих тому, должен ли символ появляться на этом уровне).
  • ⍵×P=0: для каждого из этих списков установите его на ноль, если P не равен нулю в этом месте. Это избавляет от символов с ненулевым delta-y, так что избавляется от скобок.
  • ⊃,/T\¨⍨: для каждой глубины выберите из T символы, которые должны появиться.
  • ⊖↑: создайте матрицу и поместите ее правой стороной вверх.
Мэринус
источник
Какую реализацию APL вы используете? Это бесплатно?
FUZxxl
@FUZxxl Я использую Dyalog APL, версию для Windows можно скачать бесплатно.
Марин
5

Tcl, 50

puts \33\[9A[string map {( \33\[A ) \33\[B} $argv]

Вид обмана, но хорошо ..

Я использую escape-последовательности ascii, чтобы получить разницу строк, ^[[Aзначит переместить курсор на 1 строку вверх, ^[[Bпереместить курсор на 1 строку вниз.

Йоханнес Кун
источник
5

APL, 41 символ / байт *

{⊖⍉⊃(↑∘''¨-⌿+/¨p∘.=,\⍵),¨⍵/⍨1-2×⍵∊p←'()'}

Проверено на Dyalog, с ⎕IO←1и ⎕ML←3окружающей средой. Это функция, которая принимает необходимые входные данные и возвращает выходные данные. Учитывая формулировку вопроса, я считаю, что это приемлемо. Если это не так, вот версия, которая читает из stdin и пишет в stdout, еще на 4 символа:

⍞←⊖⍉⊃(↑∘''¨-⌿+/¨'()'∘.=,\a),¨a/⍨1-2×'()'∊⍨a←⍞

Пояснение :

{                                 p←'()'}  p is the string made of two parentheses
                                ⍵∊ ______  check which characters from ⍵ are parens
                            1-2× ________  -1 for every par., 1 for every other char
                         ⍵/⍨ ____________  replace () with spaces in the orig. string
    (                 ),¨ _______________  append every char to the following items
                   ,\⍵ _____________________  for every prefix of the original string
               p∘.= ________________________  check which chars are '(' and which ')'
            +/¨ ____________________________  sum: compute the number of '(' and ')'
          -⌿ _______________________________  subtract the no. of ')' from that of '('
     ↑∘''¨ _________________________________  generate as many spaces as that number
 ⊖⍉⊃ ____________________________________  make it into a table, transpose and flip

Примеры:

topo '((1 2)(3 (4 5) moo)) (i (lik(cherries)e (woohoo)))'
          4 5                cherries    woohoo   
  1 2  3       moo       lik          e           
                      i                           

 

topo 'a  (  b ( c(d)e ) f  )  g'
            d            
          c   e          
      b           f      
a                       g

*: APL может быть сохранен во множестве устаревших однобайтовых кодировок, которые отображают символы APL в верхние 128 байтов. Поэтому для целей игры в гольф программа, которая использует только символы ASCII и символы APL, может быть оценена как chars = bytes.

Тобия
источник
Я ищу набор символов APL здесь , и я не могу найти символ. Это выглядит как сочетание из ¨и ~символов?
Гарет
Привет @ Гарет Нет, это не было в IBM APL2. Вы можете найти его в Dyalog (коммерческий, но на их сайте спрятана версия nagware, и этого вполне достаточно для игры в гольф; IMHO лучший APL на сегодняшний день), Nars2000 (лучший APL с открытым исходным кодом), GNU APL и APL ngn , среди прочих. другие.
Тобиа
@Gareth Графически это комбинация ~и ¨, хотя это отличается от символов обоих. Это оператор под названием Commute . В своей диадической форме он переворачивается аргументы двоичной функции он применяется к: (5-2)=(2-⍨5). Как монадической оператор оказывается двоичная функция в Монадический, дублируя правильный аргумент: (2*2)=(*⍨2). Он в основном используется для написания непрерывного потока функций справа налево, без необходимости ставить круглые скобки вокруг больших выражений и прыгать вокруг них. В гольфе это полезно, потому что 3*⍨1-2на один символ меньше чем (1-2)*3:-)
Tobia
2
Так что это эквивалент ~в J тогда.
Гарет
3

J, 56 символов

'( ) 'charsub|.|:((,~#&' ')"0[:+/\1 _1 0{~'()'&i.)1!:1]1

Другое 56-символьное решение J ... Я считаю глубину путем перевода (в ⁻1, )в 1 и всех другие символы в 0, а затем принимать идущую сумму этого: [: +/\ 1 _1 0 {~ '()'&i.. Остальное во многом похоже на решение @ Gareth.

Светляк
источник
2

Питон, 161 символ

S=raw_input()
R=range(len(S))
H=[S[:i].count('(')-S[:i].count(')')for i in R]+[0]
for h in range(max(H),0,-1):print''.join((' '+S[i])[H[i]==H[i+1]==h]for i in R)
Кит Рэндалл
источник
2

Питон, 130

a=[""]*9
l=8
i=0
for c in raw_input():o=l;l+=c==')';l-=c=='(';a[l]=a[l].ljust(i)+c*(o==l);i+=1
print"\n".join(filter(str.strip,a))
GRC
источник
2

Рубин 1,9 (129)

Читает со стандартного ввода.

l=0
$><<gets.split('').map{|c|x=[?(]*99;x[l+=c==?(?-1:c==?)?1:0]=c;x}.transpose.map(&:join).*(?\n).tr('()',' ').gsub(/^\s+\n/,'')
Пол Престиж
источник
3
Ницца! вы обнаружили ошибку в Ruby Highlighter :)
Кристиан Лупаску
Я проверил, и подсветка SQL работает лучше для вашей программы.
Кристиан Лупаску
@ w0lf ха, ты прав. Я изменил значение, //в ''котором количество символов остается прежним, и избегаю ошибки в маркере.
Пол Престиж
2

C, 132 символа

char*p,b[999];n;
main(m){for(p=gets(memset(b,32,999));*p;++p)*p-41?*p-40?p[n*99]=*p:++n>m?m=n:0:--n;
for(;m;puts(b+m--*99))p[m*99]=0;}

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

В коде есть два основных цикла. Первый цикл отправляет все символы, не являющиеся скобками, в соответствующую строку вывода, а второй цикл печатает каждую строку.

Хлебница
источник
1

С, 149 символов

#define S for(i=0;c=v[1][i++];)h+=a=c-'('?c-')'?0:-1:1,
c,i,h=0,m=0;main(int a,char**v){S m=h>m?h:m;for(;m;m--){S putchar(a||h-m?32:c);putchar(10);}}

бегите с цитируемым аргументом, egaout "((1 2) (3 (4 5) moo)) (i (lik (вишня) e (woohoo)))"

ребенок кролика
источник
0

C #, 229 байт

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

using C=System.Console;
class P{
    static void Main(string[]a){
        int l=a[0].Length,i=l;
        while(i>0)
            if(a[0][--i]=='(')C.CursorTop++;
        while(++i<l){
            char c=a[0][i];
            if(c=='('){
                c=' ';
                C.CursorTop--;
            }
            if(c==')'){
                c=' ';
                C.CursorTop++;
            }
            C.Write(c);
        }
    }
}
Hand-E-Food
источник
0

PowerShell , 120 119 байт

(($h=($c=$args|% t*y)|%{($l+=(1,-1)[$_-40])})|sort)[-1]..0|%{$x=0;$y=$_
-join($c|%{"$_ "[$h[$x++]-ne$y-or$_-in40,41]})}

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

Побочные эффекты: Символы &и 'изменяет высоту , как (и ), но дисплеи. Сравните результаты для:

&$f "((1 2)(3 (4 5) moo)) (i (lik(cherries)e (woohoo)))"
&$f "&&1 2'&3 &4 5' moo'' &i &lik&cherries'e &woohoo'''"

Менее гольф:

$chars=$args|% toCharArray

$heights=$chars|%{
    $level+=(1,-1)[$_-40]       # 40 is ASCII for '(', 41 is ASCII for ')'
    $level
}

$maxHeight=($heights|sort)[-1]

$maxHeight..0|%{
    $x=0;$y=$_
    $line=$chars|%{
        "$_ "[$heights[$x++]-ne$y -or $_-in40,41]
    }
    -join($line)
}
Mazzy
источник
-1

VB.net (для S & G)

Не самый красивый код.

Module Q
 Sub Main(a As String())
  Dim t = a(0)
  Dim h = 0
  For Each m In (From G In (t.Select(Function(c)
                                     h += If(c = "(", 1, If(c = ")", -1, 0))
                                     Return h
                                   End Function).Select(Function(y, i) New With {.y = y, .i = i}))
             Group By G.y Into Group
             Order By   y Descending
            Select Group.ToDictionary(Function(x) x.i)
               ).Select(Function(d) New String(
                          t.Select(Function(c,i)If(d.ContainsKey(i),If(c="("c Or c=")"c," "c,c)," "c)).ToArray))
   Console.WriteLine(m)
  Next
 End Sub
End Module
Адам Спейт
источник