DaeSick
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
      • Invitee
    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Versions and GitHub Sync Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
Invitee
Publish Note

Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

Your note will be visible on your profile and discoverable by anyone.
Your note is now live.
This note is visible on your profile and discoverable online.
Everyone on the web can find and read all notes of this public team.
See published notes
Unpublish note
Please check the box to agree to the Community Guidelines.
View profile
Engagement control
Commenting
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
  • Everyone
Suggest edit
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
Emoji Reply
Enable
Import from Dropbox Google Drive Gist Clipboard
   owned this note    owned this note      
Published Linked with GitHub
Subscribed
  • Any changes
    Be notified of any changes
  • Mention me
    Be notified of mention me
  • Unsubscribe
Subscribe
# 실전 줄리아 첫걸음 주어진 문제의 힌트와 조건을 보고 지시하는 코드를 작성하라. 톡방에 답안을 제출하면 예시 답안을 받을 수 있고, 오프라인 스터디까지 예시 답안과 본인 답안을 비교하는 코드리뷰를 준비하라. <img src="https://i.imgur.com/bvNMs9L.png" width="200"> https://open.kakao.com/o/gIr6GsOd ## 1. 함수 ### 힌트 1: 재귀함수 > 자기 자신을 호출하는 함수. 재귀 함수의 'recursive'는 ‘반복되는’이라는 의미를 갖고 있습니다. 프로그래밍에서 재귀 함수는 어떤 일을 하는 함수를 만들었을 때, 그 함수 안에서 자기 자신을 다시 불러서 함수가 실행되도록 만든 것입니다. ```julia function pow2(n) if n ≤ 0 return 1 else return 2 * pow2(n-1) end end ``` 위의 `pow2` 함수는 2의 `n`승을 리턴하는 것을 재귀함수로 구현한 것이다.[^1] 그 실행결과는 다음과 같다: [^1]: https://docs.julialang.org/en/v1/manual/functions/ ```julia julia> pow2(0) 1 julia> pow2(1) 2 julia> pow2(2) 4 ``` ### 힌트 2: 삼항연산자 > 컴퓨터 프로그래밍에서 ?:는 몇몇 프로그래밍 언어들에서 기본적인 조건식을 위한 문법의 일부이다. 이는 일반적으로 조건 연산자, 인라인 조건문(inline if), 또는 삼항 조건문(ternary if)으로 불린다. a ? b : c는, a가 참이면 b로 평가되고, 그 밖에는 c로 평가된다. ```julia julia> isless6(n) = (n < 6 ? 1 : 0) isless6 (generic function with 1 method) julia> isless6(3) 1 julia> isless6(6) 0 julia> isless6(9) 0 ``` 위의 `isless6` 함수는 `n`이 6보다 작은지 판별하는 함수다.[^2] [^2]: https://docs.julialang.org/en/v1/manual/control-flow/#man-conditional-evaluation ### 1-1 기본과제 힌트 1을 참고해 주어진 자연수 `n` 에 대해 $n$ 번째 피보나치 수 $F_n$ 을 리턴하는 함수 `F(n)` 을 작성하라. 단, $F_1 = F_2 = 1$ 이다. ### 1-2 심화과제 힌트 2를 참고해 함수 `F`와 같은 기능을 하는 함수 `F1`을 단 한 줄로 구현하라. --- ## 2. 자료구조 ### 힌트 1: `push!()` <iframe width="560" height="315" src="https://www.youtube.com/embed/NFETSCJON2M" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> ```julia julia> x = [] Any[] julia> push!(x, 1) 1-element Vector{Any}: 1 julia> push!(x, 1) 2-element Vector{Any}: 1 1 julia> push!(x, 2); julia> push!(x, 3); julia> push!(x, 5) 5-element Vector{Any}: 1 1 2 3 5 ``` ### 힌트 2: `@time` ```julia julia> @time F1(40) 0.338643 seconds 102334155 ``` `@time` 매크로를 통해 코드의 특정 블럭에서 소요된 시간을 계산할 수 있다. 함수의 앞에 쓰이면 간단하게 그 함수의 평가에 쓰인 시간을 볼 수 있다. [^3] [^3]: https://docs.julialang.org/en/v1/manual/performance-tips/#Measure-performance-with-[@time](@ref)-and-pay-attention-to-memory-allocation ### 2-1 기본과제 `push!()`는 배열의 가장 마지막 자리에 주어진 원소를 추가하는 기능을 한다. 과제 1에서 구현한 `F` 혹은 `F1` 을 사용해서 자연수 `n`을 받아 $\left\{ F_k \right\}_{k=1}^{n}$ 을 반환하는 함수 `FA(n)`을 작성하라. ### 2-2 심화과제 > **동적 프로그래밍**이란, 특정 범위까지의 값을 구하기 위해서 그것과 다른 범위까지의 값을 이용하여 효율적으로 값을 구하는 알고리즘 설계 기법이다. `FA(n)`과 기능이 같지만 동적 프로그래밍을 응용하여 속도를 개선시킨 `FA2(n)`를 구현하고, 힌트 2에 따라 `FA(n)`과 `FA2(n)`의 성능을 비교하라. ## 3. 최적화 ### 힌트 1: `randn()`, `rand()` $$ Z \sim N (0,1) $$ 위와 같이 [표준정규분포](https://freshrimpsushi.github.io/posts/normal-distribution/)를 따르는 난수발생시키는 함수는 매트랩에서와 마찬가지로 `randn(n)`으로, 다음 예시처럼 길이가 `n`이고 각 원소가 표준정규분포를 따르는 벡터를 리턴한다. ```julia julia> z = randn(10) 10-element Vector{Float64}: -1.310782389377869 -1.9610344091115333 2.3925248401432198 ⋮ -0.3730980689762752 -0.6083035817749504 1.1110122368341526 ``` 이와 달리 [유니폼 분포](https://freshrimpsushi.github.io/posts/uniform-distribution/)를 따르게 하려면 `rand()` 함수를 사용하면 된다. ### 힌트 2: 브로드캐스팅 ```julia julia> z ^ 2 ERROR: LoadError: MethodError: no method matching ^(::Vector{Float64}, ::Int64) julia> z .^ 2 10-element Vector{Float64}: 1.7181504723031553 3.8456559537194206 5.7241751107023395 ⋮ 0.13920216907382538 0.3700332476002337 1.2343481903952271 ``` 각 원소를 제곱하는 법은 `.^`과 같이 점을 찍어서 제곱하면 된다. 일반적으로 벡터에는 거듭제곱이 정의되어 있지 않기 때문에 이와 같은 벡터 연산이 필요하다. ```julia julia> abs.(z) 10-element Vector{Float64}: 1.330112275601434 0.10482038445707342 0.6899064834783252 1.237258139091657 ⋮ 0.293113713408394 1.2104619980817963 0.19047088401274126 ``` 브로드캐스팅은 대부분의 함수에 적용할 수 있다. 가령 위의 경우에는 절대값을 구하는 함수 `abs()`의 뒤에 점을 찍어 `abs.()`로 각 원소의 절대값을 취한 배열을 얻었다. ### 힌트 3: 행렬연산 $$ \mathbf{y} := \begin{bmatrix} 7 \\ 6 \\ 7 \end{bmatrix} , X = \begin{bmatrix} 6 & 8 \\ 9 & 4 \\ 3 & 10 \end{bmatrix}, W = \begin{bmatrix} w_1 \\ w_2 \end{bmatrix}, \mathbf{b} = \begin{bmatrix} b_1 \\ b_2 \\ b_3 \end{bmatrix} $$ 위와 같은 행렬들에 대해 다음을 만족하는 $W$, $\mathbf{b}$ 를 계산하는 문제가 주어져 있다고 하자. $$ \mathbf{y} = X W + \mathbf{b} $$ 단, $W$ 의 원소는 $0$ 부터 $1$ 사이의 수다. 이는 임시로 난수 추출을 사용해 다음과 같이 줄리아 코드로 옮길 수 있다. [^4] [^4]: https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/#man-linalg ```julia julia> y = [7; 6; 7] 3-element Vector{Int64}: 7 6 7 julia> X = [6 8 ; 9 4 ; 3 10] 3×2 Matrix{Int64}: 6 8 9 4 3 10 julia> W = rand(2) 2-element Vector{Float64}: 0.5562849835210015 0.08542313648610178 julia> b = randn(3) 3-element Vector{Float64}: 1.0561929458402592 -1.2382386408346975 0.41263939042167586 julia> (X * W) + b 3-element Vector{Float64}: 5.077287938855083 4.110018756798723 2.935725705845698 ``` ### 3-1 기본과제 힌트 3의 $W, \mathbf{b}$ 를 찾는 것은 **$l_{1}$-손실함수** $\displaystyle L(W,\mathbf{b}) = \left\| \mathbf{y} - \left( X W + \mathbf{b} \right) \right\|_{1}$ 의 함숫값이 $0$ 이 되게끔 하는 것과 같다. 이 함수 `L(W,b)`를 줄리아 코드로 정의하라. ### 3-2 추가과제 `L(W,b)` 가 $1$ 보다 작아질 때까지 `W = rand(2)`과 `b = randn(3)`으로 난수추출을 반복해서 최적해 `W0` 와 `b0` 를 얻고, 최적화가 얼마나 빠르게 진행되는지 기록해서 확인하라. `W`와 `b` 는 더 낮은 값을 얻지 못했을 경우 업데이트 하지 않는다. 예를 들어, 최적화에 성공한 케이스 중 하나는 다음과 같다. `L_`은 손실함수값을 기록한 배열, `W0`, `b0`는 최적해다. ```julia julia> L_ 28-element Vector{Float64}: Inf 6.002334586049868 6.002334586049868 6.002334586049868 ⋮ 2.77570601868113 2.77570601868113 0.8999024343618416 julia> W0 2-element Vector{Float64}: 0.3104322220784894 0.5791067721039918 julia> b0 3-element Vector{Float64}: 0.6707623140708989 0.8189632218454262 0.9406085326804846 julia> X * W0 + b0 3-element Vector{Float64}: 7.166209823373769 5.929280308967798 7.6629729199558705 ``` 이 때 최적화에까지 걸린 반복은 27회고, 검산 결과도 `X * W0 + b0`가 `y`와 꽤 비슷한 것을 확인할 수 있다. 최적화 과정을 시각화하면 다음과 같다. ![](https://i.imgur.com/1PAWBd7.png) 최적화를 기록한 `L_`은 증가하지 않는 함수의 개형을 보이면서, 대상함수값이 감소하지 않은 경우 그 전의 대상함수값을 기록하고 있다. 이 문제는 반드시 함수형으로 구현할 필요는 없다. ## 4. 일급객체 > 컴퓨터 프로그래밍 언어 디자인에서, 일급 객체(영어: first-class object)란 다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체를 가리킨다. 보통 함수에 매개변수로 넘기기, 수정하기, 변수에 대입하기와 같은 연산을 지원할 때 일급 객체라고 한다. ### 힌트 1: 수렴성 피보나치 수열에 역수를 취한 $\left\{ F_n^{-1} \right\}$ 는 $n \to \infty$ 일 때 $0$ 으로 수렴하는데, 이 수렴성을 프로그래밍에서는 보통 **특정 임계치**^Threshold^ 아래로 떨어지는지로 판별하곤 한다. ```julia julia> n = 1 1 julia> while true if (1/F(n)) < 0.001 break else n += 1 end end julia> n 17 ``` 이 예시에서는 오차 $\varepsilon = 10^{-3}$ 를 허용했을 때 $n = 17$ 에서 수렴함을 보였다. 한편 이 경우 어디로 수렴하는지가 정확해서 참값과의 비교가 가능했지만, 그렇지 않은 경우에는 그 반복에서의 항과 현재의 항의 차를 비교하는 식으로 수렴성을 판단한다. ### 힌트 2: 범함수^Functional^ 줄리아에서는 함수가 일급객체다. 다시 말해, 함수 자체가 인풋이나 아웃풋이 될 수도 있다. 가령 함수의 덧셈 $h = f + g$ 는 다음과 같이 구현할 수 있다. ```julia julia> h(f,g,x) = f(x) + g(x) h (generic function with 1 method) julia> h(sin,cos,π/4) 1.414213562373095 ``` ### 4-1 기본과제 $\varepsilon = 10^{-3}$ 이하의 오차를 허용한다. 미분가능한 함수 $f : \mathbb{R} \to \mathbb{R}$ 의 $x \in \mathbb{R}$ 에서의 미분계수를 구하는 함수 $D(f,x)=$`D(f,x)` 를 구현하라. ### 4-2 추가과제 $\varepsilon = 10^{-3}$ 이하의 오차를 허용한다. 적분가능한 함수 $f : \mathbb{R} \to \mathbb{R}$ 의 $[a,b] \subset \mathbb{R}$ 에서의 정적분을 구하는 함수 $I(f,a,b)=$`I(f,a,b)` 를 구현하라. ## 5. 소인수분해 ### 힌트 1: 나눗셈 ```julia julia> 7 ÷ 2 3 julia> 7 % 2 1 julia> 7 / 2 3.5 ``` 줄리아에서 정수의 나눗셈에는 몫 `÷`, 나머지 `%`가 쓰이며, `/`는 실수의 나눗셈을 수행한다. 일반적인 줄리아 코드 편집기에서 `÷`는 텍코드처럼 `\div`를 입력하고 탭(Tab)을 누르면 입력할 수 있다. ### 힌트 2: 배열의 합병과 2차원 배열 ``` julia> [[2,3,5] ; [7,11]] 5-element Vector{Int64}: 2 3 5 7 11 julia> [[2,3,5] , [7,11]] 2-element Vector{Vector{Int64}}: [2, 3, 5] [7, 11] ``` 위 예시는 두 개의 배열을 묶은 배열에 세미콜론 `;`과 쉼표 `,`를 썼을 때 어떤 차이가 있는지를 보여주고 있다. - 세미콜론 `;`은 두 배열을 이어준다. 그 배열들이 1차원 배열이라면, 그 결과도 1차원 배열이다. - 쉼표 `,`는 배열의 배열을 만들어준다. 그 배열들이 1차원 배열일 때, 그 결과를 **2차원 배열**이라 한다. ### 힌트 3: 튜플 ``` julia> function pm(a,b) return (a+b), (a-b) end pm (generic function with 1 method) julia> c,d = pm(3,2) (5, 1) julia> c 5 julia> d 1 ``` 줄리아에서의 튜플은 파이썬과 유사하게 괄호로 묶는 것만으로 사용할 수 있다. 튜플을 대입할 때 여러 변수를 사용하면 순서대로 튜플 내부의 원소를 참조하게 된다. ### 5-1 기본과제 다음과 같이 자연수 `n`의 소인수분해를 배열로 리턴하는 함수 `factorize`를 구현하라. ```julia julia> factorize(12) 3-element Vector{Any}: 2 3 2 ``` ### 5-2 심화과제 현재까지도 전세계에서 사용되고 있는 [RSA 공개 키 암호체계](https://freshrimpsushi.github.io/posts/proof-of-rsa-public-key-cryptosystem/)는 [소인수분해 문제의 어려움](https://freshrimpsushi.github.io/posts/factorization/)에 기반하고 있다. 아직 소인수분해는 NP문제지만, 이론적으로는 양자 컴퓨터를 이용해 다항시간 내에 소인수분해를 끝낼 수 있는 **쇼어 알고리즘**이 제안된 바 있다. ![](https://i.imgur.com/uR5BZVK.gif) 효율적이지는 않지만, **에라토스테네스의 체**는 주어진 자연수 이하의 모든 자연수에 대해 소인수분해를 얻는 알고리즘이다. 위 움짤이 묘사하듯 작은 소수부터 그 배수들를 지워나가다보면 결과적으로 모든 소수를 얻게 된다. 다음과 같이 주어진 자연수 $n=$`n` 에 대해 $n$ 이하의 모든 자연수에 대한 소인수분해와 모든 소수를 튜플로 리턴하는 함수 `eratosthenes(n)`를 구현하라. ```julia julia> F, P = eratosthenes(20); julia> F 20-element Vector{Vector{Int64}}: [1] [2] [3] [2, 2] [5] [2, 3] ⋮ [3, 5] [2, 2, 2, 2] [17] [2, 3, 3] [19] [2, 2, 5] julia> P 8-element Vector{Int64}: 2 3 5 7 11 13 17 19 ``` #### 모범답안 ```julia= function sloweratosthenes(n) factorized = factorize.(1:n) primes = findall(length.(factorized) .== 1) push!(factorized[1], 1) return factorized, primes end ``` ### 5-3 도전과제 10만번째까지의 소수를 1초 이내로 계산하는 `eratosthenes`를 구현하라. ``` julia> @time F, P = eratosthenes(100000); 0.113450 seconds (100.02 k allocations: 10.489 MiB) julia> F 100000-element Vector{Vector{Int64}}: [1] [2] [3] ⋮ [3, 3, 41, 271] [2, 2, 2, 2, 2, 5, 5, 5, 5, 5] julia> P 9592-element Vector{Int64}: 2 3 5 ⋮ 99989 99991 ``` ## 6. 클라인 사원군 ### 힌트 1: 구조체 > ![](https://i.imgur.com/yk7xdNm.png) > > $V = \left\{ e, a, b, c \right\}$ 과 이항연산 $\cdot$ 에 대해, $\left< V , \ \cdot \ \right>$ 을 **클라인 사원군**<sup>Klein 4-group</sup>이라고 한다. 클라인 사원군은 순환군(Cyclic Group)이 아닌 유한 군 중에서 가장 원소가 적은 군으로, 아벨군(Abelian Group)이면서 원소가 4개인 단 두가지 그룹 중 하나기도 하다. ```julia struct Klein explicit::Char end e = Klein('e'); 가 = Klein('e') a = Klein('a'); 나 = Klein('a') b = Klein('b'); 다 = Klein('b') c = Klein('c'); 라 = Klein('c') ``` > C/C++ 프로그래밍 언어에서 구조화 된 데이터를 처리할 때 struct를 사용하는데 이를 구조체라고 한다. 구조화되었다는 말은 의미가 연결되어 한 덩어리로 처리하는 방식을 말한다. 줄리아는 파이썬에서 많은 영향을 받았으나 클래스 대신 스트럭쳐를 택했다. 이 **구조체**는 줄리아가 C로부터 가장 큰 영향을 받은 요소 중 하나로, [강한 타입 언어](https://freshrimpsushi.github.io/posts/type-in-programming/)인 줄리아에 숙련되기 위해서 필수적으로 알아야 하는 개념이다. 위 예시에서 변수들은 캐릭터 `e,a,b,c` 중 하나를 가지며 이들의 차이가 곧 클라인 사원군 내에서의 차이가 된다. 관습적으로 타입의 첫글자는 대문자를 사용하므로, 우리도 `klein`이 아닌 `Klein`을 사용했다. ``` julia> 가.explicit 'e': ASCII/Unicode U+0065 (category Ll: Letter, lowercase) ``` 변수 `x`에 어떤 원소가 할당되었는지는 R을 제외한 대부분의 프로그래밍 언어가 그러하듯 `x.explicit` 와 같이 `explicit` 필드에 `.`을 찍어서 접근할 수 있다. ```julia islegal(x::Klein) = x.explicit ∈ ['e','a','b','c'] ``` 새로운 타입이 생겼으니 새로운 함수를 정의해보자. ``` julia> islegal(e) true julia> islegal(b) true julia> islegal(가) true julia> d = Klein('d') Klein('d') julia> islegal(d) false ``` 실제 변수의 명명이 어떠하든 클라인 사원군이라면 $(V, \cdot)$ 과 동형(Isomorphic)할 것이다. 위 함수 `islegal`은 `Klein`을 받아 `e,a,b,c` 중 하나인지 아닌지를 체크해주는 함수로, 변수 이름이 `e`든 `가`든 상관 없이 `true`를 반환 했으나 그에 대응되는 `explicit`이 `d`인 경우 거짓을 리턴했다. ### 힌트 2: 오버로딩 파이썬에서는 `+` 연산으로 문자열을 이을 수 있고, `*` 연산으로 문자열을 반복할 수 있다. 반면 줄리아에서는 `*`으로 문자열을 잇고 `^`으로 문자열을 반복한다. 덧셈이 곱셈으로 바뀌었을 뿐 찰떡같이 맞아떨어지고, 사실 [`*`는 수학적으로 나름 이유가 있는 노테이션](https://freshrimpsushi.github.io/posts/how-to-concatenate-strings-in-julia)이다. ``` julia> "foo" * "bar" "foobar" julia> "foo" + "bar" ERROR: LoadError: MethodError: no method matching +(::String, ::String) ``` 위 결과를 보면 `"foo" + "bar"`는 `MethodError`를 레이즈했다. 이는 이항연산 `+`이 문자열에 대해 정의되어있지 않기 때문이다. 실용성과 별개로, 여전히 파이썬에서와 같이 `+`로 문자열을 잇고 싶다면 문자열에 대해 확장된 `+`을 오버로딩하면 된다. > **오버로딩(Overloading)**: 같은 이름의 메서드 여러개를 가지면서 매개변수의 유형과 개수가 다르도록 하는 기술[^5] 큰 프로젝트일수록 네임 스페이스(Name Space)를 꼼꼼하게 신경쓰는 편이 좋지만, 실제 구현과 관계없이 메소드의 특정한 이름이 특정한 기능을 암시하는 것은 매우 중요하고 큰 편리함을 가져다줄 수 있다. [^5]: https://private.tistory.com/25 ```julia import Base.+ function +(x::String, y::String) return y * x end ``` 가령 위의 함수는 `+`로 두 문자열을 잇되, 앞뒤를 바꿔주는 식으로 오버로딩했다. 결과는 다음과 같다. ``` julia> "foo" + "bar" "barfoo" ``` ### 6-1 기초과제 다음과 같이 변수명에 관계 없이 클라인 사원군의 **항등원**인지 아닌지를 체크하는 함수를 구현하라. ``` julia> isidentity(e) true julia> isidentity(a) false julia> isidentity(가) true julia> isidentity(다) false ``` ### 6-2 추가과제 ``` julia> inv(4) 0.25 julia> inv(a) ERROR: LoadError: MethodError: no method matching inv(::Klein) ``` 줄리아에서 원래 `inv`는 역수를 반환해주는 함수다. 이를 클라인 사원군에 대해 확장하라. ``` julia> inv(e) Klein('e') ``` 다시 말해, 클라인 역원군의 원소를 받아서 그 **역원**을 반환하는 함수를 `inv` 이름 그대로 작성하라. ### 6-3 도전과제 연산 `*`에 대해 클라인 사원군을 구현하라. 다음과 같은 연산이 네이티브하게 이루어지길 원한다. ``` julia> a * b Klein('c') julia> c * b Klein('a') julia> [e * x for x in [a,b,c]] 3-element Vector{Klein}: Klein('a') Klein('b') Klein('c') julia> 라 * a Klein('b') ``` ## 모범답안 ### 1. 함수 #### 1-1 ```julia= function F(n) if n ≤ 2 return 1 else return F(n-1) + F(n-2) end end ``` #### 1-2 ```julia= F1(n) = (n ≤ 2 ? 1 : F1(n-1) + F1(n-2)) ``` ### 2. 자료구조 #### 2-1 ```julia= F1(n) = (n ≤ 2 ? 1 : F1(n-1) + F1(n-2)) function FA(n) y = [] for k in 1:n push!(y, F1(k)) end return y end FA(7) ``` #### 2-2 ```julia= function FA2(n) result = Int64[] for k ∈ 1:n if k ≤ 2 push!(result, 1) else push!(result, result[k-1] + result[k-2]) end end return result end FA2(10) ``` ### 3. 최적화 #### 3-1 ```julia= L(W,b) = sum(abs.(y .- ((X * W) .+ b))) ``` #### 3-2 ```julia= W0 = rand(2) b0 = rand(3) L_ = [Inf] while L_[end] ≥ 1 W0 = rand(2) b0 = randn(3) L0 = L(W0,b0) if L0 < L_[end] push!(L_, L0) else push!(L_, L_[end]) end end X * W0 + b0 using Plots plot(L_, label = "Loss") ``` ### 4. 일급객체 #### 4-1 ```julia= f(x) = x^2 + 4x + 4 function D(f,x) h = 1 df = Inf while abs(df - ((f(x+h)-f(x)) / h)) > 1e-3 df = ((f(x+h)-f(x)) / h) h /= 2 end return df end D(f,3) ``` #### 4-2 ```julia= f(x) = x^2 + 4x + 4 function I(f,a,b) h = b-a ∫fdx = Inf while abs(∫fdx - sum(f.(a:h:b) .* h)) > 1e-3 ∫fdx = sum(f.(a:h:b) .* h) h /= 2 end return ∫fdx end I(f,0,3) ``` --> ### 5. 소인수분해 #### 5-1 ```julia= function factorize(n) factors = [] while n > 1 for k in 2:n if n % k == 0 n ÷= k push!(factors, k) end end end return factors end ``` #### 5-3 ```julia= function eratosthenes(n::Integer) if n == 1 return [[1]], Nothing end if n == 2 return [[1], [2]], [2] end primes = [2] factorized = [[1], [2]] for k ∈ 3:n m = k for p ∈ primes if m % p == 0 m ÷= p temp = [p; factorized[m]] push!(factorized, temp) break end end if length(factorized) != k push!(primes, k) push!(factorized, [k]) end end return factorized, primes end F, P = eratosthenes(20) F P @time F, P = eratosthenes(100000); F P ``` ### 6. 클라인 사원군 #### 6-1 ```julia= isidentity(x::Klein) = x.explicit == 'e' ``` #### 6-2 ```julia= inv(x::Klein) = x ``` #### 6-3 ```julia= hardtable = [e a b c a e c b b c e a c b a e] import Base.* function *(x::Klein, y::Klein) i = (1:4)[x.explicit .== ['e','a','b','c']] j = (1:4)[y.explicit .== ['e','a','b','c']] return first(hardtable[i,j]) end ``` #### 김규엽님의 풀이 ```julia= import Base.* function *(x::Klein, y::Klein) if islegal(x) if isidentity(x) return y elseif isidentity(y) return x else return setdiff([Klein('a'), Klein('b'), Klein('c')], [x, y]) end else @error "inv(x::Kelin) 사용 시, 클라인 사원군에 속하는 원소를 입력해주십시오." end end ``` #### 권기웅님의 풀이 ```julia= import Base.* function *(x::Klein, y::Klein) # identity if x == Klein('e') return y elseif y == Klein('e') return x # otherwise elseif x == Klein('a') if y == Klein('a') return Klein('e') elseif y == Klein('b') return Klein('c') elseif y == Klein('c') return Klein('b') end elseif x == Klein('b') if y == Klein('a') return Klein('c') elseif y == Klein('b') return Klein('e') elseif y == Klein('c') return Klein('a') end elseif x == Klein('c') if y == Klein('a') return Klein('b') elseif y == Klein('b') return Klein('a') elseif y== Klein('c') return Klein('e') end end end import Base.inv function inv(x::Klein) for element ∈ ['e', 'a', 'b', 'c'] y = Klein(element) if x * y == Klein('e') return y end end end ``` -->

Import from clipboard

Paste your markdown or webpage here...

Advanced permission required

Your current role can only read. Ask the system administrator to acquire write and comment permission.

This team is disabled

Sorry, this team is disabled. You can't edit this note.

This note is locked

Sorry, only owner can edit this note.

Reach the limit

Sorry, you've reached the max length this note can be.
Please reduce the content or divide it to more notes, thank you!

Import from Gist

Import from Snippet

or

Export to Snippet

Are you sure?

Do you really want to delete this note?
All users will lose their connection.

Create a note from template

Create a note from template

Oops...
This template has been removed or transferred.
Upgrade
All
  • All
  • Team
No template.

Create a template

Upgrade

Delete template

Do you really want to delete this template?
Turn this template into a regular note and keep its content, versions, and comments.

This page need refresh

You have an incompatible client version.
Refresh to update.
New version available!
See releases notes here
Refresh to enjoy new features.
Your user state has changed.
Refresh to load new user state.

Sign in

Forgot password

or

By clicking below, you agree to our terms of service.

Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
Wallet ( )
Connect another wallet

New to HackMD? Sign up

Help

  • English
  • 中文
  • Français
  • Deutsch
  • 日本語
  • Español
  • Català
  • Ελληνικά
  • Português
  • italiano
  • Türkçe
  • Русский
  • Nederlands
  • hrvatski jezik
  • język polski
  • Українська
  • हिन्दी
  • svenska
  • Esperanto
  • dansk

Documents

Help & Tutorial

How to use Book mode

Slide Example

API Docs

Edit in VSCode

Install browser extension

Contacts

Feedback

Discord

Send us email

Resources

Releases

Pricing

Blog

Policy

Terms

Privacy

Cheatsheet

Syntax Example Reference
# Header Header 基本排版
- Unordered List
  • Unordered List
1. Ordered List
  1. Ordered List
- [ ] Todo List
  • Todo List
> Blockquote
Blockquote
**Bold font** Bold font
*Italics font* Italics font
~~Strikethrough~~ Strikethrough
19^th^ 19th
H~2~O H2O
++Inserted text++ Inserted text
==Marked text== Marked text
[link text](https:// "title") Link
![image alt](https:// "title") Image
`Code` Code 在筆記中貼入程式碼
```javascript
var i = 0;
```
var i = 0;
:smile: :smile: Emoji list
{%youtube youtube_id %} Externals
$L^aT_eX$ LaTeX
:::info
This is a alert area.
:::

This is a alert area.

Versions and GitHub Sync
Get Full History Access

  • Edit version name
  • Delete

revision author avatar     named on  

More Less

Note content is identical to the latest version.
Compare
    Choose a version
    No search result
    Version not found
Sign in to link this note to GitHub
Learn more
This note is not linked with GitHub
 

Feedback

Submission failed, please try again

Thanks for your support.

On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

Please give us some advice and help us improve HackMD.

 

Thanks for your feedback

Remove version name

Do you want to remove this version name and description?

Transfer ownership

Transfer to
    Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

      Link with GitHub

      Please authorize HackMD on GitHub
      • Please sign in to GitHub and install the HackMD app on your GitHub repo.
      • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
      Learn more  Sign in to GitHub

      Push the note to GitHub Push to GitHub Pull a file from GitHub

        Authorize again
       

      Choose which file to push to

      Select repo
      Refresh Authorize more repos
      Select branch
      Select file
      Select branch
      Choose version(s) to push
      • Save a new version and push
      • Choose from existing versions
      Include title and tags
      Available push count

      Pull from GitHub

       
      File from GitHub
      File from HackMD

      GitHub Link Settings

      File linked

      Linked by
      File path
      Last synced branch
      Available push count

      Danger Zone

      Unlink
      You will no longer receive notification when GitHub file changes after unlink.

      Syncing

      Push failed

      Push successfully