서로소 집합(유니온 파인드 구조)은 여러 값을 겹치지 않는 그룹으로 나눠서 보관하고, "이 두 값이 같은 그룹에 있나요?"라는 질문 하나에 빠르게 답해 줘요. disjoint-sets 보캐불러리에 들어 있어요.
<disjoint-set>은 빈 구조를 만들어요. 값, 즉 애텀은 add-atom으로 하나씩 추가하거나 add-atoms로 시퀀스에서 한꺼번에 추가해요. 각 애텀은 처음에는 자기 혼자만의 그룹에 있어요.
<disjoint-set> ( -- disjoint-set )
add-atom ( atom disjoint-set -- )
add-atoms ( seq disjoint-set -- )
USING: disjoint-sets ;
<disjoint-set>
{ 1 2 3 } over add-atoms ! 1, 2 and 3 each in their own group
서로소 집합은 가변적이에요. add-atom, add-atoms, equate는 새로운 집합을 반환하는 대신 그 자리에서 내용을 바꿔요. 이 워드들이 서로소 집합을 스택에서 꺼내 쓴 뒤에도 그 집합을 다시 스택에 남겨 두고 싶을 때 keep이 유용해요.
equate는 두 애텀이 각각 속한 그룹을 하나로 합쳐요. 합치는 것은 추이적이에요. 두 애텀을 합친 다음 그중 하나를 세 번째 애텀과 합치면, 셋 모두 한 그룹에 들어가요.
equate ( atom1 atom2 disjoint-set -- )
각 그룹에는 기준이 되는 구성원이 하나 있는데, 그것이 그 그룹의 대표예요. representative는 그 대표를 반환하고, 두 애텀이 같은 그룹에 속하는 것은 두 애텀의 대표가 같을 때와 정확히 일치해요.
representative ( atom disjoint-set -- representative )
USING: disjoint-sets ;
<disjoint-set>
{ 1 2 3 } over add-atoms
1 2 pick equate
1 over representative . ! => 1
2 over representative . ! => 1 (same representative as 1)
3 over representative . ! => 3 (still on its own)
그룹이 어떤 애텀을 대표로 고르는지는 내부 구현의 세부 사항이에요. 특정 애텀이 대표로 선택되는지에 기대지 말고, 같은 그룹에 있는 두 애텀의 대표가 서로 같다는 점에만 기대해요.
동네 시 동호회가 새 시즌을 시작해요. 시인들이 동호회에 가입하고, 두 시인이 함께 시를 쓰면 그 둘은 같은 창작 모임에 속하게 돼요. 동호회는 누가 누구와 같은 모임에 속하는지 관리하고 싶어 하고, 여러분은 그것을 관리하는 단어들을 작성해 달라는 부탁을 받았어요.
서로소 집합이 딱 맞아요. 각 시인은 원소이고, 창작 모임은 그룹이에요.
new-club을 정의해요. 시인들의 시퀀스를 받아서, 모든 시인이 등록된 새로운 서로소 집합을 반환해요. 각 시인은 처음에는 자신만의 창작 모임에 속해 있어요.
{ "Keats" "Byron" "Dickinson" } new-club
! => a disjoint set holding the three poets
collaborate를 정의해요. 두 시인과 동호회를 받아서, 두 시인의 창작 모임을 합치고 동호회를 반환해요. 그래서 공동 작업을 차례로 기록할 수 있어요.
{ "Keats" "Byron" "Dickinson" } new-club
"Keats" "Byron" rot collaborate
! => the club, with Keats and Byron now in one circle
circle-of를 정의해요. 시인과 동호회를 받아서, 그 시인의 창작 모임의 대표를 반환해요. 같은 모임에 속한 두 시인은 항상 같은 대표를 알려줘요.
{ "Keats" "Byron" "Dickinson" } new-club
"Dickinson" swap circle-of
! => "Dickinson" (still in a circle of their own)
same-circle?을 정의해요. 두 시인과 동호회를 받아서, 두 시인이 같은 창작 모임에 속하면 t를, 그렇지 않으면 f를 반환해요. 내장 동등성 검사를 쓰는 대신 시인들의 대표를 비교해요.
{ "Keats" "Byron" "Dickinson" } new-club
"Keats" "Byron" rot collaborate
dup [ "Keats" "Byron" ] dip same-circle? . ! => t
[ "Keats" "Dickinson" ] dip same-circle? . ! => f
Exercism에 가입하고 Factor 트랙을 개념 47개연습 문제 163개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.