- TI nspire
[TI-nspire] [Program] 순열(Permutation) - Heap's Algorithm (Recursive)
앞서 구현한 순열을 찾는 프로그램은 n^n 루프를 회전시켜야만 하는 비효율적인 프로그램이었습니다.
http://www.allcalc.org/7618
그래서 좀 더 나은 것을 찾아봤는데, 이게 가장 효율적이었습니다.
https://en.wikipedia.org/wiki/Heap%27s_algorithm
하지만 재귀호출방식이라서 잘 될까 의문이 들었습니다. 기본 알고리즘은 다음과 같습니다.
procedure generate(n : integer, A : array of any): if n = 1 then output(A) else for i := 0; i < n - 1; i += 1 do generate(n - 1, A) if n is even then swap(A[i], A[n-1]) else swap(A[0], A[n-1]) end if end for generate(n - 1, A) end if
배열[ ]이 0부터 시작하는 것을 주의하여 프로그램을 짜 봤는데...
|
Define perm_list(list,n)= Prgm : :k+1→k :© Disp "============" :© Disp "ⓐ N th trials = ",k,"---------------" : :Local f_i : If n=1 Then : Disp "★",list : Else : For f_i,1,n-1 :© Disp "ⓒ i=",f_i,", n-1=",n-1 : perm_list(list,n-1) : If mod(n,2)=0 Then : Disp "Before",list : Disp "Even n=",n,"↔",f_i : swap(list,f_i,n)→list : Disp "After ",list : Else : Disp "Before",list : Disp "Odd n=",n,"↔ 1" : swap(list,1,n)→list : Disp "After ",list : EndIf : EndFor : perm_list(list,n-1) : EndIf : :EndPrgm
|
★ {1,2,3,4} Before {1,2,3,4} Even n 2 ↔ 1 After {2,1,3,4} ★ {2,1,3,4} Before {1,2,3,4} Odd n 3 ↔ 1 After {3,2,1,4} ★ {3,2,1,4} Before {3,2,1,4} Even n 2 ↔ 1 After {2,3,1,4} ★ {2,3,1,4} Before {3,2,1,4} Odd n 3 ↔ 1 After {1,2,3,4} ★ {1,2,3,4} Before {1,2,3,4} Even n 2 ↔ 1 After {2,1,3,4} ★ {2,1,3,4} Before {1,2,3,4} Even n 4 ↔ 1 After {4,2,3,1}
(중간 생략)
★ {1,2,4,3} Before {2,1,4,3} Odd n 3 ↔ 1 After {4,1,2,3} ★ {4,1,2,3} Before {4,1,2,3} Even n 2 ↔ 1 After {1,4,2,3} ★ {1,4,2,3} |
결과에 자꾸 반복되는 조합이 생겨서 뭐가 문제인가 봤더니...
새로 찾은 (swap 후) 결과 list가 다음번에 유지되지 않고, 이전 호출 perm_list(list)로 돌아면서 새 list 대신 이전 호출때 입력받은 list 를 사용하는 것 같더라구요. (추정)
그래서 일단 list 를 프로그램의 인자로 사용하지 않고, 전역변수를 이용하도록 변경하였습니다.
Define LibPriv perm_heap(n)= Prgm : : Local f_i : If n=1 Then : count_k+1→count_k : Disp "#",count_k,heap_list : Else : For f_i,1,n-1 : perm_heap(n-1) : If mod(n,2)=0 Then : swap(heap_list,f_i,n)→heap_list : Else : swap(heap_list,1,n)→heap_list : EndIf : EndFor : perm_heap(n-1) : EndIf :EndPrgm |
0→count_k:{a,b,c,d}→heap_list perm_heap(dim(heap_list)) # 1 {a,b,c,d} # 2 {b,a,c,d} # 3 {c,a,b,d} # 4 {a,c,b,d} # 5 {b,c,a,d} # 6 {c,b,a,d} # 7 {d,b,a,c} # 8 {b,d,a,c} # 9 {a,d,b,c} # 10 {d,a,b,c} # 11 {b,a,d,c} # 12 {a,b,d,c} # 13 {a,c,d,b} # 14 {c,a,d,b} # 15 {d,a,c,b} # 16 {a,d,c,b} # 17 {c,d,a,b} # 18 {d,c,a,b} # 19 {d,c,b,a} # 20 {c,d,b,a} # 21 {b,d,c,a} # 22 {d,b,c,a} # 23 {c,b,d,a} # 24 {b,c,d,a} |
|
일단 답은 나왔습니다만, 인자 vs 전역변수 문제는 조금 더 연구를 해 보아야 할 것 같습니다.
세상의모든계산기 님의 최근 댓글
2번 사진 3개 사진 공통적으로 구석(corner) 에 증상이 있다는 특징이 있네요. 영상 찾아보니 이 가능성이 가장 높은 듯 합니다. https://www.youtube.com/watch?v=zxRBohepzwc ㄴ Liquid Crystal Leakage (액정 누설). ㄴ 손으로 밀어내니 주변으로 밀려나네요. 그래서 점으로 보이기도 하구요. 2025 10.29 500! 의 십진수 근사값 확인 500! = 1.22013682599111006870123878542304692625357434280319284219241358838 × 10^(1134) (참값, 울프람 알파) 2025 10.29 관련 라이브러리 https://allcalc.org/56263 sgn(x) 내장된 부호 함수(signum function)와 달리, 이 함수의 sgn(0)은 0을 반환합니다. 2025 10.29 라이브러리로 사용할 수 있습니다. (제작자 추천) 1. mylib 폴더에 넣기 2. Actions ➡️ library ➡️ refresh libraries 실행 하기 2025 10.29 ChatGPT-5 기호(÷, /, :) 자체는 의미적으로 같은 “나눗셈”을 뜻하지만, 문맥(사람이 쓰는 수학 vs 컴퓨터/프로그래밍)에 따라 해석 우선순위가 달라질 수 있습니다. 🔹 1️⃣ 전통 수학 표기 — ÷, /, : 수학 교과서, 논문, 일반 문서 등에서는 셋 다 의미적으로 “나누기”로 간주됩니다. 즉, 48÷2(9+3), 48/2(9+3), 48:2(9+3) 은 같은 의미로 받아들여야 합니다. 모두 사람의 수학 관행적 해석이 적용되어 48 ÷ 2 × (9+3) = 288 로 처리되죠. 즉, 기호가 바뀌어도 결과는 바뀌지 않습니다. 🔹 2️⃣ 컴퓨터·프로그래밍 문맥에서 / 사용 시 컴퓨터는 “생략된 곱셈(implicit multiplication)”을 따로 구분하지 못합니다. 따라서 다음 두 식은 완전히 다르게 인식됩니다. 표현 파이썬 등에서 해석 결과 48 / 2*(9+3) ((48 / 2) * (9+3)) 288 48 / 2(9+3) ❌ 문법 오류 (생략된 곱셈 인식 불가) — 즉, 컴퓨터 언어에서는 생략된 곱셈이 허용되지 않기 때문에, /는 반드시 명시적 *와 함께 써야 합니다. 🔹 3️⃣ “:” 기호의 경우 현대 수학에서는 “비율”을 나타내는 기호로 쓰입니다. a:b = \frac{a}{b} 따라서 (27 : 3(1+2)3) 같은 표현은 모호하거나 비표준적으로 간주됩니다. 대부분의 경우 계산기로는 입력 자체가 불가능합니다. ✅ 정리 기호 의미 결과 변화 주로 쓰이는 문맥 ÷ 나누기 없음 초중등 수학, 일반 표기 / 나누기 없음 (단, 프로그래밍에서는 생략 곱 불허) 수학/컴퓨터 : 비율 (또는 나누기 의미로 혼용) 보통 계산식에서는 사용 안 함 비, 비율 표기 🔹 결론 48 ÷ 2(9+3), 48/2(9+3), 48:2(9+3) 는 “수학적 의미”로는 동일하게 81로 해석됩니다. 하지만 프로그래밍이나 수식 파서(context) 에서는 /만 유효하고, 생략된 곱은 허용되지 않으며, :는 아예 다른 의미(비율)로 인식됩니다. 2025 10.28