다우의 매듭과 그 교차점 표기법을 고려하여 대괄호 다항식을 계산하십시오.
더 많은 기술적 정의가 있지만,이 도전에서는 매듭 을 끈의 두 끝을 함께 연결하여 물리적으로 만든 것으로 생각하면 충분 합니다. 매듭은 3 차원으로 존재하기 때문에 종이에 그릴 때 매듭 다이어그램 을 사용합니다. 매듭 다이어그램 은 교차점이 정확히 두 줄, 한 줄과 한 줄입니다.
여기에서 (b)와 (c)는 같은 매듭의 다른 다이어그램입니다.
종이에 매듭 다이어그램을 어떻게 표현합니까? 우리 대부분은 렘브란트가 아니므 로 다음과 같이 작동하는 Dowker 표기법에 의존 합니다.
매듭에서 임의의 시작점을 지정하십시오. 다음 수정과, 매듭과 숫자 1부터 발생할 횡단을 따라 임의의 방향으로 이동 :이 짝수이고 현재려고하는 경우에 이상 짝수 그 교차, 무효화합니다. 마지막으로 1, 3, 5 등에 해당하는 짝수를 선택하십시오.
예를 들어 봅시다 :
이 매듭에서 우리는 시작 지점으로 “1”을 선택하고 오른쪽으로 이동했습니다. 때마다 우리가 간다 이상 또는 아래에 로프의 또 다른 조각, 우리는 교차점을 다음 자연수를 할당합니다. 예를 들어 [3,-12]
다이어그램에서 교차점에 해당하는 스트랜드에 해당하는 짝수를 무시합니다 . 따라서이 다이어그램은로 표시됩니다 [[1,6],[2,5],[3,-12],[-4,9],[7,8],[-10,11]]
. 1, 3, 5, 7 등의 친구를 나열하면 우리에게 제공 [6,-12,2,8,-4,-10]
됩니다.
여기 몇 가지주의 할 사항이 있습니다. 우선, Dowker 표기법은 임의의 시작점과 방향을 선택할 수 있으므로 주어진 매듭마다 고유 하지 않습니다 . 그러나, 표기법이 주어지면 매듭의 구조 (기술적으로는 주요 매듭 구성 요소의 반영까지)를 완전히 결정할 수 있습니다. 모든 Dowker 표기법이 가능한 매듭을 형성 할 수있는 것은 아니지만이 문제에서는 입력이 실제 매듭을 나타내는 것으로 가정 할 수 있습니다.
매듭의 반사 사이의 모호성을 피하고 문제를 쉽게 해결하기 위해 교차 표시 목록을 입력으로 제공합니다.
양의 교차에서 하단 선은 상단 선의 관점에서 왼쪽으로 이동합니다. 부정적인 교차점에서는 오른쪽으로갑니다. 매듭 주위를 이동하는 방향을 바꾸는 것 (즉, 오버 라인과 언더 라인을 반대로하는 것 )은 교차 표시를 바꾸지 않습니다. 이 예에서 교차 표시는 [-1,-1,-1,1,-1,1]
입니다. 그것들은 다우 커 표기법과 같은 순서로 주어집니다. 즉 1, 3, 5, 7 번의 교차점에 대한 것입니다.
A
D
⟨D⟩
위의 이미지에서 첫 번째 다이어그램의 윤곽이 교차 된 형태 는 두 번째 그림 ( 양수 평활화 ) 또는 세 번째 그림 ( 음수 평활화 ) 과 같이
A
A−1
아직 혼란스러워? 대괄호 다항식을 찾으려고 시도하는 예를 들어 보겠습니다
우리는 먼저 규칙 3을 사용합니다
우리는 새로운 매듭 모두에서 규칙 3을 다시 사용합니다.
이 4 개의 새로운 매듭을 첫 번째 방정식으로 대치합니다.
이 4에 규칙 1과 2를 적용하면
자, 이것은 우리에게 말해
매듭 이론에 대한 간략한 소개를 완료 한 것을 축하합니다!
입력
두 목록 :
-
다우 커 표기법 (예 🙂
[6,-12,2,8,-4,-10]
. 교차 번호는 1부터 시작해야합니다. 해당 홀수[1,3,5,7,...]
는 암시 적이며 입력으로 제공 해서는 안됩니다 . -
다우 커 표기법에 해당하는 교차점에 대한 부호 (
1
/-1
또는 원하는 경우0
/1
또는false
/true
또는'+'
/'-'
)[-1,-1,-1,1,-1,1]
.
한 쌍의 목록 대신에 한 쌍의 목록을 가질 수 있습니다. [[6,-1],[-12,-1],...
산출
A−2+5+A−A3
[[1,-2],[5,0],[1,1],[-1,3]]
−k…k
k∈N
[0,1,0,5,1,0,-1]
규칙
이것은 코드 골프 도전입니다. 표준 허점을 사용할 수 없으며 Dowker 표기법 또는 대괄호 다항식을 계산하는 도구가있는 라이브러리는 사용할 수 없습니다. (이러한 라이브러리를 포함하는 언어는 라이브러리 / 패키지가 아닌 여전히 사용할 수 있습니다).
테스트
// 4-tuples of [dowker_notation, crossing_signs, expected_result, description]
[
[[],[],[[1,0]],"unknot"],
[[2],[1],[[-1,3]],"unknot with a half-twist (positive crossing)"],
[[2],[-1],[[-1,-3]],"unknot with a half-twist (negative crossing)"],
[[2,4],[1,1],[[1,6]],"unknot with two half-twists (positive crossings)"],
[[4,6,2],[1,1,1],[[1,-7],[-1,-3],[-1,5]],"right-handed trefoil knot, 3_1"],
[[4,6,2,8],[-1,1,-1,1],[[1,-8],[-1,-4],[1,0],[-1,4],[1,8]],"figure-eight knot, 4_1"],
[[6,8,10,2,4],[-1,-1,-1,-1,-1],[[-1,-7],[-1,1],[1,5],[-1,9],[1,13]],"pentafoil knot, 5_1"],
[[6,8,10,4,2],[-1,-1,-1,-1,-1],[[-1,-11],[1,-7],[-2,-3],[1,1],[-1,5],[1,9]],"three-twist knot, 5_2"],
[[4,8,10,2,12,6],[1,1,-1,1,-1,-1],[[-1,-12],[2,-8],[-2,-4],[3,0],[-2,4],[2,8],[-1,12]],"6_3"],
[[4,6,2,10,12,8],[-1,-1,-1,-1,-1,-1],[[1,-10],[2,-2],[-2,2],[1,6],[-2,10],[1,14]],"granny knot (sum of two identical trefoils)"],
[[4,6,2,-10,-12,-8],[1,1,1,1,1,1],[[1,-14],[-2,-10],[1,-6],[-2,-2],[2,2],[1,10]],"square knot (sum of two mirrored trefoils)"],
[[6,-12,2,8,-4,-10],[-1,-1,-1,1,-1,1],[[1,-2],[1,6],[-1,10]],"example knot"]
]
외부 자원
도전에 필요하지는 않지만 관심이있는 경우 :
Dowker 표기법의 정의에서 실수를 잡은 @ChasBrown 및 @ H.Pwiz에게 감사드립니다.
답변
K (ngn / k) , 196 193 바이트
{!N::2*n:#x;{+/d,'x,'d:&:'-2!(|/n)-n:#:'x}(+/1-2*s){j::+,/y;,/(&0|2*x;(-1+#?{x[j]&:x@|j;x}/!N){-(d,x)+x,d:&4}/,1;&0|-2*x)}'(N!{(x,'|1+x;x+/:!2)}'((2*!n),'-1+x|-x)@'0 1=/:x>0)@'/:+~(y<0)=s:!n#2}
답변
Brain-Flak , 1316 바이트
(({})<({()<(({}<>))><>}){(({})[()()]<{([{}]({})<>({}<>))}{}(([({}<>)]<<>({}<>)<>((({})<<>{({}<>)<>}<>>))>)){({}<>)<>}<>{}(({}<{}(({}<{({}<>)<>}>))>))<>{({}<>)<>}>)}<>>){(({}){}()<({}<>)>)<>{}(({}){}<>)<>}<>{}{}(()){(<({}<({}<>)>)>)<>((){[()](<(({})<>){({}[({})]<>({}<>))}{}({}<>({}<{}<>{({}<>)<>}>)[()])<>({}({})[()])(([()]{()(<({}[({})]())>)}{})<{(<{}{}>)}{}><>{()((<({}()[({}<>)])<>>))}{}<{}{}>)((){[()]<({}()<({}<({}<<>({()<({}<>)<>>}<>){({}[()]<(({})<({()<({}<>)<>>})<>>)<>{({}[()]<<>({}<>)>)}{}>)}<>>)<>>)>)((){[()](<{}(({})<<>(({})<(<<>({}<<>({}<(()()){({}[()]<([{}]()<>)<>({}<<>{({}({})<>[({}<>)])}{}{}>){({}<>)<>}<>>)}{}>{})>)>)<>{}{({}<>)<>}<>([({}<>)]<((()))>)(())<>({}<>)<>{}({}[()]){<>({}<<>(()()){({}[()]<({}<<>{({}<>)<>}>){({}[({})]<>({}<>))}{}(({})<<>({}<>)<>([{}])>)>)}{}{}>)<>({}<(({})())>[()]<>)}{}({}<<>{}([{}]()<{({}<>)<>}>){({}({})<>[({}<>)])}{}{}>){({}<>)<>}<>{}{}{}>{})>)>)}{}){(<{}(({})<<>(({}{})<<>(<({}<>)>)<>{}{({}<>)<>}<>>(({}){}){})>)>)}>}{}){(<{}([{}]<({}<<>([{}]()<>)<>({}<<>{({}({})<>[({}<>)])}{}{}>){({}<>)<>}<>>({})({}){})>)>)}{}>)}{}){{}(([{}]){}<>{}{}<<>({}<>{}){([{}]({}()()<{}({}<>)(())<>>))}{}{}{}>{})(())<>{{}({}<>)(())<>}(<>)<>}{}}{}{}<>{}{}({}<{{}({}<>)(())<>}<>{{}{((<(())>))}{}}{}{{}({}<>)(())<>}>)<>{{}({}<(<()>)<>([]){{}({}<>)(())<>([])}{}>)<>{{}({}<>)<>}{}{}({}<>)<>}<>
난 아무것도 후회하지 않는다. 입력은 평평한 쌍의 목록입니다.
# Part 1: extract edges
(({})<
({()<(({}<>))><>}){
(({})[()()]<
{([{}]({})<>({}<>))}{}(([({}<>)]<<>({}<>)<>((({})<<>{({}<>)<>}<>>))>)){({}<>)<>}
<>{}(({}<{}(({}<{({}<>)<>}>))>))<>{({}<>)<>}
>)}
<>>){(({}){}()<({}<>)>)<>{}(({}){}<>)<>}<>
{}{}(())
# Part 2: Compute bracket polynomial
{
# Move degree/sign to other stack
(<({}<({}<>)>)>)<>
# If current shape has crossings:
((){[()](<
# Consider first currently listed edge in set
# Find the other edge leaving same crossing
(({})<>){({}[({})]<>({}<>))}{}
# Move to top of other stack
# Also check for twist
({}<>({}<{}<>{({}<>)<>}>)[()])
# Check for twist in current edge
<>({}({})[()])
(
# Remove current edge if twist
([()]{()(<({}[({})]())>)}{})<{(<{}{}>)}{}>
# Remove matching edge if twist
<>{()((<({}()[({}<>)])<>>))}{}<{}{}>
# Push 1 minus number of twists from current vertex.
)
# If number of twists is not 1:
((){[()]<
# While testing whether number of twists is 2:
({}()<
# Keep sign/degree on third stack:
({}<({}<
# Duplicate current configuration
<>({()<({}<>)<>>}<>){({}[()]<(({})<({()<({}<>)<>>})<>>)<>{({}[()]<<>({}<>)>)}{}>)}
# Push sign and degree on separate stacks
<>>)<>>)
# If number of twists is not 2: (i.e., no twists)
>)((){[()](<{}
# Make first copy of sign/degree
(({})<<>(({})<
# Make second copy of sign/degree
(<<>({}<<>({}<
# Do twice:
(()()){({}[()]<
# Prepare search for vertex leading into crossing on other side
([{}]()<>)
# While keeping destination on third stack:
<>({}<
# Search for matching edge
<>{({}({})<>[({}<>)])}{}
# Replace old destination
{}>)
# Move back to original stack
{({}<>)<>}<>
>)}{}
# Add orientation to degree
>{})>)>)
# Move duplicate to left stack
<>{}{({}<>)<>}<>
# Create "fake" edges from current crossing as termination conditions
([({}<>)]<((()))>)(())<>
# Create representation of "top" new edge
({}<>)<>{}({}[()])
# While didn't reach initial crossing again:
{
# Keep destination of new edge on third stack
<>({}<<>
# Do twice:
(()()){({}[()]<
# Search for crossing
({}<<>{({}<>)<>}>){({}[({})]<>({}<>))}{}
# Reverse orientation of crossing
(({})<<>({}<>)<>([{}])>)
>)}{}
# Remove extraneous search term
{}
# Push new destination for edge
>)
# Set up next edge
<>({}<(({})())>[()]<>)
}
# Get destination of last edge to link up
{}({}<
# Find edge headed toward original crossing
<>{}([{}]()<{({}<>)<>}>){({}({})<>[({}<>)])}
# Replace destination
{}{}>)
# Move everything to left stack
{({}<>)<>}
# Clean up temporary data
<>{}{}{}
# Push new sign/degree of negatively smoothed knot
>{})>)
# Else (two twists)
# i.e., crossing is the twist in unknot with one half-twist
>)}{}){(<{}
# Copy sign and degree+orientation
(({})<<>(({}{})<
# Move sign to left stack
<>(<({}<>)>)
# Move copy of configuration to left stack
<>{}{({}<>)<>}
# Add an additional 4*orientation to degree
<>>(({}){}){})>)
>)}
# Else (one twist)
>}{}){(<
# Invert sign and get degree
{}([{}]<({}<
# Search term for other edge leading to this crossing
<>([{}]()<>)
# With destination on third stack:
<>({}<
# Find matching edge
<>{({}({})<>[({}<>)])}{}
# Replace destination
{}>)
# Move stuff back to left stack
{({}<>)<>}<>
# Add 3*orientation to degree
>({})({}){})>)
>)}{}
# Else (no crossings)
>)}{}){{}
# If this came from the 2-twist case, undo splitting.
# If this came from an initial empty input, use implicit zeros to not join anything
# New sign = sign - 2 * next entry sign
(([{}]){}<>{}{}<
# New degree = average of both degrees
<>({}<>{})
# Find coefficient corresponding to degree
{([{}]({}()()<{}({}<>)(())<>>))}{}{}
# Add sign to coefficient
{}>{})
# Move rest of polynomial back to right stack
(())<>{{}({}<>)(())<>}
# Set up next configuration
(<>)<>
}{}
}{}{}<>{}
# Step 3: Put polynomial in correct form
# Keeping constant term:
{}({}<
# Move to other stack to get access to terms of highest absolute degree
{{}({}<>)(())<>}<>
# Remove outer zeros
{{}{((<(())>))}{}}
# Move back to right stack to get access to lower order terms
{}{{}({}<>)(())<>}
>)<>
# While terms remain:
{
# Move term with positive coefficient
{}({}<(<()>)<>([]){{}({}<>)(())<>([])}{}>)<>{{}({}<>)<>}{}
# Move term with negative coefficient
{}({}<>)<>
}<>