import os
import tarfile
import urllib
import pandas as pd

 

housing = pd.read_csv('./housing.csv')
housing

 

결측치 확인 

housing.info()

 

ocean_proximity가 어떤 카테고리가 있고, 각 카테고리마다 얼마나 많은 구역 있는지 확인

housing["ocean_proximity"].value_counts()

 

bescribe()

  • 널 값 제외.
  • 숫자형 특성의 요약 정보 보여줌
  • std : 값이 퍼져 있는 정보 측정 (표준 편차)
  • 백분위 수
    • latitude의 25%는 33.93보다 작음
housing.describe()

 

히스토그램 그려보기

%matplotlib inline
import matplotlib.pyplot as plt
housing.hist(bins = 50, figsize = (20,15))
plt.show()
  • %matplotlib : 맷플롯립이 주피터 자체의 백엔드 사용하게 

 

테스트 세트 만들어보기

from zlib import crc32
def test_set_check(identifier, test_ratio):
    return crc32(np.int64(identifier)) & 0xffffffff < test_ratio * 2**32
def split_train_test_by_id(data, test_ratio, id_column):
    ids = data[id_column]
    in_test_set = ids.apply(lambda id_ : test_set_check(id, test_ratio))
    return data.loc[~in_test_set], data.loc[in_test_set]
housing_with_id = housing.reset_index()

train_set, test_set = split_train_test_by_id(housing_with_id, 0.2, "index")

→ 해시값을 계산하여 해시 최대값의 20%보다 작거나 같은 샘플만 테스트 세트로 보낼 수 있음

 

사이킷런 

train_test_split

  • 난수 초깃값을 지정 가능 - random_state
  • 행의 개수가 같은 여러 개의 데이터셋을 넘겨서 같은 인덱스를 기반으로 나누기 가능 
from sklearn.model_selection import train_test_split
train_set, test_set = train_test_split(housing, test_size = 0.2, random_state = 42)

 

계층적 샘플링

  • 카테고리 5개 가진 소득 카테고리 특성
  • bin - 카테고리 범위
  • housing["income_cat"] = pd.cut(housing["median_income"],
                                  bins = [0.,1.5,3.0,4.5,6.,np.inf],
                                  labels = [1,2,3,4,5])

 

'Hand-On Machine Learning' 카테고리의 다른 글

[9장] 비지도 학습_가우시안 혼합  (0) 2021.07.27

https://www.acmicpc.net/problem/20300

 

20300번: 서강근육맨

PT 첫째 날에 $1$과 $4$를 선택하고, 둘째 날에 $2$와 $3$을 선택하고, 마지막 날에 $5$를 선택하면 $M$은 $5$가 되며, 이때가 $M$이 최소일 때이다.

www.acmicpc.net

 

이 문제는 정말 간단하다. 

음 먼저 최솟값을 구해야하기 때문에 

작은 것 끼리 더하는게 아닌, 

어릴 적 덧셈 빨리 하는 법 하면 기억나는 

첫번째 자리랑 끝자리 더해서 n/2만큼 반복하면 합이 나온다는 방법을 이용했다 

(방법 이름이 생각 안 난다. )

 

 

어쨋든 

알고리즘

  • 개수를 입력받는다. 
  • 개수만큼 숫자를 받고
  • 정렬한다. 
  • 받은 개수가 짝수이면
    • 앞자리 , 끝자리 더한다
    • 앞자리 ++, 끝자리 ++ n/2번 더한다. 
  • 받은 개수가 홀수이면
    • 끝자리 max_num으로 넣고
    • 짝수와 같이 진행한다. 

여기서 add_num을 다르게 한 이유가. 

홀수는 끝자리를 먼저 더해서 -2를 한 것이고, 

짝수는 끝자리 배열 인덱스를 접근하기 위해서다.

 

 

코드는 

#include <iostream>
#include<vector>
#include <algorithm>
using namespace std;

int main() {

	int testcase;
	cin >> testcase;
	vector<long long> input;
	long long output_max = 0;
	long long num;
	for (int i = 0; i < testcase; i++) {
		cin >> num;
		input.push_back(num);
	}

	sort(input.begin(), input.end());
	int add_num = 1;
	if (testcase % 2 == 1) {
		output_max = max(output_max, input[testcase - 1]);
		add_num = 2;
	}
	for (int i = 0, end = testcase - add_num; i < testcase / 2; i++,end--) {
		output_max = max(output_max, input[i] + input[end]);
	}
	cout << output_max;
	return 0;
}

 

https://www.acmicpc.net/problem/1758

 

1758번: 알바생 강호

첫째 줄에 스타박스 앞에 서 있는 사람의 수 N이 주어진다. N은 100,000보다 작은 자연수이다. 둘째 줄부터 총 N개의 줄에 각 사람이 주려고 하는 팁이 주어진다. 팁은 100,000보다 작거나 같은 자연수

www.acmicpc.net


이건 그냥 계산만 하는 거라서
왜 그리디 알고리즘인지 모르겠다.

나중에 여쭤봐야지

그냥 간단하게, 팁을 많이 준 사람은 앞에 순서에 해서
많이 받게 하는 것이다.


여기서 오래 걸린 이유는,
python의 입출력을 어떻게 해야할지 몰라서다.

처음에 입출력을 input()으로만 사용해서 했더니
틀렸다는 것이다.

진짜 왜 틀렸을까. 했는데
입출력 문제였다.

그래서 input()대신
sys.stdin.readline을 사용하려는데
그것도 jupyter Notebook에서 invalid literal for int() with base 10: '' 이렇게 나온것이다.
int(sys.stdin.readline)을 사용했는데,,,

파이참으르 사용해서 확인했더니 잘 되기만 했다. ㅋㅎ
그냥 주피터가 잘 못한듯,,,;;

새로운 것을 배웠다,
input()보단
sys.stdin.readline()이 더 빠르다는 것을,
그리고 여러 개 받을 땐 (정수형)
int(sys.stdin.readline()) for _ in range(n)을 사용하자!

import sys input = sys.stdin.readline testcase = int(input()) input_num = [int(input()) for _ in range(testcase)] input_num.sort(reverse= True) sum_output = 0 for i in range(testcase): if input_num[i] - i >0: sum_output += input_num[i]-i print(sum_output)

https://www.acmicpc.net/problem/1541

 

1541번: 잃어버린 괄호

첫째 줄에 식이 주어진다. 식은 ‘0’~‘9’, ‘+’, 그리고 ‘-’만으로 이루어져 있고, 가장 처음과 마지막 문자는 숫자이다. 그리고 연속해서 두 개 이상의 연산자가 나타나지 않고, 5자리보다

www.acmicpc.net

 

처음에 왜 55-50+40이 -35가 나오는지 몰랐다. 

그런데 식을 보니깐

마이너스가 나오려면 마이너스가 커야 하기 때문에 

55-(50+40)하면 -35가 나온다는 걸 깨달았다. 

 

수업시간에 깨달아서 좀 진정하고 코드를 짰다. 

역시 알고리즘 먼저 생각하고 짜니깐.

짜는건 오래 안 걸린다...

 

알고리즘

  • 입력을 받는다
  • stringstream으로 숫자 파싱한다. 
  • 파싱한 숫자가 0보다 크다면(양수)
    • sum(마이너스 일 때 더한 수)가 0이면 push
    • sum이 0이 아니라면, 
      • 앞에 마이너스가 있어서 마이너스 할 것을 더하고 있다면 sum더하기 ( ex, -20+30일 경우)
      • 그냥 양수가 나온 것이라면, push (ex, +50+60+70)
  • 0보다 작다면(음수)
    • 마이너스가 나온 것이 처음 or 마이너스 시작이면
      • check true로 하고(시작했다는 것을 알림)
      • sum에 num 더하기
    • 앞에 마이너스가 있어서 더하고 있었는데 다음 마이너스가 나온 것이라면 (ex, -20 +30 40 -30)
      • 더한 값 전부 -1곱해서 push
      • sum을 새로 업데이트 

 

그냥 생각하면 쉬웠는데,,

조금 더러운 코드가 된게 아닌가 싶다...

 

#include <iostream>
#include<sstream>
#include<string>
#include <stack>

using namespace std;
int main() {
	stringstream ss;
	string input;
	stack<int> number;

	int num;
	int sum = 0;
	cin >> input;
	ss.str(input);
	bool check = false;
	while (ss >> num) {
		if (num > 0) {
			if (sum == 0) {
				number.push(num);
			}
			else {
				if (!check) {
					number.push(num);
				}
				else {
					sum += num;
				}
			}
		}
		else {
			if (!check) {
				check = true;
				sum += num * (-1);
			}
			else {
				number.push((-1)*(sum));
				sum = num * (-1);
				check = true;
			}	
		}
	}
	if(check)
		number.push((-1)*(sum));
	int output = 0;
	for (int i = 0; !number.empty(); i++) {
		output += number.top();
		number.pop();
	}
	cout << output;
	return 0;
}

 

https://www.acmicpc.net/problem/2217

 

2217번: 로프

N(1 ≤ N ≤ 100,000)개의 로프가 있다. 이 로프를 이용하여 이런 저런 물체를 들어올릴 수 있다. 각각의 로프는 그 굵기나 길이가 다르기 때문에 들 수 있는 물체의 중량이 서로 다를 수도 있다. 하

www.acmicpc.net


이 친구는 좀 쉬웠는데,,
왜 안 됐을까 아직도 모르겠다.

나는 정렬하기 귀찮아서 set을 썼었는데,,
틀렸다,,
set이랑 배열이랑 무슨 상관일까?
포인터로 접근해서 그런가,,,,,,,,

set 말고 배열로 할당받아 계산하니 됐다.

이 알고리즘은 엄청 간단하다.

  • 정렬한다.
  • 정렬한 첫번째 값(젤 작은 값 ) * testcase랑 곱한다.
  • testcase는 감소하면서 두 번째 값을 곱한다.
  • 젤 큰 값을 찾는다.


이렇게 하는 이유가,
로프는 전체를 쓸 필요가 없고, 들어올릴 수 있는 최대 중량을 구하는 것이다.


생각해보면 간단하다.
예를 들어
40
100
2
5000
무게를 들 수 있는 로프가 있다.

정렬을 안 해보고 생각해보자
40 부터 1개니깐, 무게는 40
40,100 개를 들면, x/2 = 40(최소 40들 수 있음) → 최대 80
40, 100, 2이면 : x/3 = 2(최소 2 들 수 있음) → 최대 6
40, 100, 2, 5000 : x/4 = 2(최소 2 들 수 있음) → 최대 8

여기서 젤 큰 값은 80이다.
따라서 최댓값은 80이다.
로프를 전부 포함 안 해도 된다고 했으니
이런 결과값이 나올 수 있다.

#include<iostream> #include <set> #include <algorithm> using namespace std; int main() { int input[100001]; int testcase; cin >> testcase; long long max_num = 0; for (int i = 0,num; i < testcase; i++) { cin >> num; input[i] = num; } sort(input, input + testcase); for (int i = 0,mul = testcase; i < testcase; i++) { long long cal_num = (mul--) * input[i]; if(max_num < cal_num) max_num = cal_num; } cout << max_num; return 0; }

cout << fixed << setprecision(1) << (min_pa + min_ju) + ((min_pa + min_ju) * 0.1);

fixed << setprecision(소수점 아래 수)

fixed가 있으면, 소수점 아래의 수만 생각하고

 

없으면 자연수까지 생각한다고 한다. 

setprecision(5)이면

123.45까지

 

 fixed << setprecision(5)이면

123.45678

 

 

이렇게 나온다. 

'study > C or C++' 카테고리의 다른 글

[set] 공부  (0) 2021.04.08
1일차  (0) 2019.04.28


https://www.acmicpc.net/problem/1343

 

1343번: 폴리오미노

첫째 줄에 사전순으로 가장 앞서는 답을 출력한다. 만약 덮을 수 없으면 -1을 출력한다.

www.acmicpc.net


이건 그냥 음 처음에는 split써서 . 나눌까 했는데
그럼 ...이 여러개 나오면?
결국 구현했긴 한데
틀렸다.

그래서 순서대로 구해보기로 했는데

알고리즘은 간단하다.
1. 입력받는다.
2. "."과 문장 끝이 아니면 카운트센다
3. "."이 나오거나 문장끝이면

  • 카운트가 홀수이면 구현할 수 없기 때문에 "-1" 출력
  • 4로 나눠지면 "AAAA"추가
  • 2로 나눠지면 "BB"추가
#include <iostream> #include <string> using namespace std; int main() { string input_str; cin >> input_str; string output; int count = 0; for (int i = 0; i < input_str.size()+1; i++) { if (input_str[i] == '.' || input_str[i] == '\0') { if (count % 2 != 0) { cout << "-1"; return 0; } while (count / 4 != 0) { output+= "AAAA"; count -= 4; } while (count / 2 != 0) { output += "BB"; count -= 2; } if (i != input_str.size()){ output+="."; count = 0; } } else { count++; } } for (int i = 0; i < output.size(); i++) { cout << output[i]; } return 0; }



python

#1343 import sys input_str= str(input()) count = 0 output = "" for i in range(len(input_str)+1): if i == len(input_str) or input_str[i] == '.' : if count % 2 != 0: print("-1") sys.exit() while(count //4 != 0): output += "AAAA" count -= 4 while (count//2 != 0): output += "BB" count -= 2 if i != len(input_str): output += "." count = 0 else: count+=1 print(output) 

https://www.acmicpc.net/problem/14916

 

14916번: 거스름돈

첫째 줄에 거스름돈 액수 n(1 ≤ n ≤ 100,000)이 주어진다.

www.acmicpc.net


이 문제는 한번 생각을 해보아야 한다.
무조건 5를 나누는게 아닌, 최소한의 개수를 구해야한다.
그래서 나는 처음에 1부터 계산 해보았다.

1 2 3 4 5 6 7 8 9
2원 개수 0 1 0 2 0 3 1 4 2
5원 개수 0 0 0 0 1 0 1 0 1

이렇게 보면,
5의 배수는 무조건 5원으로 나눈다.
그런데 2원은 무조건 2로 나눠진다고 해서 바뀌는게 아니였다.

10 11 12 13 14 15
2원 개수 0 3 1 4 2 0
5원 개수 2 1 2 1 2 3



생각해보면 쉽다.
5원까지는 미리 적어놔야하거나,
아니면 계산하면된다. -1이 있으니
5원부터는 앞에꺼 들고오는 식이다.

1. 또 여기서 10원 이하는 2의 몫이다.
2. 10이하의 홀수들은 배열[i-5]의 값에 +1을 하면된다.
왜냐면 5원을 빼면 2원이 남거든.
남은 걸 계산하지말고 들고오자!

이런것이다.
c++코드는 좀 오래전에 짜서

#include <iostream> using namespace std; int main() { int check[100001] = { -1,-1,1,-1,2, }; int num; int count = 0; cin >> num; for (int i = 5; i <= num; i++) { if (!check[i]) { if (i % 5 == 0) { check[i] = i / 5; } else { if (check[i - 5] == -1)check[i] = i / 2; else { check[i] = check[i-5] + 1; } } } } cout << check[num]; return 0; }


python

input_num = int(input()) check = [] for i in range(1,input_num+1): if (i%2 != 0) &(i %5 != 0) and i < 5: check.append(-1) else: if (i % 5 == 0): check.append(i//5) elif (i <10 and i % 2 == 0): check.append(i//2) else : check.append(check[i-6] + 1) print(check[input_num-1]) 


python 더 열심히 해보자.

+ Recent posts