USING: arrays assocs combinators fry grouping io kernel math math.order math.ranges namespaces prettyprint sequences sorting ; IN: braces-matcher : positions ( text char -- seq ) [ >array ] dip '[ swap _ = [ drop f ] unless ] map-index sift ; : prepare-run-count ( seq int -- pairs ) [ dup length ] dip zip ; : inc-positions ( text char -- pairs ) positions 1 prepare-run-count ; : dec-positions ( text char -- pairs ) positions -1 prepare-run-count ; : off? ( var -- ? ) get f = ; : on? ( var -- ? ) off? not ; : counter+ ( int -- current ) brace-count [ get + ] [ set ] [ get ] tri ; : reset-counter ( -- ) brace-count 0 swap set ; : counter-case ( pos count -- pos/f ) { { [ dup 1 = up? off? and ] [ drop up? on ] } ! came from 0 { [ dup 0 = ] [ drop up? off ] } { [ dup 0 < ] [ 2drop reset-counter f ] } [ 2drop f ] } cond ; : open-close-list ( text open-char close-char -- seq ) [ inc-positions ] [ dec-positions ] bi-curry* bi append sort-keys ; : matching-pairs ( text open-char close-char -- seq ) reset-counter open-close-list [ first2 counter+ counter-case ] map sift 2 >array ; ! testcase: ! [ { { 0 10 } { 14 16 } } ] [ "{ { } { } } } { }" CHAR: { CHAR: } matching-pairs ] unit-test