# SAI Season7 S+ Team6 "SuPLeme"
# 3rd week
# ====================================================================================== #
# Practical Problem
1) 3차원 공간에서 임의의 점 3개를 생성한다. 생성된 좌표들로 삼각형을 만들 수 있는지 판별하시오.
1-1) numpy의 random을 사용하여 3차원 공간에서 [-100, 100] 사이의 임의의 정수를 추출해 3좌표 a, b, c를 만드시오. [1]
import numpy as np
def generate_3dots():
p0 = np.random.randint(-100, 101, size = 3)
p1 = np.random.randint(-100, 101, size = 3)
p2 = np.random.randint(-100, 101, size = 3)
return p0, p1, p2
a, b, c = generate_3dots()
1-2) 위 추출된 3좌표로 삼각형을 만들 수 있는 지 확인하시오. [7]
불가능할 시 가능할 때까지 좌표를 랜덤하게 추출하시오.
이 후, 삼각형이 완성가능한 좌표를 생성할 때 출력하시오.
Hint) 3좌표 중 임의의 2점을 이어 선분을 벡터로 a,b로 만들었을 때, a = kb꼴로 나타나진다면, 삼각형을
이룰 수 없음. (단, k는 임의의 실수)
a-b, a-c를 계산한 후, x좌표, y좌표, z좌표가 모두 임의의 실수 k배로 꼴로 표현되는지 확인해보세요!
def l2_norm(v):
return np.sqrt(np.sum(v * v))
def is_triangle(p0, p1, p2):
v01 = np.subtract(p1, p0)
v02 = np.subtract(p2, p0)
if np.dot(v01, v02) != l2_norm(v01) * l2_norm(v02):
return True
else:
return False
# If there are two dots a and b, the vector which is from a to b is equal to (b - a).
# A: Three dots a, b, and c cannot make a triangle.
# B: Two vectors u and v such that u = b - a and v = c - a are parallel.
# C: The dot product of u and v is equal to the product of norms of them.
# D: The cross product of u and v is equal to zero.
# E: The one is the other's multiple(u = kv or v = ku).
# A ~ E are equivalent.
# We'd used C in the function 'is_triangle' to investigate if three dots can make a triangle.
# The function has a problem: cannot compute the product of the norms exactly because of the "Floating-point error".
# <Example>
# p0 = [0,0,0], p1 = [1,1,1], p2 = [2,2,2]
# v01 = [1,1,1], v02 = [2,2,2]
# np.dot(v01, vo2) = 6
# l2_norm(v01) * l2_norm(v02) = 5.9999999... (by Floating-point error)
# np.dot(v01, v02) != l2_norm(v01) * l2_norm(v02) => False
def is_triangle1(p0, p1, p2):
v01 = np.subtract(p1, p0)
v02 = np.subtract(p2, p0)
if np.array_equal(v01, np.zeros(3)):
return False
elif np.array_equal(v02, np.zeros(3)):
return False
elif np.prod(v01) != 0:
ratio = v02 / v01
if ratio[0] == ratio[1] and ratio[1] == ratio[2]:
return False
else:
return True
elif np.prod(v02) != 0:
ratio = v01 / v02
if ratio[0] == ratio[1] and ratio[1] == ratio[2]:
return False
else:
return True
else:
for i in range(3):
if v01[i] != 0:
nonzero_idx = i
break
ratio = v02[nonzero_idx] / v01[nonzero_idx]
if all(ratio * v01[i] == v02[i] for i in range(3)):
return False
else:
return True
# E_A: v01 = k * v02 or v02 = k * v01
# E_B: v01[i] / v02[i] or v02[i] / v01[i] is constant for i = 0, 1, 2
# E_A and E_B are equivalent
# So we can know if v01 = k * v02 or v02 = k * v01 by deviding v02[i] by v01[i] for i = 0, 1, 2.
# But we need to check if the denominator is equal to zero before dividing.
# If one of the vectors is equal to zero vector, return False.
# If one of the vectors has no zero, divide the other vector by it.
# If the above two conditions are false, two vectors have both zero element and non-zero element.
while is_triangle1(a, b, c) == False:
a, b, c = generate_3dots()
print(np.array([a,b,c]))
# The result of print function above is a matrix, which contains the coordinates of three dots.
# 1st row: coordinates of a
# 2nd row: coordinates of b
# 3rd row: coordinates of c
2) 행렬의 덧셈은 행과 열의 크기가 같은 두 행렬의 같은 행, 같은 열의 값을 서로 더한 결과가 된다.
최대 10X10 크기인 두 개의 행렬을 랜덤으로 만들고, 그 두개의 행렬 덧셈의 결과를 반환하는 함수,
solution을 완성하시오.
2-1) 최대 크기가 10X10인 두 행렬을 랜덤으로 생성하시오. [2]
nrow = np.random.randint(1, 11)
ncol = np.random.randint(1, 11)
matA = np.random.randint(-100, 101, size = (nrow, ncol))
matB = np.random.randint(-100, 101, size = (nrow, ncol))
2-2) 두 행렬의 덧셈을 하시오. [2]
def solution(mat0, mat1):
return np.array([np.add(mat0[i], mat1[i]) for i in range(mat0.shape[0])])
mat_result = solution(matA, matB)
2-3) 행렬의 덧셈 값을 출력하시오. [2]
print(mat_result)
2-4) 행렬의 크기를 출력하시오. [2]
print("{}X{}".format(mat_result.shape[0], mat_result.shape[1]))
# ====================================================================================== #
# Theoretical Problem
1) numpy의 np.append()함수에서 axis를 설정하지 않았을 때,
두 배열의 차원이 일치하지 않아도 1차원 배열을 반환한다. [2]
O -> np.append() 디폴트값이 axis=None이고, 이는 차원과 상관없이 원소를 추가하여 1차원 배열을 return해줌 / numpy.append(arr, values, axis=None)
#근거 코드
arr1 = np.arange(1,13)
arr2 = np.arange(13,25).reshape(3,4)
arr3 = np.append(arr1, arr2) #axis가 없으면 1차원 배열로 변형해서 붙임
print(arr3) #오류없이 배열 붙음
2) np.sort() 함수를 사용하면 원본 배열이 직접 변경된다. [2]
--> X -> 원본 변경 안됨 / np.sort()함수는 정렬된 배열을 return을 해주는데, return값이 있는 것은 대부분 원본이 변경이 안됨. 즉, return값이 없으면 원본이 변경되니 조심해야함
#근거 코드
arr=np.random.randint(10, size=10)
print(arr)
#np.sort(배열) default : 오름차순
print(np.sort(arr))
print(arr)
3) np.reshape 함수를 사용하여 배열의 총 원소 수가 변할 수 있다. [2]
--> X -> reshape은 차원(형태) 변경에 주로 사용됨
#근거 코드
arr=np.arange(1,13).reshape(3,5)
print(arr) # 오류발생
4) np.concatenate() 함수는 기본적으로 배열을 0축(행 방향)으로 병합한다. [2]
--> O -> concatenate 함수의 매개변수 디폴트 : numpy.concatenate((a1, a2, ...), axis=0, out=None, dtype=None, casting="same_kind")
#근거 코드
arr1 = np.arange(1,13).reshape(3,4)
arr2 = np.arange(13,25).reshape(3,4)
arr_default=np.concatenate([arr1,arr2])
arr_axis0=np.concatenate([arr1,arr2], axis =0 )
print(arr1)
print(arr_default)
print(arr_axis0)
5) numpy 배열을 수평으로 병합하기 위해 np.hstack() 함수를 사용할 수 없다. [2]
--> X -> 수평 병합 : hstack
#근거 코드
arr1 = np.arange(1,13).reshape(3,4)
arr2 = np.arange(13,25).reshape(3,4)
arr_hstack = np.hstack((arr1, arr2))
print(arr_hstack)