[Zero-Base DS]스터디노트_기초수학(03)

HAHAHAEUN·2024년 3월 20일

주요내용

1. 기초수학 문제풀이 복습

2. 기초수학 강의 회고

I. 약수와 소수

import random

numList = []
isPrimeList = []
isNumnPrimeList = []

rNum = random.randint(100,1000)
print(f'rNum: {rNum}')

for i in range(1, rNum + 1):

    soinsuFlag = 0

    # 약수
    if rNum % i == 0:
        print(f'[약수]: {i}')
        numList.append(i)
        soinsuFlag += 1

    # 소수
    if i != 1:
        flag = True  # 전제조건 소수
        for n in range(2, i):
            if i % n == 0:
                flag = False  # 소수가 아님
                break

        if(flag):  # 반복문 빠져나와서 if 소수일 경우,
            print(f'[소수]: {i}')
            isPrimeList.append(i)
            soinsuFlag += 1

    # 소인수: 약수이면서 소수인 것
    if soinsuFlag >= 2:
        print(f'[소인수]: {i}')
        isNumnPrimeList.append(i)

출력 결과 : (결과가 길어 일부만 발췌)

강의 자료 학습 전 내가 만든 프로그램

import random 

numList = []
isPrimeList = []
isNumnPrimeList = []

rNum = random.randint(100,1000)
print(f'rNum: {rNum}')

for i in range(1, rNum + 1):
  # 약수
    if rNum % i == 0:
        numList.append(i)
  # 소수
    if i != 1:
        flag = True  # 전제조건 소수
        for n in range(2, i):
            if i % n == 0:
                flag = False  # 소수가 아님
                break

       if(flag):  # 반복문 빠져나와서 if 소수일 경우,
           isPrimeList.append(i)
# 소인수
for idx, values in enumerate(numList):
    if values in isPrimeList:
        isNumnPrimeList.append(values)
print(numList)
print(isPrimeList)
print(isNumnPrimeList)

출력 결과 : (리스트형식으로 되어있는게 보기 편할 것 같아서 리스트 형식으로 출력했었다)

II. 소인수와 소인수분해

import random
rNum = random.randint(100,1000)
print(f'rNum: {rNum}')
isPrimeList = []

n = 2  # 소수는 2부터 시작
while n <= rNum:
    if rNum % n == 0:
        isPrimeList.append(n)
        rNum /= n
    else:
        n += 1

print(isPrimeList)

# 갯수 출력: .count()
tempNum = 0
for s in isPrimeList:
    if tempNum != s:
        print(f'{s}의 개수: {isPrimeList.count(s)}')
        tempNum = s   # 같은 숫자를 count하면 안되니, 해당 숫자부터 다시 시작

출력 결과 :

III. 최대공약수

import random

rNum1 = random.randint(100,1000)
rNum2 = random.randint(100,1000)

maxNum = 0
for n in range(1, min(rNum1, rNum2) + 1):
    if rNum1 % n == 0 and rNum2 % n == 0:
        print(f'공약수: {n}')
        maxNum = n

print(f'최대공약수: {maxNum}')
if maxNum == 1:
    print(f'{rNum1}{rNum2}는 서로소이다')

출력 결과 :

강의 자료 학습 전 내가 만든 프로그램

import random

rNum1 = random.randint(100,1000)
rNum2 = random.randint(100,1000)

commonList = []

for i in range(1,rNum1 + 1):
   if rNum1 % i == 0 and rNum2 % i == 0:
       commonList.append(i)

print(f'{rNum1}{rNum2}의 공약수: {commonList}')
print(f'{rNum1}{rNum2}의 최대 공약수: {max(commonList)}')

if len(commonList) == 1:
   print(f'{rNum1}{rNum2}는 서로소이다')
else:
   print(f'{rNum1}{rNum2}는 서로소가 아님')

출력 결과 :

  • 공약수 리스트(commonList)를 만들고 해당 len이 1인 경우, 서로소로 출력되도록 만들었다.
  • 교수님이 만드신 프로그램을 보며 더 간결하게 만드는 방법을 고민해봐야겠다고 느꼈다

IV. 최소공배수

import random

rNum1 = random.randint(100,1000)
rNum2 = random.randint(100,1000)
commonList = []
print(f'rNum1: {rNum1}')
print(f'rNum2: {rNum2}')

maxNum = 0
for i in range(1, min(rNum1, rNum2) + 1):
    if rNum1 % i == 0 and rNum2 % i == 0:
        commonList.append(i)
        maxNum = i
print(commonList)
print(f'최대공약수: {maxNum}')

minNum = (rNum1 * rNum2) // maxNum
print(f'최소공배수: {format(int(minNum), ',')}')

출력 결과 :

V. 진법

# 사용자 입력 num -> 변환

inputNum = int(input('10진수 입력: '))

#1)
print(f'{inputNum} -> 2진수: {bin(inputNum)}')
print(f'{inputNum} -> 8진수: {oct(inputNum)}')
print(f'{inputNum} -> 16진수: {hex(inputNum)}')

#2) #제거하면, 0b/0o/0x 제거되어서 나옴
print('{} -> 2진수: {}'.format(inputNum, format(inputNum, '#b')))
print('{} -> 2진수: {}'.format(inputNum, format(inputNum, '#o')))
print('{} -> 2진수: {}'.format(inputNum, format(inputNum, '#x')))

#3) 2진수/8진수/16진수 -> 10진수 (int)
print(f'2진수(0b10101))-> 10진수: {int('0b10101', 2)}')
print(f'8진수(0o31))-> 10진수: {int('0o31', 8)}')
print(f'16진수(0x5f))-> 10진수: {int('0x5f', 16)}')

#4) 2진수 -> 8진수 (oct) / 10진수(int) / 16진수(hex)
print(f'2진수(0b11001))-> 8진수: {oct(0b11001)}')
print(f'2진수(0b11001))-> 10진수: {int(0b11001)}')
print(f'2진수(0b11001))-> 16진수: {hex(0b11001)}')

#5) 8진수 -> 2진수 (bin) / 10진수(int) / 16진수(hex)
print(f'8진수(0o31))-> 2진수: {bin(0o31)}')
print(f'8진수(0o31))-> 10진수: {int(0o31)}')
print(f'8진수(0o31))-> 16진수: {hex(0o31)}')

#6) 16진수 -> 2진수 (bin) / 10진수(int) / 8진수(oct)
print(f'16진수(0x19))-> 8진수: {bin(0x19)}')
print(f'16진수(0x19))-> 10진수: {oct(0x19)}')
print(f'16진수(0x19))-> 16진수: {hex(0x19)}')

출력 결과 :

VI. 등차수열

  • 등차수열은 공식을 사용하면 간단하게 해결할 수 있다

    등차수열 공식

    • 일반항 : an=a1+(n1)da_n = a_1 + (n-1)*d
    • 등차중앙 : an=(an1+an+1)/2a_n = (a_{n-1} + a_{n+1})/2
    • 등차 수열의 합 : sn=n(a1+an)/2s_n = n(a_1 + a_n)/2

inputN1 = int(input('a1 입력: '))
inputD = int(input('공차 입력: '))
inputN = int(input('n 입력: '))

valueN = inputN1 + (inputN - 1)*inputD
sumN = (inputN*(inputN1 + valueN))/2

print('='*30)
print(f'{inputN}번째 항의 값: {int(valueN)}')
print(f'{inputN}번째 항까지의 합: {int(sumN)}')
# 파이썬은 나누기 값이 float형식으로 나오므로, int로 바꿔줌

출력 결과 :

  • 공식을 모르는 경우, 활용할 수 있는 방법:
inputN1 = int(input('a1 입력: '))
inputD = int(input('공차 입력: '))
inputN = int(input('n 입력: '))

valueN = 0
sumN = 0

n = 1
while n <= inputN:
    valueN = inputN1 + inputD * (n - 1)
    sumN += valueN
    print(f'{n}번째 항까지의 합: {sumN}')
    n += 1

print('='*30)
print(f'{inputN}번째 항까지의 합: {sumN}')

출력 결과 :

VII. 등비수열

  • 등비수열은 공식을 사용하면 간단하게 해결할 수 있다

    등비수열 공식

    • 일반항 : an=a1rn1a_n = a_1 * r^{n-1}
    • 등차중앙 : an2=an1an+1a_n^2 = a_{n-1} * a_{n+1}
    • 등차 수열의 합 : sn=a1(1rn)/(1r)s_n = a_1 * (1 - r^n)/(1-r)

inputA1 = int(input('a1 입력: '))
inputR = int(input('공비 입력: '))
inputN = int(input('n 입력: '))

valueN = inputA1 * (inputR**(inputN - 1))
sumN = int(((inputA1 * (1 - (inputR**inputN)))/(1-inputR)))
print(f'{inputN}번째 항의 값: {format(valueN, ',')}')
print(f'{inputN}번째 항까지의 합: {format(sumN, ',')}')

출력 결과 :

  • 공식을 모르는 경우, 활용할 수 있는 방법:
inputA1 = int(input('a1 입력: '))
inputR = int(input('공비 입력: '))
inputN = int(input('n 입력: '))

#1) 공식 미사용
valueN = 0; sumN = 0
n = 1
while n <= inputN:

    if n == 1:
        valueN = inputA1
        sumN = valueN
        print(f'{n}번째 항의 값: {valueN}')
        print(f'{n}번째 항까지의 합: {sumN}')
        n += 1
        continue

    valueN *= inputR
    sumN += valueN
    print(f'{n}번째 항의 값: {format(valueN, ',')}')
    print(f'{n}번째 항까지의 합: {format(sumN, ',')}')
    n += 1

print('='*30)
print(f'{inputN}번째 항의 값: {format(valueN, ',')}')
print(f'{inputN}번째 항까지의 합: {format(sumN, ',')}')
print('='*30)

출력 결과 :

VIII. 계차수열

  • 계차수열 또한 공식을 사용하면 더 쉽게 해결이 가능하다
    • 등차수열 혹은 등비수열 중 문제에 해당하는 공식 사용

# 공식 사용(등차수열)
# an = a1 + (n-1)*d
# sn = n(a1 + an)/2
# an = 시그마bk + a1
# b_k = 3 + (k-1)*3 = 3k
# 시그마(n-1): bk = (k-1)(3k)/2 = (3k^2-3K)/2
# an = (3k^2-3K)/2 + 2

valueANN = int((3 * (inputAN**2) -3*(inputAN))/2 + 2)
print(f'an의 {inputAN}번째 항의 값: {valueANN}')

출력 결과 :

  • 공식을 모르는 경우, 활용할 수 있는 방법:
inputAN1 = int(input('a1 입력: '))
inputAN = int(input('an 입력: '))
inputBN1 = int(input('b1 입력: '))
inputBD = int(input('bn 공차 입력: '))

valueAN = 0
valueBN = 0

# B항을 통한 일반항 구하기
n = 1
while n <= inputAN:

    if n == 1:
        valueBN = inputBN1
        valueAN = inputAN1
        print(f'an의 {n}번째 항의 값: {valueAN}')
        print(f'bn의 {n}번째 항의 값: {valueBN}')
        n += 1  # 무한루프에 빠지지 않기 위해 필요
        continue
    valueAN += valueBN
    valueBN += inputBD
    print(f'an의 {n}번째 항의 값: {valueAN}')
    print(f'bn의 {n}번째 항의 값: {valueBN}')
    n += 1

print('='*30)
print(f'an의 {inputAN}번째 항의 값: {valueAN}')
print(f'bn의 {inputAN}번째 항의 값: {valueBN}')
print('='*30)

출력 결과 :

IX. 피보나치수열

inputN = int(input('n 입력: '))

valueN = 0  # 찾아야하는 n번째 항의 값
sumN = 0  # n번째 항까지의 합

valuePreN2 = 0
valuePreN1 = 0

n = 1
while n <= inputN:

    if n == 1 or n == 2:
        valueN = 1
        valuePreN2 = valueN
        valuePreN1 = valueN
        sumN += valueN
        n += 1
        continue

    else:
        valueN = valuePreN2 + valuePreN1
        valuePreN2 = valuePreN1
        valuePreN1 = valueN
        # 한 바퀴 돌았을 때, 이전 n-2 = n-1, n-1 = n 됨

        sumN += valueN
        n += 1

print(f'{inputN}번째 항의 값: {valueN}')
print(f'{inputN}번째 항까지의 합: {sumN}')

출력 결과 :

X. 팩토리얼

  • 팩토리얼 프로그램은 총 3가지 방법으로 만들 수 있다
# 1) 팩토리얼 프로그램 by 반복문
# 2) 재귀 함수 사용
# 3) 제공 모듈

#1) 반목문 사용

def facFun1(n):

    fac = 1
    for n in range(1, n+1):
        fac *= n

    return fac

num = int(input('input number: '))
print(f'{num}!: {facFun1(num)}')
print('='*30)

#2) 재귀함수
def facFun2(n):

    if n == 1:
        return n
    return n * facFun2(n-1)

num2 = int(input('input number: '))
print(f'{num2}!: {facFun2(num2)}')
print('='*30)

#3) 모듈
import math
num3 = int(input('input number: '))
factorial = math.factorial(num3)
print(factorial)

출력 결과 : (그리고 당연하게 결과는 같다)

XI. 군 수열(묶어서 규칙을 찾자)

# 수열의 합이 최초 100을 초과하는 n번째 항의 값

flag = True  # 무한으로 돌림, 특정 시점까지

n = 1; sumN = 0; nCnt = 1  # 군의 개수: n; 항의 개수: nCnt
searchNP = 0; searchNC = 0 # 찾고자 하는 분모, 분자

while flag:

    for i in range(1, n + 1):
        print(f'{i}/{n-i+1},', end='')

        sumN += i / (n-i+1)
        nCnt += 1

        if sumN > 100:
            searchNC = i
            searchNP = n-i+1
            flag = False # 합이 지정된 항 개수를 넘으면 stop
            break

    print()
    n += 1  # n = 1: 1군, n = 2: 2군 ...
            # n 값에 따라, 분자는 1씩 증가, 분모는 1씩 감소
print(f'수열의 합이 최초 100을 초과하는 항, 값, 합: {nCnt}항, {searchNC}/{searchNP}, {round(sumN, 2)}')

출력 결과 :

  • 군수열이 프로그램을 짜는데 가장 힘들었던 것 같다. 군별로 행을 나누는 깔끔한 방법이 생각나지 않아 애를 먹다 강의를 참고했었다.
  • 군수열은 추후에 다시 한 번 강의를 복습해야겠다.

XII. 순열, 조합, 확률

  • 순열, 조합 그리고 확률은 기본적으로 공식 + 팩토리얼 프로그래밍을 익히면 할 수 있는 구조여서 어렵지는 않았다.(복습 + 복습 같은 느낌으로 다가왔다)
  • 확률 예제
# 꽝 6장, 선물 4장 => 꽝 3 + 선물 3 확률
# 10C6
# 6C3* 4C3

def proFun():

    numN = int(input('numN 입력: '))
    numR = int(input('numR 입력: '))

    resultP = 1
    resultR = 1
    resultC = 1

    for i in range(numN, numN - numR, -1):
        resultP *= i

    for i in range(numR, 0, -1):
        resultR *= i

    resultC = int(resultP/resultR)
    return resultC
event1 = proFun()
event2 = proFun()
total = proFun()
result = 100 * ((event1 * event2)/total)
print(f'꽝 3장 조합: {event1}')
print(f'선물 3장 조합: {event2}')
print(f'꽝 3장 & 선물 3장 확률: {round(result, 2)}%')

출력 결과 :

금일은 이번주에 학습했던 기초수학에 대한 문제풀이 시간을 가졌다. 강의를 보기 전 먼저 예시를 혼자 풀어보고 그 후 강의 내용과 비교하며 보완 할 부분들을 수정해나갔다.
강의 내용과 비슷하게 풀은 문제도 있는가하면, 아예 다르게 푼 방법도 있었다. 또한 아예 풀지 못하고 강의를 보며 따라간 내용도 있었다. 추후 다시 해당 문제들을 풀었을 때는 막힘없이 풀 수 있도록 더욱 더 열심히 실력을 갈고 닦아야겠다.

[자료 출처: 제로베이스 데이터 취업 스쿨]

profile
할 거면 제대로 하자

0개의 댓글