본문 바로가기

학습 노트/알고리즘 (Python)

Python #1

서론


홈페이지를 만들어 보겠다고 삽질할 때도, 앱을 만드는 중에도
이제는 머리가 굳은 건지 원래도 멍청했던 게 이제야 티가 나는 건지
슬슬 공부를 떠나서 프로젝트에 돌입하며 한계를 느끼기 시작했다.

보고 이해하는 것과 처음부터 내가 생각한 것을 구현하는 것은 상당히 큰 차이가 있다.
이걸 메꾸기 위해 다른 공부가 필요하다고 생각했다.

Swift를 공부하고, 가장 많이 사용하기는 하지만 진입이 쉽고, 자료가 많기로는 Python을 따라가기 힘들다.
따라서 알고리즘 자체를 공부하고, 예제를 풀고, 이를 서로 공부하는 자리를 마련했는데,
사용하는 언어들이 다양하다 보니 같이 공부할 때는 Python을 사용하기로 결정했다.

한 녀석은 대학원생으로 Python을 이미 사용하고 있고,
한 녀석은 웹 개발자로의 취직을 준비하며 Java 등등의 다른 언어들을 사용하며,
프로젝트 중간에 Python을 잠깐은 본 듯 하다.
나도 졸업작품으로 Python을 사용하긴 했지만 항상 그렇듯 언어를 다시 잡을 때는 처음 배우는 것처럼 배우기로 했다.

그렇다고 주객이 전도되는 건 싫다.
Python을 주 언어로 둘 것도 아니고 공부의 목적이 알고리즘에 있기 때문에
간단한 문법 공부로 책이나 강의나 보며 필기를 하기보다는 예제를 풀며 빨리 익숙해지도록 방향을 정했다.

 

초보자를 위한 파이썬 300제

파이썬 기초 문법을 배웠다고 해서 누구나 프로그래밍에 익숙해지는 것은 아닙니다. 프로그래밍에 익숙해지기까지 많은 문제를 풀어보고 익숙해지는 것이 필요합니다. 파이썬 300제 ...

wikidocs.net

이 얼마나 좋은 세상인가.
여길 제외해도 좋은 자료들이 인터넷 상엔 널려 있다.

 

본론


이 날 우리는 300번 까지를 목표로 뒀지만
시간이 지나며 집중력이 흐트러진 탓인지 130번 까지를 푸는 것에 만족해야 했다.

20220319.ipynb
0.06MB

그중 129번과 130번은 자유롭게 풀고 코드를 비교해 보기로 했다.

No.129

#Egg's

value = input("id:")

original = value.replace('-','')
sum = 0

for i in range(12):
  if i == 0 or i == 8:
    sum += int(original[i]) * 2
  elif i == 1 or i == 9:
    sum += int(original[i]) * 3
  elif i == 2 or i == 10:
    sum += int(original[i]) * 4
  elif i == 3 or i == 11:
    sum += int(original[i]) * 5
  elif i == 4:
    sum += int(original[i]) * 6
  elif i == 5:
    sum += int(original[i]) * 7
  elif i == 6:
    sum += int(original[i]) * 8
  elif i == 7:
    sum += int(original[i]) * 9

target_flag = 11 - (sum % 11)

personal = value.split('-')[1]
flag = int(personal[-1:])

if target_flag == flag:
  print('true')
else:
  print('false')

replace 메서드를 사용해 계산을 위해 입력받은 주민등록 번호에서 '-'을 제거하고,
반복문을 사용해 각 자릿수에 적절한 연산을 시행한다.
(반복문은 조금 더 뒤쪽에서 다루지만 미리 사용했다.)

뒷자리의 마지막 번호인 식별코드를 추출하기 위해 '-'을 기준으로 문자열을 분리해
가장 끝 번호를 추출해 비교한다.

#Rabbit's

a = input("주민등록번호 : ")
x = a.replace("-","")
num1 = int(x[0])*2 + int(x[1])*3 + int(x[2])*4 + int(x[3])*5 + int(x[4])*6 + int(x[5])*7 + int(x[6])*8 + int(x[7])*9 + int(x[8])*2 + int(x[9])*3 + int(x[10])*4 + int(x[11])*5
num2 = num1 % 11
num3 = 11 - num2
if num3 == int(x[12]):
    print("유효한 주민등록증입니다.")
else:
    print("유효하지 않은 주민등록증입니다.")

동일한 알고리즘에서 반복문과 조건문을 대량 덜어낸 모습이다.
라인 수는 적지만 가독성은 조금 떨어지는 것이 단점이다.

#Whale's

num=input()

jumin=[float(num[0:1])*2,float(num[1:2])*3,float(num[2:3])*4,float(num[3:4])*5,
       float(num[4:5])*6,float(num[5:6])*7,float(num[7:8])*8,float(num[8:9])*9,
       float(num[9:10])*2,float(num[10:11])*3,float(num[11:12])*4,
       float(num[12:13])*5]

if float(num[13:14]) == (11-(float(sum(jumin))%11)) :
  print("왜 맞음", num[13:14])
else :
  print("유효 x", num[13:14], (11-(float(sum(jumin))%11)))
float(num[0:1])2

문자열 분할을 적극적으로 사용했다.
곱셈 결과는 배열에 순서대로 저장되고, 총합은 sum 메서드를 통해 구했다.

No.130

{'opening_price': '50175000', 'closing_price': '50136000', 'min_price': '49876000', 'max_price': '50332000', 'units_traded': '344.34219358', 'acc_trade_value': '17249542652.8511', 'prev_closing_price': '50162000', 'units_traded_24H': '2890.41931439', 'acc_trade_value_24H': '145358846994.2832', 'fluctate_24H': '-208000', 'fluctate_rate_24H': '-0.41', 'date': '1647885139712'} red

request로 받아오는 데이터는 위와 같은 dictionary 데이터다.

#Egg's

import requests
btc = requests.get("https://api.bithumb.com/public/ticker/").json()['data']

max = int(btc['max_price'])
min = int(btc['min_price'])
stprice = int(btc['opening_price'])
clprice = int(btc['closing_price'])

range = max - min
if stprice + range > max:
  print('red')
else:
  print('green')

Dictionary로 전달된 값을 사용하기 편한 변수로 바인딩했다.

#Rabbit's

import requests
btc = requests.get("https://api.bithumb.com/public/ticker/").json()['data']

a = {"시가": btc["opening_price"], "종가": btc["closing_price"],"최저가": btc["min_price"], "최고가": btc["max_price"]}
if (float(a["최고가"]) - float(a["최저가"])) + float(a["시가"]) > float(a["최고가"]):
    print("상승장")
else:
    print("하락장")

#Whale's

import requests
btc = requests.get("https://api.bithumb.com/public/ticker/").json()['data']

byundong=int(btc['max_price'])-int(btc['min_price'])

if (int(btc['opening_price'])+byundong) > int(btc['max_price']) :
  print("상승장")
else :
  print("하락장")

문제가 간단한 만큼 전부 비슷한 코드들이 나왔다.
토끼의 경우가 조금 특이한 경우인데 Dictionary를 새로운 Dictionary로 변환 후 진행했다.
어떻게 하든 상관없지만

a = {"시가": btc["opening_price"],
     "종가": btc["closing_price"],
     "최저가": btc["min_price"],
     "최고가": btc["max_price"]}

Dictionary의 선언의 경우 위와 같이 가독성에 신경 쓰는 쪽이 좋겠다는 의견을 주고받았다.

 

결론


No.129

//
//  main.swift
//  algorithm
//
//  Created by Martin.Q on 2022/03/22.
//

import Foundation
let id = readLine()
var sum = 0
let correction = CharacterSet(charactersIn: "0123456789-")

if id?.rangeOfCharacter(from: correction) != nil {
	let processing: String = id!.replacingOccurrences(of: "-", with: "")
	var array = [Character]()

	processing.forEach { char in
		array.append(char)
	}

	for i in 0...12 {
		guard let target = array[i].wholeNumberValue else {
			break
		}

		switch i {
		case 0, 8:
			sum += (target * 2)
		case 1, 9:
			sum += (target * 3)
		case 2, 10:
			sum += (target * 4)
		case 3, 11:
			sum += (target * 5)
		case 4:
			sum += (target * 6)
		case 5:
			sum += (target * 7)
		case 6:
			sum += (target * 8)
		case 7:
			sum += (target * 9)
		default:
			break
		}
	}

	let correction = 11 - (sum % 11)

	if correction == array.last?.wholeNumberValue {
		print("true")
	} else {
		print("false")
	}
} else {
	print("input id must have 13 number with '-'")
}

129번 문제를 Swift로 바꿔봤다.

첫 번째로 느낀 점은 Swift의 문자열을 다루는 부분이 여전히 어렵다는 점이다.
일반적인 정수형 인덱스를 사용하는데 이게 번거로워 배열로 변환해 사용했다.

두 번째로 Python에선 사용하지 않았던 필요한 예외처리 부분을 추가했다.
CharacterSet을 사용해 숫자와 '-'으로만 구성된 입력인지 판단할 수 있다.

세 번째로 Python으로 작성했을 때 진행했던 '-'을 기준으로 한 불필요한 문자열 슬라이싱을 제거했다.

'학습 노트 > 알고리즘 (Python)' 카테고리의 다른 글

Stack #1  (0) 2022.06.04
선형 데이터 구조와 탐색  (0) 2022.05.03
Q1. 방 배정 하기  (0) 2022.04.22
Python #3  (0) 2022.04.18
Python #2  (0) 2022.04.15