Последовательность скобок в лексикографическом порядке

9

Вызов взят здесь, а также здесь

Последовательность из n скобок состоит из n ( s и n ) s.

Допустимая последовательность скобок определяется следующим образом:

Вы можете найти способ повторить удаление соседней пары скобок "()", пока она не станет пустой.

Например, (())это допустимые скобки, вы можете стереть пару на 2-й и 3-й позиции, и она становится (), тогда вы можете сделать ее пустой. )()(недопустимые скобки, после того, как вы удалите пару на 2-й и 3-й позиции, она становится, )(и вы больше не можете стереть

задача

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

Вывод может быть массивом, списком или строкой (в данном случае последовательность на строку)

Вы можете использовать другую пару скобок , таких как {}, [], ()или любого открытого близко знаком

пример

  • n = 3

    ((()))    
    (()())    
    (())()    
    ()(())    
    ()()()
    
  • п = 2

    (())
    ()()
    
Луис Фелипе Де Иисус Муньос
источник
@ JoKing Да, конечно. Я предполагаю, что в любом случае не будет иметь никакого значения для основной концепции задачи.
Луис Фелипе Де Иисус Муньос
Эх, я могу вспомнить несколько языков, где eval будет интерпретировать их по-разному, например
Джо Кинг,
1
Связанный: каталонские числа (результат этого вызова = количество строк результата этого вызова)
user202729
3
Практически то же самое , но с некоторыми странными ограничениями, такими как «Вы не можете писать рекурсивные функции». /// Надстройка этой задачи (разрешить все скобки Brain-Flak)
user202729
Означает ли «массив, список или строка» «последовательностей» «любой знак открытия-закрытия», что мы можем вывести список списков из двух целых чисел (например, 1s и -1s)?
Джонатан Аллан

Ответы:

8

Perl 6 , 36 байт

{grep {try !.EVAL},[X~] <[ ]>xx$_*2}

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

Находит все лексографически отсортированные комбинации 2N []и фильтрует те, которые EVALправильно. Обратите внимание, что все действительные комбинации (даже такие как [][]) оцениваются как [](что неверно, но мы notэто ( !) отличаем от tryвозвращаемыхNil )

Объяснение:

{                                  }  # Anonymous code block
                        <[ ]>         # Create a list of ("[", "]")
                             xx$_*2   # Duplicate this 2n times
                   [X~]               # Find all possible combinations
 grep {          },                   # Filter from these
            .EVAL                     # The EVAL'd strings
       try !                          # That do not throw an error
Джо Кинг
источник
3
Если кому-то интересно, [][]это дзенский фрагмент пустого массива, который возвращает сам массив. Срез может быть применен несколько раз, поэтому [][][][]...оценивается []. Кроме того, [[]]не строит вложенный массив, но пустой массив из-за правила единственного аргумента (вы должны написать [[],]для вложенного массива). Таким образом, любая сбалансированная последовательность []скобок приводит к пустому массиву, который превращается в false.
nwellnhof
6

R , 112 107 99 байт

Нерекурсивный подход. Мы используем "<" и ">", потому что он избегает escape-символов в регулярном выражении. Чтобы позволить нам использовать более короткую спецификацию для диапазона ASCII, мы генерируем 3 ^ 2n 2n-символьных строк "<", "=" и ">", используяexpand.grid (через их коды ASCII 60, 61 и 62), а затем выполняем команду grep для посмотрите, какие комбинации дают сбалансированные открывающие и закрывающие скобки. Конечно, возможности "=" будут игнорироваться.

Через http://rachbelaid.com/recursive-regular-experession/

function(n)sort(grep("^(<(?1)*>)(?1)*$",apply(expand.grid(rep(list(60:62),2*n)),1,intToUtf8),,T,T))

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

объяснение

"^(<(?1)*>)(?1)*$" = regex for balanced <> with no other characters
^ # match a start of the string
  ( # start of expression 1
    < # open <>
       (?1)* # optional repeat of any number of expression 1 (recursive)
  # allows match for parentheses like (()()())(()) where ?1 is (\\((?1)*\\))
    > # close <>
  ) # end of expression 1
  (?1)* # optional repeat of any number of expression 1
$ # end of string

function(n)
  sort(
    grep("^(<(?1)*>)(?1)*$", # search for regular expression matching open and close brackets
      apply(
        expand.grid(rep(list(60:62),2*n)) # generate 3^(2n) 60,61,62 combinations
      ,1,intToUtf8) # turn into all 3^(2n) combinations of "<","=",">"
    ,,T,T) # return the values that match the regex, so "=" gets ignored
  ) # sort them

р , 107 байт

Обычный рекурсивный подход.

-1 спасибо @Giuseppe

f=function(n,x=0:1)`if`(n,sort(unique(unlist(Map(f,n-1,lapply(seq(x),append,x=x,v=0:1))))),intToUtf8(x+40))

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

j.doe
источник
1
ах, я пытался найти Mapгольф, но не мог обернуть голову вокруг него. Я не убежден, что parse+ evalбудет работать с тех пор ()()и тому подобное.
Джузеппе
4

C (gcc) , 114 байтов

f(n,x,s,a,i){char b[99]={};n*=2;for(x=1<<n;x--;s|a<0||puts(b))for(s=a=i=0;i<n;)a|=s+=2*(b[n-i]=41-(x>>i++&1))-81;}

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

Должно работать для n <= 15.

объяснение

f(n,x,s,a,i){
  char b[99]={};   // Output buffer initialized with zeros.
  n*=2;            // Double n.
  for(x=1<<n;x--;  // Loop from x=2**n-1 to 0, x is a bit field
                   // where 1 represents '(' and 0 represents ')'.
                   // This guarantees lexicographical order.
      s|a<0||puts(b))  // Print buffer if s==0 (as many opening as
                       // closing parens) and a>=0 (number of open
                       // parens never drops below zero).
    for(s=a=i=0;i<n;)  // Loop from i=0 to n-1, note that we're
                       // traversing the bit field right-to-left.
      a|=              // a is the or-sum of all intermediate sums,
                       // it becomes negative whenever an intermediate
                       // sum is negative.
        s+=            // s is the number of closing parens minus the
                       // number of opening parens.
                        x>>i++&1   // Isolate current bit and inc i.
                    41-(        )  // ASCII code of paren, a one bit
                                   // yields 40 '(', a zero bit 41 ')'.
             b[n-i]=               // Store ASCII code in buffer.
          2*(                    )-81;  // 1 for ')' and -1 for '(' since
                                        // we're going right-to-left.
}
nwellnhof
источник
4

Python 2 , 91 88 84 81 байт

f=lambda n:n and sorted({a[:i]+'()'+a[i:]for a in f(n-1)for i in range(n)})or['']

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

-3 байта благодаря pizzapants184

TFeld
источник
Также работает в Python 3, я думаю
SuperStormer
Вы можете заменить set(...)набором compreatsion ( {...}) на -3 байта. Попробуйте онлайн!
pizzapants184
@ pizzapants184 Спасибо :)
TFeld
3

05AB1E , 13 байтов

„()©s·ãʒ®õ:õQ

Попробуйте онлайн или проверьте еще несколько тестов .

Объяснение:

„()            # Push string "()"
   ©           # Store it in the register without popping
    s·         # Swap to get the (implicit) input, and double it
      ã        # Cartesian product that many times
       ʒ       # Filter it by:
        ®      #  Push the "()" from the register
         õ:    #  Infinite replacement with an empty string
           õQ  #  And only keep those which are empty after the infinite replacement
Кевин Круйссен
источник
3

Japt, 15 13 байт

ç>i<)á Ôke/<>

Попробуй это


объяснение

ç                 :Input times repeat the following string
 >i<              :  ">" prepended with "<"
    )             :End repeat
     á            :Get unique permutations
       Ô          :Reverse
        k         :Remove any that return true (non-empty string)
         e/<>     :  Recursively replace Regex /<>/
мохнатый
источник
3

K (нгн / к) , 36 35 байт

{"()"(&/-1<+\1-2*)#(x=+/)#+!2|&2*x}

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

+!2|&2*x все двоичные векторы длины 2 * n

(x=+/)# только те, которые суммируются

(&/-1<+\1-2*)# только те, чьи частичные суммы, рассматривающие 0/1 как 1 / -1, нигде не являются отрицательными

"()" используйте 0/1 в качестве индексов в этой строке

СПП
источник
2

Perl 6 , 42 байта

{grep {!S:g/\(<~~>*\)//},[X~] <( )>xx$_*2}

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

Использует рекурсивное регулярное выражение. Альтернативная замена:S/[\(<~~>\)]*//

38 байтов с 0 и 1 в качестве символов открытия / закрытия:

{grep {!S:g/0<~~>*1//},[X~] ^2 xx$_*2}

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

объяснение

{                                        }  # Anonymous block
                              <( )>         # List "(", ")"
                                   xx$_*2   # repeated 2n times
                         [X~]  # Cartesian product with string concat
                               # yields all strings of length 2n
                               # consisting of ( and )
 grep {                },  # Filter strings
        S:g/             # Globally replace regex match
            \(           #   literal (
              <~~>       #   whole regex matched recursively
                  *      #   zero or more times
                   \)    #   literal )
                     //  # with empty string
       !                 # Is empty string?
nwellnhof
источник
2

Сетчатка 0.8.2 , 50 байт

.+
$*
1
11
+%1`1
<$'¶$`>
Gm`^(?<-1>(<)*>)*$(?(1).)

Попробуйте онлайн! Использует <>с. Объяснение:

.+
$*

Преобразовать в одинарный.

1
11

Удвойте результат.

+%1`1
<$'¶$`>

Перечислите все 2 × 2n-битные двоичные числа, сопоставляя цифры с <>.

Gm`^(?<-1>(<)*>)*$(?(1).)

Храните только сбалансированные последовательности. Это использует трюк со сбалансированными скобками, обнаруженный @MartinEnder.

Нил
источник
2

Красный , 214, 184 136 байт

func[n][g: func[b n][either n = length? b[if not error? try[load b][print b]return 0][g append copy b"["n g append copy b"]"n]]g""2 * n]

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

Использует подход Джо Кинга. Находит все возможные расположения скобок с использованием рекурсии (они генерируются в лексикографическом порядке) и распечатывает его, если расположение оценивается как действительный блок.

Гален Иванов
источник