int main(void)
{
queue<int> q;
int n;
// 카드 수 입력
cin >> n;
// 입력한만큼 카드 추가
for(int i=0; i<n; i++)
q.push(i+1);
// 마지막에 한장이 남으므로 n-1번 반복
for(int i=0; i<n-1; i++)
{
q.pop(); // 맨 윗장을 지우고
q.push( q.front() ); // 그리고 오게 된 카드를 맨 뒤에 놓음
q.pop(); // 뒤로 보냈기에 중복 방지로 지움
}
// 정답 출력
cout << q.front();
return 0;
}
#셀레니움 라이브러리 import
from selenium import webdriver
from urllib.request import urlopen
from bs4 import BeautifulSoup as bs
from urllib.parse import quote_plus
from selenium.webdriver.common.keys import Keys
import time
from IPython.display import Image
import urllib
import time
# Colab에선 웹브라우저 창이 뜨지 않으므로 별도 설정한다.
# Colab 기본 설정
options = webdriver.ChromeOptions()
options.add_argument('--headless') # Head-less 설정
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36'
options.add_argument('user-agent={0}'.format(user_agent))
driver = webdriver.Chrome('chromedriver', options=options)
#해당 url로 이동 ex : MSFT
url = "https://www.nasdaq.com/market-activity/stocks/"+ticker+"/earnings"
driver.implicitly_wait(10)
driver.get(url)
consensus EPS 크롤링
import pandas as pd
# consensus EPS 크롤링
driver.implicitly_wait(10)
table = driver.find_element_by_class_name('earnings-forecast__section--quarterly')
# 통채로 추출한 테이블에서 필요한 consensus EPS 부분만 따로 추출
tbody = table.find_element_by_tag_name("tbody")
rows = tbody.find_elements_by_tag_name("tr")
eps = []
for index, value in enumerate(rows):
body=value.find_elements_by_tag_name("td")[0]
eps.append(body.text)
#다음 5개 분기의 consensus의 정확한 날을 모르므로, 최대한 미래 값으로 설정하였다.
eps_dict = {
'2099-01-01': eps[0],
'2099-01-02': eps[1],
'2099-01-03': eps[2],
'2099-01-04': eps[3],
'2099-01-05': eps[4],
}
# dataframe 형태의 다음 5분기에 대한 consensus eps
eps = pd.DataFrame.from_dict(eps_dict, orient='index').rename(columns={0:'epsactual'})
현재 분기와 이전 분기 EPS 크롤링
import datetime
# 지금까지 발표된 eps 크롤링
table = driver.find_element_by_class_name('earnings-surprise__table')
# 문자열 형태로 받은 eps 데이터를 띄어쓰기 단위로 나눔
table_list = table.text.split()
# 15번째와 21번째에 현재분기와 이전분기 발표 날짜가 저장되어있고
## 여기서 사용하는 날짜 형식은 "2021-12-09" 이므로 해당 형태로 바꾸어준다.
table_list[15] = table_list[15][6:] + '-' + table_list[15][:2] + '-' + table_list[15][3:5]
table_list[21] = table_list[21][6:] + '-' + table_list[21][:2] + '-' + table_list[21][3:5]
# 크롤링한 eps 데이터를 딕셔너리 형태로 바꾸고, 이를 다시 dataframe 형태로 바꿔준다.
eps_b = {
table_list[15] : table_list[16]
,
table_list[21] : table_list[22]
}
# 날짜를 index로 설정하고, eps열의 이름을 'epsactual' 로 지정
eps_second = pd.DataFrame.from_dict(eps_b, orient='index').rename(columns={0:'epsactual'})
# 날짜가 내림차순으로 정렬 되어있어 다시 역순으로 정렬
eps_second = eps_second.iloc[::-1]
# 가격 데이터와 eps 데이터를 불러오기 위한
## 야후 파이낸스 api 설치
!pip install yahoo_fin
!pip install yahoo_fin --upgrade
import pandas as pd
import yahoo_fin.stock_info as si
# price history
price = si.get_data(ticker)
# earnings history
earnings_hist = si.get_earnings_history(ticker)
## index가 [4:] 인 이유는 미래 4개 분기의 eps 데이터를 불러오는데
### None 값으로 가져오기 때문에 잘라버림
earnings_hist = earnings_hist[4:]
# list 형식으로 불러온 것을 dataframe 형태로 바꿔줌
earnings = pd.DataFrame(earnings_hist)
# 미래 -> 과거 순에서 과거 -> 미래 순으로 바꿈
earnings = earnings[['startdatetime','epsactual']].iloc[::-1]
# 날짜 10글자로 조정
earnings['startdatetime'] = earnings['startdatetime'].str.slice(start=0, stop=10)
# startdatetime -> Date 로 이름 변경
earnings = earnings.rename({'startdatetime': 'Date'}, axis=1)
# 날짜 data를 index로 설정
earnings = earnings.set_index('Date',inplace = False)
#크롤링한 eps data와 실제 eps를 합침
EPS_plus_forcast = earnings.append(eps_second, ignore_index=False)
## 날짜와 eps 가 중복되는 경우가 발생하는데, 가장 밑에 있는 요소를 살리고
## 나머지는 다 지우도록 설정
EPS_plus_forcast = EPS_plus_forcast.loc[~EPS_plus_forcast.index.duplicated(keep='last')]
### ex : "2021-01-01" "2.1" , "2021-01-01" "2.3" 인 경우
### 후자를 선택하고 이전 값은 제거
EPS_plus_forcast = EPS_plus_forcast.append(eps, ignore_index=False)
EPS_plus_forcast
# 왜인지는 모르겠는데 eps가 지수표현이 되어 출력돼서
# 소수점 3글자만 출력하도록 설정
## 1.0+e0 -> 1.000
pd.options.display.float_format = '{:.3f}'.format
Pandas의 rolling 사용하면 NTM을 쉽게 계산할 수 있다. 하지만 rolling 기능은 자기 자신과 이전 N개의 합을 계산하므로, EPS를 뒤집어서 계산해야 한다.
또한 NTM은 자기 자신의 eps는 포함하지 않으므로, rolling 이후, 자기 자신을 빼주어야 한다.
# ntm 계산용으로 eps 뒤집기
ntm_tmp = EPS_plus_forcast.iloc[::-1]
# 자기 자신도 포함해서 더해버려서 5개를 더하고 자기자신을 빼면 미래의 4개가 됨
ntm_tmp = ntm_tmp['epsactual'].rolling(window = 5, min_periods=5).sum()
# ntm 다시 처음으로 되돌리기
ntm_tmp = ntm_tmp.iloc[::-1]
# eps와 ntm의 요소가 str로 되어있는 경우가 있어
# float 형태로 바꿔준다
ntm_tmp = ntm_tmp.astype('float')
EPS_plus_forcast = EPS_plus_forcast.astype('float')
# rolling 값에서 자기 자신 값을 빼준다.
NTM = ntm_tmp.to_frame(name='epsactual').sub(EPS_plus_forcast, fill_value = 0, axis = 0)
가격 데이터와 EPS 데이터를 합쳐 하나의 dataframe으로 정리한다.
# NTM과 가격데이터 융합
df = price.join(NTM)
# 실적 발표한 날 이전의 날들은
## 그 이전 실적발표한 날의 NTM으로 설정한다
df = df.fillna(method='ffill')
# dataframe의 모든 요소를 출력
pd.set_option('display.max_row', None)
df.tail()
1. K번째까지 탐색하며 가장 큰 수 전까지 제거 2. 확정된 처음 수 이후부터 끝까지 탐색하면서 다음 수와 비교했을 때 수가 증가한 경우 해당 수 제거 3. 제거함에도 불구하고, k가 남은 경우 k만큼 끝 자리 수 제거ㅌ
테스트 케이스는 다 맞았지만, 채점 결과 하나만 통과,,, 스택구조로 다시 풀어보겠다.
string solution(string s, int k)
{
int f_val = 0;
int f_inx;
for(int i=0; i<=k; i++) // 1. 과정
{
if(f_val < s[i] - '0')
{
f_val = s[i] - '0';
f_inx = i;
}
}
s = s.substr(f_inx, s.size() - f_inx);
k = k - f_inx;
while(k > 0) // 2. 과정, 지워야할 숫자가 없다면 종료
{
vector<int> idx;
for(int i=0; i<s.size()-1; i++) //다음 수가 커지는 경우 인덱스 저장
{
if(s[i] < s[i+1] && idx.size() < k)
idx.push_back(i);
}
for(int i=0; i<idx.size(); i++) // 저장된 인덱스의 수 제거
{
s = s.erase(idx[i]-i,1);
}
k = k - idx.size(); //지워야 할 숫자들의 수 갱신
if(idx.size() == 0) //다음 수가 커지는 경우가 없다면 끝내기
break;
}
if(k > 1) // 3. 과정
s = s.substr(0, s.size() - k);
return s;
}
Try 2
테스트 케이스를 안 알려줘서 직접 다 쥐어짜내면서 하느라 죽는줄 알았다...
오름차순, 내림차순 섞으면서 해보고 오름차순으로만도 해보고, 내림차순만으로도 해보고
두자리 숫자에 하나만 지워보기도 하고, 테스크 케이스를 최대한 많이 굴려보는게 접근하기 좋다.
특히나 프로그래머스는 불친절한 감이 없지않아 있다...
아이디어는 아래 블로그를 적극적으로 활용했다.
string solution(string s, int k)
{
int f_val = 0;
int f_inx = 0;
string ans;
for(int i=0; i <= k; i++) //처음 큰 수까지 추출 과정
{
if(f_val < s[i] - '0')
{
f_val = s[i] - '0';
f_inx = i;
}
}
s = s.substr(f_inx, s.size() - f_inx); //추출한 값까지 제거
ans += s[0];
k = k - f_inx;
f_inx = 1; //첫 자리는 정했으므로 그 다음 자리부터 시작
while(k>0 && f_inx< s.size())
{ //더 이상 지울 수가 없거나 탐색 인덱스가 범위를 초과하면 중단
f_val = 0; //수 비교 초깃값 0
int tmp = f_inx; //탐색 시작점 저장
for(int i=0; i<=k && tmp+i < s.size(); i++)
{ //가장 큰 수의 인덱스를 찾는 과정
if(f_val < s[tmp+i] - '0')
{
f_val = s[tmp+i] - '0';
f_inx = tmp+i;
}
}
ans += s[f_inx]; // 찾은 큰 수를 추가
k -= (f_inx - tmp);
//큰 수의 인덱스와 시작점의 차이는 지운 숫자의 수임
f_inx ++; //큰 수의 인덱스 다음 인덱스부터 탐색 시작
}
if(k>0) //k가 남아있는 경우 끝에서 k만큼 지워 주면 됨
ans = s.substr(0, s.size()-k);
else //다 지운 경우 탐색 인덱스 부터 끝부분까지 마저 채워주면 됨
ans += s.substr(f_inx, s.size() - f_inx);
return ans;
}
1년이 증가할 때마다 e s m을 1 증가하고 입력한 E S M과 동일한지 확인 다르다면, 1년을 다시 증가
중간에 e s m 이 각각의 범위를 초과할 때마다 1로 초기화시켜줌
int main()
{
int E,S,M;
int e = 1;
int s = 1;
int m = 1;
int year = 1;
cin >> E >> S >> M;
while(1)
{
if(E == e && S == s && M == m)
break;
e ++;
s ++;
m ++;
if(e == 16) e=1;
if(s == 29) s=1;
if(m == 20) m=1;
year++;
}
cout << year;
return 0;
}
bool solution(int x)
{
bool answer = true;
int tmp;
int sum = 0;
int X = x;
while(x != 0) // 각 자리수를 더하는 과정
{
tmp = x%10;
sum += tmp;
x = x / 10;
}
if(X % sum != 0)
answer = false;
return answer;
}
class Solution {
public:
int addDigits(int num)
{
int tmp;
int sum = 0;
while(num > 9) // 아래 과정을 한 자리 수가 될 때까지 반복
{
while(num != 0) // 각 자리수를 더하는 과정
{
tmp = num%10;
sum += tmp;
num = num / 10;
}
num = sum;
sum = 0;
}
return num;
}
};