def sum_if_3(k, m):
    if (m % 3 == 0) or (str(m).endswith('3')):
        return k + m
    else:
        return k

"""
Explanation: 흐름 제어: 조건문과 반복문(루프) 활용
요약


조건문 활용

if문: 불리언 값을 이용하여 조건을 제시하는 방법



반복문(루프) 활용


while 반복문(루프): 특정 조건이 만족되는 동안 동일한 과정을 반복하는 방법


for 반복문(루프): 특정 구간 내에서 동일한 과정을 반복하는 방법.

range 함수의 활용





최종 목표


두 정수의 최대공약수를 구하는 함수: gcd()
gcd(6, 8) = 2
gcd(14, 21) = 3


자연수 n이 주어졌을 때, 1부터 n까지의 자연수 중에서 3의 배수이거나 숫자 3을 포함하는
숫자들의 합을 구하는 함수 sum_of_3s() 구현하기:
sum_of_3s(10) = 3 + 6 + 9
sum_of_3s(15) = 3 + 6 + 9 + 12 + 13 + 15


조건문
어떤 일은 특정 조건 하에서만 할 수 있는 경우가 있다. 
예를 들어, 숫자 k가 3의 배수이거나 3으로 끝나는 경우에만 그 값을 다른 값에 더하라고 할 수 있다.
위 문장을 코드로 나타내려면 아래 요소들이 필요하다. 

이런저런 경우에만 __무엇무엇__을 해라.
숫자 k가 3의 배수이다.

숫자 k가 숫자 3으로 끝난다.


"이런저런 경우에만 무엇, 무엇을 해라"는 if문으로 나타낸다.
if 이런저런:
     무엇
     무엇


"숫자 k가 3의 배수이다"는 아래 수식으로 표현된다.
k % 3 == 0


"숫자 k가 숫자 3으로 끝난다"는 좀 더 어렵지만, 앞서 배운 문자열 메소드를 활용하면 된다.
str(k).endswith('3')


여기서 str() 함수는 숫자를 문자열로 형변환 시키는 함수이다. 
int() 또는 float() 함수와 반대의 일을 한다.
예제
두 개의 숫자 k, m이 주어졌을 때, 만약 m이
3의 배수이거나 3으로 끝나는 숫자일 경우에만
k와 m을 더하는 함수 sum_if_3()를 구현하라.
견본답안:
End of explanation
"""


sum_if_3(5, 18)

sum_if_3(4, 7)

"""
Explanation: 주의: else문은 if문에서 다루는 경우가 성립하지 않을 때 무슨 일을 해야할지를 정한다.
End of explanation
"""


if 'bc' in 'abcde':
    print("'bc'가 'abcde'의 부분문자열이다.")

"""
Explanation: 예제
두 개의 숫자 k, m이 주어졌을 때, 만약 m이
3의 배수이거나 숫자 3을 포함하는 경우에만
k와 m을 더하는 함수 sum_if_3s()를 구현하라.
이 문제를 풀기 위해서는 문자열에 특정 문자열이 부분문자열로 포함되어 있는지를 판단해야 하는데 
아래 예제와 같이 in 함수를 이용할 수 있다.
End of explanation
"""


def sum_if_3s(k, m):
    if (m % 3 == 0) or ('3' in str(m)):
        return k + m
    else:
        return k

sum_if_3s(2, 31)

sum_if_3s(3, 15)

sum_if_3s(13, 28)

"""
Explanation: 견본답안:
End of explanation
"""


num1 = 5
num2 = 10

if num1 < num2:
    print("num1이 num2 보다 작다.")
else:
    if num1 == num2:
        print("num1이 num2와 같다.")
    else:
        print("num1이 num2 보다 크다.")

"""
Explanation: 중첩 조건문과 일반화된 조건문
if ... else ... 문은 두 가지 경우를 처리할 때 사용한다.
반면에, 예를 들어, 크거나, 같거나, 작거나 등 세 가지 이상의 경우를 
처리하려면 if ... else ...문을 중첩해서 사용하거나
if ... elif ... elif ... else ... 처럼 다중 조건문을
사용할 수 있다.

중첩 조건문(중첩 if문) 활용 예제
End of explanation
"""


num1 = 5
num2 = 10

if num1 < num2:
    print("num1이 num2 보다 작다.")
elif num1 == num2:
    print("num1이 num2와 같다.")
else:
    print("num1이 num2 보다 크다.")

"""
Explanation: 다중 조건문(다중 if문) 활용 예제
End of explanation
"""


# 좀 더 세련된 print 함수를 사용하고자 한다.
from __future__ import print_function

number = 43
divisor = 7
answer = 0

# While 루프
while number > 0:
    number = number - divisor
    # 음수가 아니라면 빼주는 횟수를 1회 늘린다.
    if number > 0:
        answer += 1

# 이제 answer를 출력하면 된다.
print('몫은', answer, '이다')

"""
Explanation: 주의: if문의 중첩 정도는 임의로 복잡해질 수 있다. 
따라서 가능하면 일반화된 조건문을 사용하면 다루기가 보다 쉬워진다.
반복문(루프)
반복문(루프)은 동일한 코드를 반복해서 실행시킬 때 사용한다. 
루프를 만들기 위해 for문과 while문을 사용한다. 

for 반복문: 반복을 몇 번 할지 미리 알 수 있는 경우 사용
while 반복문: 특정 조건이 만족되는 동안 반복하고자 할 경우

여기서는 먼저 while 반복문을 살펴보고 이후에 for 반복문을 살펴본다.
while 반복문
while 반복문은 항상 아래 모양을 갖는다:
python
while 조건:
    본문코드1
    본문코드2
    ...
__조건__이 참이 되는 동안 본문코드들이 실행된다.
예제
정수들을 나누어 몫을 구하는 코드를 작성해보자.
몫을 어떻게 구현할까? 

먼저 몫이 어떤 의미인가를 알아야 한다.
그 다음에 그 의미를 구현하는 코드를 작성한다. 

어떤 정수 a를 다른 정수 b로 나누었을 때의 몫은 a에서 b를 몇 번 뺄 수 있는가와 동일한 의미를 갖는다.
즉, a에서 b를 반복해서 빼주는 과정이 필요하고 이 과정을 음수가 되지 않을 때까지만 반복해야 한다. 
예를 들어 43을 7로 나누었을 때의 몫은 다음과 같이 구할 수 있다.
End of explanation
"""


def gcd(a, b):
    if a < b:
        # 이 경우에는 a와 b의 값을 서로 바꾼다.
        a, b = b, a
    while b != 0:
        a, b = b, a % b
    return a

"""
Explanation: 'while' 루프를 작성할 때 조건문이 언젠가는 만족되지 않아서 더 이상 루프가 돌지 않도록 코드를 작성하는 것이 가장 중요하다. 
연습
두 정수의 최대공약수(gcd)를 리턴하는 함수를 구현하라.
힌트: 유클리드 호제법을 활용하라. 아래 사이트 참조: http://tibyte.kr/224
견본답안:
End of explanation
"""


gcd(6, 8)

gcd(14, 21)

"""
Explanation: 주의: 파이썬에서 두 변수에 할당된 값을 맞교환 하는 방법이 매우 간단하다.
하지만 C 또는 자바에서는 다르게 처리해야 한다. 
예를 들어, 아래와 같은 방식을 이용할 수 있다.
```C
int a = 3
int b = 5
int temp
temp = a
a = b
b = temp
```
End of explanation
"""


for char in "adam":
    print(char)

"""
Explanation: for 루프
while 반복문과는 달리 몇 번 반복되어야 하는지를 아는 경우 for 반복문을 사용할 수 있으며, 아래 형식을 따른다.
python
    for 항목변수 in 컬렉션 자료형 값:
        코드1
        코드2
        ...
컬렉션 자료형: 리스트, 튜플, 문자열, 어레이 등 여러 개의 값을 동시에 다룰 수 있는 자료형을 의미하며, 다음 시간에 보다 자세히 다룬다.
여기서는 문자열과 range() 함수를 이용하여 for 반복문을 사용하는 법을 익힌다.
문자열과 for 문
예제
아래 코드는 문자열에 포함된 문자 각각을 출력한다.
End of explanation
"""


a_word = 'aardvarks'
new_word = ''
for char in a_word:
    if char == 'a':
        new_word = new_word + 'A'
    else:
        new_word = new_word + char

print(new_word)

"""
Explanation: 연습
문자열에 있는 소문자 a를 대문자 A로 변경하여 새로운 문자열을 생성하는 코드를 작성하라.
예를 들어, "aardvarks"를 이용하여 "AArdvArks"를 생성하는 코드를 작성하라.
견본답안1:
End of explanation
"""


a_word = ' n o r t h w e s t e r n'

temp_word = ''
for char in a_word:
    if char != ' ':
        temp_word = temp_word + char
        
new_word = temp_word.title()

print(new_word)

"""
Explanation: 연습
아래 문자열
' n o r t h w e s t e r n'
을 이용하여 아래 문자열을 생성하는 코드를 구현하라:
'Northwestern'
End of explanation
"""


a_range = range(10)
print(a_range)

"""
Explanation: range() 함수와 for 문
range() 함수는 일정한 규칙에 따라 나열된 수열을 생성한다.
End of explanation
"""


type(a_range)

"""
Explanation: range() 함수의 리턴값의 자료형은 리스트이다.
주의: 파이썬3에서 range() 함수의 리턴값은 range라는 자료형이다. 
리스트와 거의 비슷하지만 용도가 좀 다르다는 정도만 기억하고 넘어가도 좋다.
End of explanation
"""


a_range_1 = range(3, 10)
a_range_1

a_range_2 = range(3, 10, 2)
a_range_2

"""
Explanation: range() 함수는 인자를 최대 세 개까지 받을 수 있다. 각 인자들의 역할은 슬라이싱에 사용되는 세 개의 인자들의 역할과 동일하다.

range([start,] stop [, step])
start의 경우 주어지지 않으면 0을 기본값으로 갖는다.
step의 경우 주어지지 않으면 1을 기본값으로 갖느다.
End of explanation
"""


from __future__ import print_function

for i in range(6):
    print(i,"의 제곱은", i ** 2, "이다.")

for i in range(0, 6, 2):
    print(i,"의 제곱은", i ** 2, "이다.")

"""
Explanation: range 함수는 for문에서 유용하게 활용된다.
End of explanation
"""


for i in range(5):
    print("다섯 번 출력합니다.")

"""
Explanation: 단순한 카운트 역할을 수행하는 용도로 range함수를 활용할 수도 있다.
즉, 어떤 일을 특정 횟수만큼 반복하고자 할 때 사용한다.
End of explanation
"""


a_word = 'hamster'

for i in range(7):
    print(a_word[i])

a_word = 'hamster'

for i in a_word:
    print(i)

"""
Explanation: range() 함수와 문자열 인덱싱을 활용하면 문자열에 대해 for문을 직접 활용하는 것과 동일한 일을 할 수 있다. 
예를 들어, 문자열의 길이와 range() 함수를 다음처럼 활용할 수 있다.
End of explanation
"""


for i in range(8):
    print(a_word[i])

"""
Explanation: 주의: 문자열의 길이가 range() 함수에 사용되는 인자보다 작으면 오류가 발생한다. 
이유는 문자열의 길이보다 긴 인덱스가 사용되기 때문이다.
End of explanation
"""


def sum_of_3s(n):
    sum = 0
    for i in range(1, n+1):
        if i % 3 == 0:
            sum = sum + i
        elif '3' in str(i):
            sum = sum + i
    return sum

sum_of_3s(10)

sum_of_3s(15)

"""
Explanation: 이제 아래 문제를 해결할 수 있다.
연습
자연수 n이 주어졌을 때, 1부터 n까지의 자연수 중에서 3의 배수이거나 숫자 3을 포함하는 숫자들의 합을 구하는 함수 sum_of_3s() 구현하기:
sum_of_3s(10) = 3 + 6 + 9 = 18
sum_of_3s(15) = 3 + 6 + 9 + 12 + 13 + 15 = 58
견본답안:
End of explanation
"""


