본문 바로가기

MATLAB/ㄴ 기타

Mastering Programming with MATLAB_Recursion(재귀)

1. Factorial

 

Factorial(재귀함수를 사용)

 


function f = rfact(n)
    if ~isscalar(n) || n ~= fix(n) || n < 0 % 입력되는 숫자가 스칼라인지, 분수가 아닌지, 음수가 아닌지를 확인
        error('non-negative integer scalar input expected');
    end
    if n == 0
        f = 1;
    else
        f = n * rfact(n-1);
    end
end


 

ex) rfact(5)

f : 1 → 2 → 6 → 24 → 120

 

 

* rfact에 대한 함수파일인 rfact.m을 만드려면, 파일명과 함수명이 동일해야 함.

 

 


Factorial (재귀함수를 사용하지 않음)

 


function f = ifact(n)
    if ~isscalar(n) || n ~= fix(n) || n < 0
        error('non-negative integer scalar input expected');
    end
    
    f = 1;
    for ii = 1:n
        f = f * ii;
    end
end

 

 

2. Sierpinsky 삼각형

 

Sierpinsky 삼각형

 


function sierpinski(depth)
    s = 1; c = [0;0]; % s = 삼각형 변의 길이 , c = 중심좌표
    clf; 
    axis([c(1)-s/2 , c(1)+s/2 , c(2)-s/2 , c(2)+s/2], 'equal');

    title(sprintf('Sierpinski Triangle with Depth =  %d', depth))
    hold on;
    sier(depth, s, c);
    hold off;
end

function sier(d, s, c)
    if d <= 0 % base case // 재귀의 깊이가 0 이하인 경우, 삼각형을 그림
        plot(c(1)-[s,0,-s,s]/2 , c(2)-[s,-s,s,s]*sqrt(3)/4 , 'k');
    else % recursive case
        s = s/2; % 삼각형의 변의 길이를 절반으로 나눔
        h = s*sqrt(3)/2; %높이
        sier( d-1, s, c - [s;h]/2  ); % 왼쪽 아래
        sier( d-1, s, c + [0;h]/2  ); % 중앙 위쪽
        sier( d-1, s, c + [s;-h]/2 ); % 오른쪽 아래
    end
end

 

 

조금 더 속도가 빠른 코드

 


function sierpinskiE(depth)
    s = 1; c = [0;0]; % s = length of side, c = center
    clf; axis([c(1)-s/2 , c(1)+s/2 , c(2)-s/2 , c(2)+s/2] , 'equal');
    title(sprintf('Sierpinski Triangle with Depth =  %d', depth))
    hold on;
    plot(1/2*[-1,0,1,-1],sqrt(3)/4*[-1,1,-1,-1],'r--'); % 윤곽선을 그리는 곳
    pts  = sier(depth, s, c, [ ]);
    plot(pts(1 , :) , pts(2 , :) , 'k-');
    hold off;
end

function pts  = sier(d, s, c, pts)
    if d <= 0 % base case
        pts = [pts, c + [[-s,0,s,-s,nan] / 2;  sqrt(3) * [-s,s,-s,-s,nan] / 4]] ; % 삼각형의 x값과 y값을 계산해 pts에 담음
    else % recursive case
        s = s/2; % cuts size in half
        h = s*sqrt(3)/2; % height
        pts = sier( d-1, s, c - [s;h]/2,  pts ); % bottom left
        pts = sier( d-1, s, c + [0;h]/2,  pts ); % top middle
        pts = sier( d-1, s, c + [s;-h]/2, pts ); % bottom right
    end
end


 

 

 

3. Greatest Common Divisor (최대공약수)

 


function d = rgcd(x,y)

    if (~isscalar(x) || ~isscalar(y) || ...
        x ~= fix(x) || y ~= fix(y) || ...
        x < 0 || y < 0)
        error('x and y must be non-negative integers');
    end

    a = max([x y]);
    b = min([x y]);
    
    if b == 0
        d = a;
    else
        d = rgcd(b,rem(a,b)); % a와 b의 최대공약수는 a를 b로 나눈 나머지와 b의 최대공약수이다
end

 

 

4. 나열된 숫자의 각 자릿수의 합 구하기

 


function total = digit_sum(input)

    if input == 0
        total = 0;
    else
        last_digit = rem(input, 10); % 마지막 자릿수: 입력된 숫자에서 10을 나눈 후 나머지
        remain_digit = fix(input/10); % 나머지 숫자: 입력된 숫자에서 10을 나눈 후 반올림
        total = last_digit + digit_sum(remain_digit); % 나머지 숫자를 digit_sum() 재귀함수를 이용하여 마지막 자릿수를 모두 구함
    end

end

 

 

 

5. 주어진 벡터에서 최댓값 찾기

 


function mx = recursive_max(v)

    n = length(v); % 벡터의 길이 확인
    if n == 1
        mx = v(1); % 벡터의 길이가 1이면 유일한 요소가 최댓값
    else
        first_element = v(1); % 벡터의 첫번째 요소와 나머지 요소를 분리
        rest_of_vector = v(2:end);
        
        max_rest = recursive_max(rest_of_vector); % 첫번째 요소와 나머지 요소의 최댓값을 비교해서 더 큰 값을 선택
        if first_element > max_rest
            mx = first_element;
        else
            mx = max_rest;
        end
    end

end

 

 

6. 주어진 벡터의 원소를 뒤집기

 


function w = reversal(v)
    n = length(v);
    if n <= 1 % 벡터의 길이가 1보다 작으면, 벡터를 그대로 반환
        w = v;
    else
        rest_of_vector = reversal(v(2:end)); % 첫번째 원소를 제외한 나머지부분에 대해 재귀호출
        w = [rest_of_vector, v(1)]; % 첫번째 원소를 뒤에 붙임
    end
end

 

ex) v = [1 2 3 4 5] 이면, 5 → 5 4 → 5 4 3 → 5 4 3 2 → 5 4 3 2 1 순으로 진행됨

 

 

7. 피보나치 

 


function fib_sequence = fibor(n)
    if n <= 1
        fib_sequence = 1; % n이 1 이하일 때, 1을 반환
    else
        prev_fib1 = fibor(n-1); % n-1번째 피보나치 수
        prev_fib2 = fibor(n-2); % n-2번째 피보나치 수
        fib_sequence = prev_fib1 + prev_fib2; % n번째 피보나치 수
    end
end


 

 

8. 회문(Palindrome)

 


function p = palindrome(text)
    if length(text) <= 1 % 만약 문자열이 1 이하인 경우, 회문이다.
        p = true;
    else
        first_char = text(1); % 문자열의 첫번째 문자와 마지막 문자 비교
        last_char = text(end);
        if first_char == last_char % 첫번째와 마지막이 같은경우, 나머지 문자열이 회문인지 확인
            middle_text = text(2:end-1); % 첫번째와 마지막을 제외한 문자열
            p = palindrome(middle_text);
        else
            p = false; % 첫번째 문자와 마지막 문자가 다르면 회문이 아님
        end
    end
end