Топографічні рядки


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. Так само є 4 символи на вході між mooі i.

Виграє код, який робить це з найменшою кількістю символів.


Чи безпечно припускати, що висоти завжди будуть позитивними? Наприклад, введення ((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.@#)створює список усіх відмінків у рядок ( i.@#) та прошиває ( ,.) разом із результатом (('('&([:+/=)-')'&([:+/=))\дієслова.

(('('&([:+/=)-')'&([:+/=))\це дієслово застосовується до всіх префіксам рядки (так на вході helloбуло б застосувати до h, he, hel, hell, і hello. Він являє собою вилку , яка підраховує кількість відкритих дужок , ('('&([:+/=)а потім віднімає число близьких дужок ')'&([:+/=). Це дає мені список індексів у рядку та рівня, на якому символ у цьому індексі має бути на виході. На простому введенні це дає мені таке:

   (('('&([:+/=)-')'&([:+/=))\,.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

Потім перекладаю масив |:і повертаю його назад, |.щоб отримати бажаний вихід.


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

@Gareth Так, ми обидва :)
Крістіан Лупаску

Хочете додати пояснення, як це працює?
Тімві

@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: візьміть загальну кількість Р, даючи висоту для кожного символу. Додайте їх до кожного символу, щоб символи поза дужками знаходились у першому рядку.
  • (⍴T)∘⍴¨⍳⌈/R: для кожного можливого значення y складіть список дотику T, що складається лише з цього значення. (тобто 1111 ..., 2222 .... і т. д.)
  • R∘=¨: для кожного елемента цього списку подивіться, чи дорівнює він R. (Для кожного рівня тепер у нас є список нулів та ті, які відповідають тому, чи повинен на цьому рівні відображатися символ).
  • ⍵×P=0: для кожного з цих списків встановіть його на нуль, якщо P на цьому місці не дорівнює нулю. Це позбавляється від символів з ненульовою дельтою-у, так що позбавляється дужок.
  • ⊃,/T\¨⍨: для кожної глибини виберіть із T символи, які повинні з’явитися.
  • ⊖↑: створити матрицю і поставити її правою стороною вгору.

Яку реалізацію APL ви використовуєте? Це безкоштовно?
FUZxxl

@FUZxxl Я використовував Dyalog APL, версію Windows можна завантажити безкоштовно.
Марінус

5

Tcl, 50

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

Вид обману, але добре ..

Я використовую послідовності біг 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, може бути оцінена як символи = байти.


Я шукаю набір символів APL тут , і я не можу знайти символ. Це схоже на поєднання символів ¨та ~символів?
Гарет

Привіт @Gareth Ні, цього не було в IBM APL2. Ви можете знайти його в Dyalog (комерційний, але є nagware версія похований на своєму веб - сайті, і це досить добре для гри в гольф, ІМХО найкращий 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))

2

Рубін 1,9 (129)

Читає від stdin.

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 :)
Крістіан Лупаску

Я перевірив, і підсвічування 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

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

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

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