Гольф Алгоритм соответствия скобок

25

Вам будет предоставлена ​​строка s. Гарантируется, что строка имеет равные и хотя бы один [s и ]s. Также гарантируется, что кронштейны сбалансированы. Строка также может содержать другие символы.

Цель состоит в том, чтобы вывести / вернуть список кортежей или список списков, содержащих индексы каждого [и ]пары.

примечание: строка с нулевым индексом.

Пример: !^45sdfd[hello world[[djfut]%%357]sr[jf]s][srtdg][]должен вернуться

[(8, 41), (20, 33), (21, 27), (36, 39), (42, 48), (49, 50)]или что-то эквивалентное этому. Кортежи не нужны. Списки также могут быть использованы.

Тестовые случаи:

input:[[asdf][][td([)ty54g% ]hg[[f]u][f[[jhg][gfd]sdf]sdfs]ghd]fr43f]
output:[(0, 62),(1, 6), (7, 8), (9, 56), (13, 22), (25, 30), (26, 28), (31, 52), (33, 47), (34, 38), (39, 43)]
input:[[][][][]][[][][][[[[(]]]]]))
output:[(0, 9), (1, 2), (3, 4), (5, 6), (7, 8), (10,26),(11, 12), (13, 14), (15, 16), (17, 25), (18, 24), (19, 23), (20, 22)]
input:[][][[]]
output:[(0, 1), (2, 3), (4, 7), (5, 6)]
input:[[[[[asd]as]sd]df]fgf][][]
output:[(0, 21), (1, 17), (2, 14), (3, 11), (4, 8), (22, 23), (24, 25)]
input:[]
output:[(0,1)]
input:[[(])]
output:[(0, 5), (1, 3)]

Это , поэтому выигрывает самый короткий код в байтах для каждого языка программирования.

Печенье мельницы
источник
1
Имеет ли значение порядок вывода?
wastl
1
нет.
Печенье ветряной мельницы
21
msgstr "примечание: строка индексируется нулями." - Распространено позволить реализациям выбирать последовательную индексацию в таких задачах (но это, конечно, зависит от вас)
Джонатан Аллан
1
Можем ли мы принять ввод как массив символов?
Лохматый
7
Стоит один байт ...
Дилнан

Ответы:

13

Brain-Flak Classic , 108 байт

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

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

Сохраняет каждое отверстие [в правильном стеке и выводит всякий раз, когда мы нажимаем ].

Nitrodon
источник
5

JavaScript, 69 62 байта

Немного о гольфе в поезде домой. Возможно, может быть улучшено.

Принимает ввод как массив символов и выводит объект с ключами, являющимися индексами [s, а их значения - индексами соответствующих им ]s.

a=>a.map((x,y)=>x==`]`?o[a.pop()]=y:x==`[`&&a.push(y),o={})&&o

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

мохнатый
источник
Я поражаюсь, что ты можешь играть в гольф на мобильном телефоне. : P
Оливер
2
@ Оливер, меня поражает, что я могу (почти) печатать на сенсорных экранах вообще - вернуть клавиатуры!
Лохматый
4

Haskell , 92 79 байтов

g(u:a)n(']':x)=(u,n):g a(n+1)x
g a n(s:x)=g([n|s=='[']++a)(n+1)x
g[]_[]=[]
g[]0

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

объяснение

Мы создаем функцию, gкоторая принимает 3 аргумента.

  • a, который является местоположением всех непревзойденных [с.

  • n, которое является количеством обработанных символов

  • x что символы необработанные.

Если наш первый символ - ]мы убираем uспереди наш aи возвращаем (u,n)плюс все остальное.

g(u:a)n(']':x)=(u,n):g a(n+1)x

Если наш первый символ - нет ], то есть [или что-то еще, мы увеличиваем nи добавляем [n|s=='[']в начало a. [n|s=='[']будет [n]если s=='['и []иначе.

g a n(s:x)=g([n|s=='[']++a)(n+1)x

Если у нас нет символов, мы возвращаем пустой список.

g[]_[]=[]
Мастер пшеницы
источник
1
вау, вот хороший кусок рекурсивных функций. Я новичок в Haskell, это меня впечатлило :)
Windmill Cookies
@ gnu-никто Спасибо! Этот ответ, вероятно, не оптимален, поэтому я бы посоветовал вам попытаться победить его или подождать, пока не появятся серьезные игроки в гольф на Хаскеле.
Пшеничный волшебник
Я бы лучше подождал, пока не появятся серьезные игроки в гольф на Haskell
Windmill Cookies
4

Java 10, 95 байт

Пустая лямбда, принимающая входную строку как int[]кодовые точки Юникода.

s->{int r=0,w=0;for(var c:s){if(c==91)s[w++]=r;if(c==93)System.out.println(s[--w]+","+r);r++;}}

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

Ungolfed

s -> {
    int r = 0, w = 0;
    for (var c : s) {
        if (c == 91)
            s[w++] = r;
        if (c == 93)
            System.out.println(s[--w] + "," + r);
        r++;
    }
}

Подтверждения

  • спасибо Джонатану Фреху за идею использования входной строки в качестве стека ( здесь )
Jakob
источник
Вы должны определить rи wкак часть кода, а не в качестве параметров: s->{int r=0,w=0;...}.
Оливье Грегуар
@ OlivierGrégoire Вид неоднозначны, но этого выглядит , как это было предназначено , чтобы охватить несколько пустых входов.
Якоб
1
Ответ, который вы цитируете, явно отвечает на вопрос «Разрешено ли нам принимать пустой параметр, вместо того, чтобы мы его нигде не использовали ?». Вы используете эти входы. Я не вижу здесь никакой двусмысленности.
Оливье Грегуар
Часть вопроса, связанная с редактированием, делает ее абсолютно недвусмысленной в отношении «неиспользуемой» переменной.
Оливье Грегуар
Правильно, но тогда почему верхний ответ (1) не утверждает, что входы не используются, (2) указывает, каковы значения дополнительных входов, и (3) упоминает возможность злоупотребления дополнительными входами? Независимо от того, я буду перемещать переменные.
Якоб
4

vim, 89 байт

:s/\(.\)/\1<C-V><C-M>/g|g/^\[/ :norm %mm%:pu! =line('.').','.line(\"'m\")<C-V><C-M><C-X>$<C-X>J
:v/\[/d|%s/\[//g

аннотированный

:s/\(.\)/\1<C-V><C-M>/g            " one character per line
|g/^\[/                            " for each opening square bracket:
  :norm %mm%                       "   mark the line with the matching bracket
  :pu! =line('.').','.line(\"'m\") "   write the line numbers to preceeding line
  <C-V><C-M><C-X>$<C-X>J           "   convert to 0-based counting and join lines
:v/\[/d                            " remove all non-opening bracket lines
|%s/\[//g                          " remove brackets

<C-V>0x16. <C-M>0x0d. <C-X>0x18.

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

луч
источник
4

QBasic (QB64), 137 127 112 байтов

INPUT a$
for i=0to len(a$)
c$=mid$(a$,i+1,1)
if"["=c$then
b(n)=i
n=n+1
elseif"]"=c$then
n=n-1
?b(n),i
endif
next

Нам нужны четыре двух байта, потому что задача требует 0-индексации. Мой первый пост QBasic, обратная связь приветствуется.

  • 10 байтов благодаря Стинбергу
  • 3 байта благодаря Эрику Аутгольферу
  • 12 байтов, сохраняя в формате Unix ( \r\n-> \n)

Выглядит так при исполнении:

Как это выглядит

Wastl
источник
Хороший. Пара указателей: используйте ?вместо print(компилятор автоматически расширяет это до print), вам не нужны пробелы между строками в кавычках и THENв IFs, и вы можете удалить iпосле NEXT.
Steenbergh
@steenbergh Да, кажется, я забыл удалить пробелы ... но я удалил один между 0и to? Я в замешательстве ...
Wastl
1
Не уверен насчет QB64, но думаю if c$="["может статьif"["=c$ , elseif c$="]"может стать elseif"]"=c$, end ifможет стать endifи, с небольшим изменением выходных данных, ?b(n),iможет стать ?b(n)i(QBasic 1.1 - это то, что я использую, ваш случай может отличаться).
Эрик Outgolfer
@EriktheOutgolfer почти все ?b(n)iработает
wastl
3

Pyth, 26 байт

VQIqN\[=+YZ)IqN\],.)YZ)=hZ

Попробуй здесь

объяснение

VQIqN\[=+YZ)IqN\],.)YZ)=hZ
VQ                     =hZ   For each character in the input (indexed by Z)...
  IqN\[=+YZ)                 ... if the character is [, add the index to Y...
            IqN\],.)YZ)      ... if the character is ], output the previous index
                             and current index.

источник
Ницца! Мой наивный подход был 36 байтов C,x"[" MQ #.e*qb\[t+lhfSI/LT"[]"._>Q. Редактировать: я тоже немного преуспел в игре в гольф, сейчас мне меньше 30.
Мистер Xcoder,
3

R , 141 133 115 112 108 байт

function(y,x=utf8ToInt(y)){for(i in seq(x)){if(x[i]==91)F=c(i,F);if(x[i]==93){T=c(T,F[1],i);F=F[-1]}};T[-1]}

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

Ничего особенного. 1-индексированный, потому что я так сказал. У R на самом деле нет стеков, поэтому я изначально использовалc , headи tailполучить тот же самый буквальный эффект. Развернутая оригинальная версия (обновляет, используя, utf8ToIntчтобы удалить некоторые байты, используя начало вектора в качестве вершины стека, и злоупотребляя Tи Fвстроенными, чтобы избежать инициализации стеков.):

f <- function(y, x=el(strsplit(y,""))) {
  p <- l <- NULL
  for(i in seq_along(x)) {
    if(x[[i]]=='[') {
      p <- c(p, i)
    }
    if(x[[i]]==']') {
      l <- c(l, tail(p, 1), i)
      p <- head(p, -1)
    }
  }
  l # Because I said so. Change to l-1 if you want to check the test cases.
}
НГМ
источник
и 1:nchar(y)короче чем seq_along(x). Очень хорошее решение, кстати :)
JayCe
Интересно, если gregexprэто путь?
НГМ
Первоначально я пытался использовать этот подход, но я не уверен, что это правильный путь.
JayCe
Решение JayCe имеет недостатки (проверьте результат, он возвращает 22 28 22вместо 22 28 21), вероятно, использование (ab) T / F не совсем безопасно: D. Это короче и похоже на работу -> Попробуйте онлайн!
digEmAll
2

Forth (gforth) , 75 байтов

: f 0 do dup i + c@ dup 91 = if i s>f then 93 = if f>s . i . cr then loop ;

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

Злоупотребляет стеком с плавающей запятой, но позволяет использовать a, do loopпоскольку код не (вручную) касается стека возврата.

объяснение

  1. Перебирать символы в строке
  2. Проверьте каждый символ
    1. Если равно [ , положить в стек с плавающей запятой
    2. если равно ]pop из стека с плавающей точкой и выводится с текущей позицией

Код Объяснение

0 do                 \ start a loop from 0 to string-length
  dup                \ duplicate the starting address to avoid losing it
  i + c@             \ get the address of the current position and retrieve the character
  dup                \ duplicate the character, to allow checking twice
  91 = if            \ if char = [
    i s>f            \ store the current address on the floating point stack
  then               \ end the if-statement
  93 = if            \ if char = ]
    f>s .            \ pop the starting position from the float-stack and print
    i .              \ print the current position
    cr               \ output a newline
  then               \ end the if-statement
loop                 \ end the loop
reffu
источник
2

Сетчатка , 36 байт

L$v`\[((\[)|(?<-2>])|[^]])*
$.`,$.>`

Попробуйте онлайн! Объяснение:

L

Создайте список из результатов матча.

$

Используйте следующую замену для создания списка вместо совпадений.

v`

Разрешить совпадения совпадений

\[((\[)|(?<-2>])|[^]])*

Это приложение балансировочных групп .NET. [Подобран в буквальном смысле, то , как много символов , сколько возможно потребляется. При [сопоставлении каждого последующего совпадение добавляется в $2стек. Если этот стек не пустой, мы можем сопоставить ], удалив совпадение из стека. В противном случае мы можем сопоставить все, что не является ]( [ранее уже было сопоставлено). Совпадение прекращается, когда оно встречает совпадение ]для [, поскольку $2стек (сейчас) пуст в этой точке.

$.`,$.>`

Подстановка состоит из двух переменных, разделенных запятой. .Указывает на то, что длина переменной, а не ее значение, можно использовать. >Указывает на то, что переменная должна быть оценена с точки зрения правой сепаратора , а не матч. $`Переменная относится к префиксу матча, что означает , $.`дает позицию [; то >модификатор изменяет к префиксу правого сепаратора матча, который дает положение соответствия ].

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

Желе ,  22 21 20  19 байт

Без сомнения, в Jelly это возможно вдвое меньше: p ...

n€Ø[ḅ-µMịÄÐƤi€0ĖƊ’Ä

Монадическая ссылка, принимающая список символов, который возвращает список списков целых чисел.
Как полная программа, она принимает строку и печатает представление указанного списка.

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

Как?

n€Ø[ḅ-µMịÄÐƤi€0ĖƊ’Ä - Link: list of characters    e.g. "[f[o]o!]"
  Ø[                - list of characters = ['[', ']']
n€                  - not equal? for €ach              [[0,1],[1,1],[0,1],[1,1],[1,0],[1,1],[1,1],[1,0]]
                    -     ...relating to the characters:  [     f     [     o     ]     o     !     ]
    ḅ-              - convert from base -1             [1,0,1,0,-1,0,0,-1]
                    -     ...i.e.: 1 where '['; -1 where ']'; and 0 elsewhere
      µ             - start a new monadic chain with that as the argument, say V
                Ɗ   - last 3 links as a monad (function of V):
          ÐƤ        -   for post-fixes:
         Ä          -     cumulative sum               [[1,1,2,2,1,1,1,0],[0,1,1,0,0,0,-1],[1,1,0,0,0,-1],[0,-1,-1,-1,-2],[-1,-1,-1,-2],[0,0,-1],[0,-1],-1]
            i€0     -   1st index of 0 in €ach (or 0)  [8,1,3,1,0,1,1,0]
               Ė    -   enumerate                      [[1,8],[2,1],[3,3],[4,1],[5,0],[6,1],[7,1],[8,0]]
       M            - maximal indices of V             [1,3]
        ị           - index into                       [[1,8],[3,3]]
                 ’  - decrement                        [[0,7],[2,2]]
                  Ä - cumulative sum (vectorises)      [[0,7],[2,4]]
Джонатан Аллан
источник
Я пытался использовать, œ¿и это родственники, но не смог найти решение. Это было ближе всего, что я получил.
Дилнан
Да, это может быть короче, но я управлял только одним жалким байтом , а не половиной байтов. Это все еще чувствует себя слишком долго. :(
Эрик Outgolfer
@EriktheOutgolfer и здесь было легко сохранить 1 байт
Джонатан Аллан
2

SWI-Пролог 254 байта

d([']'|T],I,[S|Z],M,R):-J is I+1,d(T,J,Z,[',','(',S,',',I,')'|M],R).
d(['['|T],I,S,M,R):-J is I+1,d(T,J,[I|S],M,R).
d([_|T],I,S,M,R):-J is I+1,d(T,J,S,M,R).
d(_,_,_,R,R).
m(X):-atom_chars(X,A),d(A,0,[],[']'],[_|R]),atomic_list_concat(['['|R],S),print(S).

Пример:

?- m('!^45sdfd[hello world[[djfut]%%357]sr[jf]s][srtdg][]').
'[(49,50),(42,48),(8,41),(36,39),(20,33),(21,27)]'
true 
Ян Дрозен
источник
1

C (gcc) , 87 байт

f(char*Z){for(char*z=Z,*q=z;*z;*z++-93||printf("%d,%d;",*--q,z-1-Z))*z-91||(*q++=z-Z);}

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

объяснение

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

f(char*Z){          // take mutable input string
 for(char*z=Z,*q=z; // copy pointer to current string index, current stack index
 *z;                // loop through the entire string
 *z++-93||          // if z == ']'
   printf("%d,%d;", // decrement stack pointer,
    *--q,z-1-Z))    //  write bracket pair position
  *z-91||           // if z == '['
   (*q++=z-Z);}     // write bracket position onto stack, increment stack pointer

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

Джонатан Фрех
источник
1

Желе , 20 байт

=©ⱮØ[_/aÄ$+®ŻĠḊẎ_2s2

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

Это имеет побочный эффект на регистр, надеюсь, что это может быть функцией.

Эрик Outgolfer
источник
Это многоразово, так что я думаю, что все в порядке. Ответы БФ обычно не оставляют ленту пустой
dylnan
1

Japt v1.4.5, 23 байта

;Ë¥']?ApENo):D¥'[©NpE
A

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

Распаковано и как это работает

;UmDE{D==']?ApENo):D=='[&&NpE
A

;                              Use alternative set of initial variables
                               A = [] is used here
 UmDE{                         Map over each char of input string...
      D==']?                     If the char is closing bracket...
            ApENo)                 Push the current index and N.pop() to A
                  :D=='[&&       Otherwise, if the char is opening bracket...
                          NpE      Push the current index to N

A     Output A

На выходе получается плоский массив [closing index, opening index]. Если обратный порядок нежелателен, добавление wв конце делает работу (+1 байт).

фонтанчик для питья
источник
1

Common Lisp, 95 байт

(lambda(u &aux s)(dotimes(p(length u))(case(elt u p)(#\[(push p s))(#\](print`(,(pop s),p))))))
Длинная версия
(defun par (string &aux stack)
  (dotimes (pos (length string))
    (case (char string pos)
      (#\[ (push pos stack))
      (#\] (print (list (pop stack) pos))))))
тесты
((lambda(u &aux s)(dotimes(p(length u))(case(elt u p)(#\[(push p s))(#\](print`(,(pop s),p))))))
 "!^45sdfd[hello world[[djfut]%%357]sr[jf]s][srtdg][] ")

печатает:

(21 27) 
(20 33) 
(36 39) 
(8 41) 
(42 48) 
(49 50)
CoreDump
источник
1

K (нгн / к) , 38 37 байт

{b@0N 2#,/=(|':+\-/a)b:&|/a:"[]"=\:x}

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

{ } функция с аргументом x

"[]"=\:xдва логических списка для случаев "["и"]"

a: назначить на a

|/ логическое «или» из двух списков

& где (при каких показателях) скобки?

b: назначить на b

-/список с 1 для "[", -1 для"]" и 0 везде

+\ частичные суммы

|': попарные максимумы (каждый элемент максируется с предыдущим, исходный элемент остается тем же)

Это представляет глубину скобки для каждого символа. Индексируем этоb (сопоставление индексирует) и получаем глубину скобок только для скобок.

= «group by» - словарь, отображающий глубину на индексы, при которых они встречаются

,/ объединить значения в словаре, игнорируя ключи

0N 2# преобразовать в матрицу из 2 столбцов (список списков)

b@индекс bс каждым элементом матрицы

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

Желе , 20 18 байт

Сохраненный 1 байт благодаря @ user202729 сообщил мне , что µ€это)

ẹⱮØ[µ³ḣċþØ[_/Ụị)Z’

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

После борьбы с этим в течение нескольких часов, чтобы заставить его работать ... Я честно удивлен, что это получилось так коротко :-)

объяснение

ẹⱮØ[µ³ḣċþØ[_/Ụị)Z’   Main link. Argument: s (string)  '[a[b]c[]][d]'
  Ø[                 Shortcut for the string "[]".
 Ɱ                   For each char in the "[]":
ẹ                      Find the indices of each occurrence in the input.
                     For our example, this gives the array [[1, 3, 7, 10], [5, 8, 9, 12]].

    µ                Begin a new monadic chain, with said array as its argument.
               )     For each of the two sub-arrays q within the array:
                         [[1, 3, 7, 10], [5, 8, 9, 12]]
     ³ḣ                For each item n in q, take the first n chars of the input.
                         [['[',     '[a[',      '[a[b]c[',   '[a[b]c[]]['],
                          ['[a[b]', '[a[b]c[]', '[a[b]c[]]', '[a[b]c[]][d]']]
        þØ[            For each string s in this, and each char c in "[]":
       ċ                 Count the occurrences of c in s.
                         [[[1, 0],  [2, 0],     [3, 1],      [4, 3]],
                          [[2, 1],  [3, 2],     [3, 3],      [4, 4]]]
           _/          Reduce each pair by subtraction. This is the number of open brackets
                         at each position.
                         [[1, 2, 2, 1], [1, 1, 0, 0]]
             U         Sort the indices by their values, using position as a tiebreaker.
                         [[1, 4, 2, 3], [3, 4, 1, 2]]
              ị        Index these values back into q.
                         [[1, 10, 3, 7], [9, 12, 5, 8]]

               )     Start a new monadic chain with the result as its argument.
                Z    Zip; transpose rows and columns.
                         [[1, 9], [10, 12], [3, 5], [7, 8]]
                 ’   Decrement; switch to 0-indexing.
                         [[0, 8], [9, 11], [2, 4], [6, 7]]
ETHproductions
источник
1

CJam , 25 байтов

0q{"[]"#"_ \p_p "S/=~)}/;

Удивительно конкурентоспособный - проигрывает только Джапту и Желе [ Править : и древесный уголь и Stax :(]

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

объяснение

0                          Push 0.
 q                         Push the input.
  {                   }/   For each character in the input:
   "[]"#                     Find index of this character in the string "[]" (or -1 if not found).
                   =         Use this index to choose
        "       "S/            one of the following snippets
                    ~          and execute it:
         _                       If it was 0 ('['), duplicate the number on the stack.
           \p_p                  If it was 1 (']'), print the current number and the one under it.
                                 If it was -1, do nothing.
                     )       Increment the number on top of the stack.
                        ;  Delete the number.
Esolanging Fruit
источник
0

Pyth ,  28  26 байтов

{I#.e,t+lhfSI/LT`Y+._>Qk\]

Тестирование.

На данный момент это дольше, чем подход Mnemonic , но я чувствую, что могу немного поиграть в эту игру, и к счастью, она также не использует Python-императивные структуры, такие как V. Начальная версия была 36 байтов и также имела многочисленные ошибки.

Как это работает

{I # .e, t + lhfSI / LT`Y + ._> Qk \] - Полная программа. Принимает цитируемую строку Q из STDIN.
   .e - Пронумерованная карта. k = индекс итерации, b = текущий элемент.
                     > Qk - Получить элементы Q с индексами, превышающими k.
                   ._ - Генерирует все префиксы этого.
                  + \] - и добавить «]» (для обработки некоторых крайних случаев).
          f - Фильтр по этому списку, с T = текущий элемент.
              L `Y - для каждого символа в str ([])," [] "...
             / T - ... Подсчитать вхождения этого в T.
           SI - И проверьте, сортируются ли значения все чаще.
         ч - зав. Получить первый элемент.
       + l - Получить длину этого + k.
      т - уменьшение (на 1).
     - и соединить это значение с k. Возвращает [i, k] где i
                             индекс соответствующего], а k - индекс [.
  # - Отфильтровать этот список по:
{I - пара инвариантна относительно дедупликации.
Мистер Xcoder
источник
{I#.e,t+lhfSI/LT`Y._>Q aaalmost работает для 22 байтов ...
Mr. Xcoder
0

Perl 5, 53 байта

say"$-[0] ".($+[0]-1)while s/\[[^][]*\]/1x length$&/e

Запустить как perl -nE '<above code snippet>'. Принимает ввод через стандартный ввод.

Как обычно, оптимальным Perl-решением проблемы является регулярное выражение. Мы пытаемся сопоставить любую пару скобок, в которой нет пар, используя довольно глупый класс символов ( s/\[[^][]*\]/.../). Если совпадение прошло успешно, мы заменяем сопоставленный текст цифрой1 снова и снова, чтобы мы случайно не этими скобками, и распечатали индексы совпадения. Промыть и повторить.

Сильвио Майоло
источник
0

Stax , 13 байт

é√p(l▓1½\á²ë(

Запустите и отладьте его

Он использует входной стек для отслеживания открытых пар скобок. Вот программа распакована, разархивирована и прокомментирована.

F       iterate over input characters
 .][I   get the index of the character in the string "[]", or -1
 ^|cv   skip the rest of this iteration if index was -1
 i~     push the current iteration index to the input stack
 C      skip the rest of this iteration if index was 0
 \      form a pair with the top two items from the input stack
 JP     join with space, and print

Запустите этот

рекурсивный
источник
0

Древесный уголь , 20 байтов

FLθ≡§θι[⊞υι]«I⊟υ,Iι⸿

Попробуйте онлайн! Ссылка на подробную версию кода. Объяснение:

FLθ

Цикл по неявному диапазону длины входной строки.

≡§θι

Включить текущий персонаж.

[⊞υι

Если это, [то нажмите текущий индекс в предопределенную переменную массива.

]«I⊟υ,Iι⸿

Если это, ]тогда извлеките последний индекс из переменной массива и напечатайте его, а текущий индекс разделите запятой и начните новую строку. Альтернативные выходные форматы, если это приемлемо, будут сохранять несколько байтов: ]I⟦⊟υιωсохраняются 2 байта, но каждый индекс печатается на отдельной строке, с двойным интервалом между парами индексов; ]I⟦⊟υιпросто печатает индексы на отдельных строках, что затрудняет их различение.

Нил
источник