반응형
728x90
반응형
 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

문제 : https://programmers.co.kr/learn/courses/30/42840

나의 풀이

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <string>
#include <vector>
 
using namespace std;
 
vector<int> solution(vector<int> answers) {
    
    // 벡터를 이렇게 초기화할 수 있다~ 라고 알면 된다.
    vector<int> a_answer({ 12345 });
    vector<int> b_answer({ 21232425 });
    vector<int> c_answer({ 3311224455 });
    
    vector<vector<int>> students; // 세 사람의 제출 답안을 묶음.
    vector<int> answer; 
    // 문제 정답으로 가장 최대로 맞춘 사람의 인덱스가 들어감.
    // 맞춘 횟수가 동일하면 공동 순위로 함께 들어감 -> 2, 2, 2 / 0, 0, 0, -> 답 : 1,2,3 / 1,2,3
    
    int ac_idx = 0, ac[3= { 0, }; // 정답 맞춘 갯수, 카운트 (0:a/2:c)
    
    students.push_back(a_answer);
    students.push_back(b_answer);
    students.push_back(c_answer);
    
    
    for(auto it : students)
    {
        for(int i=0; i<answers.size(); i++// 문제 문항수 만큼 반복하면서
        {
            // 하나하나 맞는지 대입한다. 반복되는 패턴이므로 나머지 연산자 활용
            if(answers[i] == it[i%it.size()]) 
                ac[ac_idx]++;
        }
        if(answer.size() == 0// 첫 대입은 무조건 대입.
            answer.push_back(ac_idx+1);
        else if(ac[answer.back()-1< ac[ac_idx]) // 이전 대입의 카운트보다 크면 
        { 
            // 교체
            answer.pop_back();
            answer.push_back(ac_idx+1);
        }
        else if(ac[answer.back()-1== ac[ac_idx]) // 이전 대입과 같으면 
            answer.push_back(ac_idx+1); // 추가 (공동 순위 개념)
            
        ac_idx++// 다음 카운트랑 비교를 위해
    }
    return answer;
}
cs

 

인기있는, 다른 사람의 풀이

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <string>
#include <vector>
#include <algorithm>
 
using namespace std;
 
vector<int> one = {1,2,3,4,5};
vector<int> two = {2,1,2,3,2,4,2,5};
vector<int> thr = {3,3,1,1,2,2,4,4,5,5};
 
vector<int> solution(vector<int> answers) {
    vector<int> answer;
    vector<int> they(3);
    for(int i=0; i<answers.size(); i++) {
        if(answers[i] == one[i%one.size()]) they[0]++;
        if(answers[i] == two[i%two.size()]) they[1]++;
        if(answers[i] == thr[i%thr.size()]) they[2]++;
    }
    int they_max = *max_element(they.begin(),they.end());
    for(int i = 0; i< 3; i++) {
        if(they[i] == they_max) answer.push_back(i+1);
    }
    return answer;
}
cs

내가 푼거에 비해서 깔끔하다 나는 반복문 투성인데 여기에서는 answers를 기준으로 한번만 돌았다.. ㅋㅋㅋ max_element 함수로 최대 값을 구한 뒤, 최대 값과 같으면 순서대로 다 집어넣는다. 5졌습니다..

728x90
반응형

'프로그래밍응용 > 오답노트' 카테고리의 다른 글

카카오톡 비밀지도  (0) 2021.02.18
SQL1  (0) 2021.02.15
벡터 복사 및 sort 이용  (0) 2021.02.13
우선순위 큐 이용한 문제 ㅋㅋ  (0) 2021.02.13
stack 주식 가격  (0) 2021.02.13
728x90
반응형
 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

출처

[1, 5, 2, 6, 3, 7, 4]를 2번째부터 5번째까지 자른 후 정렬합니다. [2, 3, 5, 6]의 세 번째 숫자는 5입니다.
[1, 5, 2, 6, 3, 7, 4]를 4번째부터 4번째까지 자른 후 정렬합니다. [6]의 첫 번째 숫자는 6입니다.
[1, 5, 2, 6, 3, 7, 4]를 1번째부터 7번째까지 자릅니다. [1, 2, 3, 4, 5, 6, 7]의 세 번째 숫자는 3입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 
#include <iostream>
#include <vector>
#include <algorithm>
 
using namespace std;
 
vector<int> solution(vector<int> array, vector<vector<int>> commands) {
    vector<int> part_vector;
    vector<int> answer;
    int i=0, j=0, k=0;
    
    // commands로부터 조건들을 꺼낸다.
    for(auto it=commands.begin(); it!=commands.end(); it++)
    {
        i = (*it)[0]-1, j = (*it)[1]-1, k = (*it)[2]-1// 1번째는 0번째이므로 -1 처리.
        
        part_vector.resize(j-i+1); // j-i+1 은 부분 벡터의 크기
        copy(array.begin()+i, array.begin()+j+1, part_vector.begin()); // 부분 벡터를 복사
        
        sort(part_vector.begin(), part_vector.end()); // 정렬(퀵)
        answer.push_back(part_vector[k]); // 정렬된 부분 벡터에서 k번째를 구함.
    }
    return answer; // 간단
}
cs
728x90
반응형

'프로그래밍응용 > 오답노트' 카테고리의 다른 글

SQL1  (0) 2021.02.15
무식하게 완전 탐색! - 모의고사  (0) 2021.02.15
우선순위 큐 이용한 문제 ㅋㅋ  (0) 2021.02.13
stack 주식 가격  (0) 2021.02.13
A집단과 B집단의 차이를 구할 때  (0) 2021.02.12
728x90
반응형

출처

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

섞은 음식의 스코빌 지수 = 가장 맵지 않은 음식의 스코빌 지수 + (두 번째로 맵지 않은 음식의 스코빌 지수 * 2)

  • 모든 음식의 스코빌 지수를 K 이상으로 만들 수 없는 경우에는 -1을 return 합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <vector>
#include <queue>
 
using namespace std;
 
int solution(vector<int> scoville, int K) {
    priority_queue<intvector<int>, greater<int>> pq; // 우선순위 큐 | Min Heap
    // priority_queue<int, vector<int>, greater<int> > pq; // 우선순위 큐 | Max Heap
    int answer = 0;
    int n1, n2;
    
    for(auto n : scoville) 
        pq.push(n); // Min Heap의 우선순위 큐에 모두 때려 넣는다 -> 스코빌 지수가 작은 녀석들부터 순서대로 튀어나온다
    
    while(pq.size() > 1 && pq.top() < K) // 큐에 2개 이상 들어가야만 세그멘테이션 폴트 에러가 발생하지 않는다.
    {
        // 두 개를 뽑고,
        n1 = pq.top(); pq.pop();
        n2 = pq.top(); pq.pop();
        
        // 두 음식을 섞어서 새롭게 스코빌 지수를 하나 탄생시키고 넣으면
        pq.push(n1+n2*2); // 해당 힙에 구조가 조정되어 들어간다 -> Min Heap 계속 유지하기 때문에 top이 K 이상이라면 나머지 값들도 모두 K이상을 만족
        answer++;
    }
    
    if(pq.top() < K) // 위 과정을 거쳤는데도 K 이상을 충족하지 않는다면
        return -1// 더 이상 조합으로는 K 이상으로 맞출수 없다는 소리이다. 음식이 1개 남았고, K미만인 경우임.
    
    return answer;
}
cs

 

728x90
반응형

'프로그래밍응용 > 오답노트' 카테고리의 다른 글

SQL1  (0) 2021.02.15
무식하게 완전 탐색! - 모의고사  (0) 2021.02.15
벡터 복사 및 sort 이용  (0) 2021.02.13
stack 주식 가격  (0) 2021.02.13
A집단과 B집단의 차이를 구할 때  (0) 2021.02.12
728x90
반응형

초 단위로 기록된 주식가격이 담긴 배열 prices가 매개변수로 주어질 때, 가격이 떨어지지 않은 기간은 몇 초인지를 return 하도록 solution 함수를 완성하세요.

prices [1, 2, 3, 2, 3] return [4, 3, 1, 1, 0]
  • 1초 시점의 ₩1은 끝까지 가격이 떨어지지 않았습니다.
  • 2초 시점의 ₩2은 끝까지 가격이 떨어지지 않았습니다.
  • 3초 시점의 ₩3은 1초뒤에 가격이 떨어집니다. 따라서 1초간 가격이 떨어지지 않은 것으로 봅니다.
  • 4초 시점의 ₩2은 1초간 가격이 떨어지지 않았습니다.
  • 5초 시점의 ₩3은 0초간 가격이 떨어지지 않았습니다.

내 풀이

#include <iostream>
#include <string>
#include <vector>

using namespace std;

vector<int> solution(vector<int> prices) {
    vector<int> answer;
    int cnt;

    for(auto it=prices.begin(); it!=prices.end(); it++) // 순차적으로 하나씩 접근
    { // 여기서 현재 잡고 있는 it가 비교의 기준임.
        cnt = 0;
        for(auto eit=(it+1); eit!=prices.end(); eit++) // 바깥 반복에서 접근한 요소 다음 요소들을 모두 확인한다
        {
            cnt++;
            if((*eit)-(*it) < 0) // 비교의 기준 it 보다 작아지는지 확인
            { // 작아지면
                answer.push_back(cnt); // 그 때의 카운트를 넣는다
                cnt = -1; // 카운트가 등록되었으니 의미 없음 이제.
                break;
            }
        }
        if(cnt != -1) // 끝까지 작아지지 않았다면 
            answer.push_back(cnt); // 총 카운트를 넣는다.
    } // 그리고 다음 요소를 기준으로 변경한다 

    return answer;
}

인기 풀이

#include <string>
#include <vector>
#include <stack>

using namespace std;

vector<int> solution(vector<int> prices) {
    vector<int> answer(prices.size());
    stack<int> s;
    int size = prices.size();
    for(int i=0;i<size;i++){
        while(!s.empty()&&prices[s.top()]>prices[i]){
            answer[s.top()] = i-s.top();
            s.pop();
        }
        s.push(i);
    }
    while(!s.empty()){
        answer[s.top()] = size-s.top()-1;
        s.pop();
    }
    return answer;
}

728x90
반응형

'프로그래밍응용 > 오답노트' 카테고리의 다른 글

SQL1  (0) 2021.02.15
무식하게 완전 탐색! - 모의고사  (0) 2021.02.15
벡터 복사 및 sort 이용  (0) 2021.02.13
우선순위 큐 이용한 문제 ㅋㅋ  (0) 2021.02.13
A집단과 B집단의 차이를 구할 때  (0) 2021.02.12
728x90
반응형
 

나는 자기계발서를 읽고 벤츠를 샀다

꿈을 이루고 성공을 잡는 법은 도대체 어디서 누구에게 배워야 하는가?'경영학 교수인 나는 꿈을 이루는 법을 자기계발서에서 배웠다!' 인간과 세상을 이해하려면 인문서를,꿈을 이루고 성공을

www.yes24.com

최성락 저 | 아템포 | 2014년 06월 12일

2014년도 제대한 직후에 서점갔다가 표지에 꽂혀서 샀던 책이다. 그 책을 몇 페이지 읽다가 방치해둔 후, 이제 와서 읽게 된다 ㄷㄷ이걸 이제와서 들쳐본 내가 참 레전드이다..

표지와 제목은?

아무튼 이 책은 제목부터 굉장히 자극적이었다. 자기계발서를 읽고서 벤츠를 산다니 이게 어디 말이 되는 소리인가? 표지의 벤츠 마크는 영롱하고 안정감 가득한 것이 매우 인상적이다.

책 제목의 윗 부분에는 경영학 교수의 대담한 고백이라고 적혀 있는데, 그렇다! 이번에도 지난 책 리뷰들과 마찬가지로 어떤 교수님이 쓰신 책이었던 것이다. (최성락 교수님)

그래서 내용은?

내용으로는 전형적인 자기 계발서들과는 조금 다르다. 읽는 내내 생각한 것이

아! 이 책은 자기계발서를 읽기 전에 꼭 읽어야하는 책이 아닐까?

위와 같이 생각을 하곤 했다.

1장 Case Study 벤츠, 어떻게 하면 살 수 있을까

먼저, 철저하게 본인의 경험을 바탕으로 생각들을 서술한다. 벤츠를 사기 위해서 해온 생각과, 행동, 그리고 마음 가짐 등을 경험에 기반하여 서술한다.

2장 절대 무시해선 안 되는 자기계발서의 힘

그 다음, 자기 계발서의 힘에 대해 설명한다. 이 설명과 함께 자기 계발서를 경영학과 심리학에 비유하는 부분들이 있는데 이 부분이 나는 너무 인상 깊었다. 너무나도 구구절절 맞는 말이었던 것이다. 어찌보면 이렇게 당연한 얘기들이다.목표를 세우고, 그 목표를 수치화하는 것이 특별한 내용인가? 절대 아니다. 목표가 있기 때문에 움직일 수 있는 것이고, 행동의 밑거름이 되는 것이다. 이런 경영학에서도 나오는 당연한 글을 읽으면서 감탄한 나는 계획만 세울줄 알았지 목표는 없었다. 이 얼마나 모순 그 자체인가!성공 = 행복 ? 전혀 연관이 없다. 성공했지만 행복하지 않을 수 있다. 성공을 위해 다가가는 과정 하나하나가 진행될수록 행복이라고 이야기한다. 이런 면에서 봤을 때, 심리학이란 비유를 드는 것이다.

3장 행동하지 않는 자여, 왜 자기계발서를 욕하는가!

다음으로는 자기계발서를 비판하는 내용들을 다시 전면적으로 비판하는 내용을 담는다. 3장의 소제목부터 뜬금하게 만든다. 행동하지도 않고? 딱 한 번 읽어놓고 변화를 바라는가? 단 기간에 성공할 것을 바라는건가?

4장 자기계발서, 어떻게 읽을 것인가

자기계발서를 그냥 읽는 것은 의미가 없다. 자기 계발서에서 이야기하는 행동이나 태도가 몸에 베이고, 사고 구조를 바꿔야한다. 그래야 행동으로 옮겨지기 때문이다. 어떤 자기 계발서를 읽을지, 어떻게 읽을지, 어떻게 활용할지, 얼마나 주기로 읽어야할지 등에 대해서 상세히 설명한다.

그래서 느낌은?

다 읽고나서 나는 혼돈 그 자체였다. 기존의 자기계발서에 대한 부정적인 시각이 모두 깨졌다.

정말이지 나는 자기계발서 류의 책은 절대 읽지 않았다. 왜 읽지 않았냐면 너무나도 뻔한 말들 뿐이고, 노력해야한다는 말 뿐이라고 그냥 부정적인 시각으로 못을 박아놨었기 때문이다.

그러나 너무나도 잘못된 시각이고, 잘못된 태도였다.

시간을 들이고, 꾸준히, 노력하는 것만이 정답이고 정도인데,
시간을 들이지도 않고, 노력하는 것도 없이 자기 계발서만 읽고 성공한다는 것은 정말 도둑 놈의 심보이다. 

이전까지는 성공을 하려면 아이템이 좋아야하고, 사업을 해야하며, 아이디어가 좋아야 성공한다고 생각했다. 그러나 이 얼마나 어리석은 생각이었을까? 정말 객관적으로 봤을 때 겉으로는 아이템이며, 창의적인 아이디이며 했지만 결국에는 일확천금을 꿈 꾼 것과 다를 바가 없다. 로또가 당첨되길 바라는 것과 무엇이 다를까?

나의 20대는 정말 후회스럽다. 그냥 막연하게 열심히 해야겠다 라는 생각은 했지만, 어떻게? 왜? 까지는 생각해보지 못했다. 조금만 더 깊게 생각하고, 좀 더 목표를 구체화하여 열심히 살았더라면 하고 후회를 해본다.

가장 중요한 것은 나의 모든 것들이 변하려면 일단, 행동해야한다. 항상 같은 행동을 하거나, 아무것도 하지 않으면서 다른 결과를 바라는 것은 정신병이나 다름 없다. 무조건 변화를 위한 새로운 행동을 행해야 하는데, 이 책에서는 그 첫 걸음이 자기계발서를 읽는 것이라고 이야기한다. 그 다음, 목표를 세우고, 그 목표를 수치화한 뒤 행복을 위해서 성취해가는 과정을 겪으면 되는 것이다.

그래서 포스팅이 완료되고 난 후, 나는 연습장에 목표를 적으러 간다.

이 책은 자기계발서에 부정적인 선입견을 가지고 있거나, 일확천금과 같은 허황된 꿈을 꾸고 있는 사람들이 반성하기 위해 읽기 딱 좋은 책이다. 아니! 이 책을 비판하려거든 읽어도 좋다. 다만 반박할 수 있어야 한다. 목표를 세우지 않고, 행동할 수 있는가? 반박하지 못한다면 반박을 위해 읽으려는 사람들은 책을 읽지도 말아야 한다.

728x90
반응형

'Library' 카테고리의 다른 글

트렌드 코리아 2021 / 2021년 01월 Reading  (0) 2021.02.13
가끔은 제정신 / 2020년 12월 Reading  (0) 2021.02.11
728x90
반응형
 

영풍문고 - 서점다운 서점

“코로나 이후 찾아온 강인한 소의 해, 묵직한 변화의 흐름을 짚다” 팬데믹 시대, 침체된 시장과 삶에 활기를 불어넣어줄 다음 트렌드는 무엇인가? 새로운 한 해를 이끌어나가기 위해 우리는

www.ypbooks.co.kr

저자 : 김난도외ㅣ출판사 : 미래의창2020.10.13 ㅣ 400p ㅣ ISBN-13 : 9788959896837

2020년 부터 꼭 했던 다짐이 있다. 올해는 꼭 트렌드 코리아 책을 읽어보겠노라. 그런데 2020년에도 실패 했었다. 제일 여유가 많았던 해였는데도 안 읽었을까.. 너무 안타깝지만 2021년에는 그것을 성공하고 말았다 뚜둥!

 

표지와 제목은?

일단은 이 책은 소비와 관련된 트렌드에 대한 내용이 주를 이룬다. 그래서인지 소비하면 딱 떠오를 수 있는 바코드가 책 표지의 하단에 크게 그려져 있다. 그건 뭐 역대 트렌드 코리아도 마찬가지인 것 같다.

 

표지에서 가장 핵심은 바로 다음의 문구이다.

팬데믹 위기에 대응하는 전략은 무엇인가?

2020년 한해는 코로나(COVID-19, 우한 폐렴) 역병의 해, 그 자체였다. 코로나 바이러스가 트렌드고 나발이고 다 씹어먹어버렸다.. 

그렇지만 이렇게 팬데믹 위기에서도 트렌드는 분명히 있다! 새롭게 소비의 형태가 다시 쓰여지고, 뿐만 아니라 새로운 업무 형태, 새로운 운동 형태, 새로운 모임 양상 등 새로운 트렌드가 분명히 존재한다. 이러한 트렌드를 읽어내고, 그 현상을 설명한다.

그래서 내용은?

 COWBOY HERO

카우보이 히로?가 무엇인가 했더니, 이니셜을 이어만든 단어이다. 이니셜은 아래에 나열된 단어들의 이니셜이다. 

Coming of 'V-nomics' | 브이노믹스

Omni-layered Homes | 레이어드 홈

We Are the Money-friendly Generation | 자본주의 키즈

Best We Pivot | 거침없이 피보팅

On This Rollercoaster Life | 롤코라이프

Your Daily Sporty Life | #오하운, 오늘하루운동

Heading to the Resell Market | N차 신상

Everyone Matters in the 'CX Universe' | CX 유니버스

'Real Me'- Searching for My Real Label | 레이블링 게임

'Ontact', 'Untact' with a Human Touch | 휴먼터치

내용의 첫 시작은 이전 트렌드 코리아 2020에서 시사한 키워드들을 소개하며 시작된다. 

그리고 본격적인 내용의 첫 시작은 바이러스로 인한 변화에 대해 설명한다. 경제면 경제, 기업이나 소비자의 행동 패턴이라던가.. 중요한 것은 바이러스 질병으로 인해 세계 경제가 이렇게 변화하고, 이에 맞춰서 기업이나 소비자들이 어떻게 변화하는가에 대한 전체적인 흐름을 설명한다.
그도 그럴 것이 코로나 역병 형국에 지어진 트렌드와 사회를 묘사해낸 책이기 때문에 가장 중요한 요소이니까.

그 뒤 부터는 코로나로 인해서 변화하는 모든 소비, 생산 활동에 대해서 테마 별로 나누어 쭉 설명한다.

물론 코로나로 인해서 발생하는 변화만 설명하는 것만은 아니다. 각 세대 X세대, Y세대, Z세대의 특성에 맞게 소비 패턴이 변화하는 것 또한 설명으로 나타난다.

그래서 느낌은?

사실, 이렇게 사회 현상을 설명하는 책에 대해서 내용을 요약해서 정리하는 것은 좀 어색했다. 내가 요약하면 그 현상을 정리한 내용이 유포되는 느낌이 들기 때문에 좀 꺼림칙했다. 그래서 이 책에 대한 리뷰에서는 나의 느낌에 좀 더 비중을 둘까 한다.

이 책을 읽는 내내, 내가 들었던 생각은.. '아 이거 사업이라도 해야하나?', 이러한 생각이 압도적으로 많이 들었다.

이러한 시대적인 상황으로 인해서 이렇게 트렌드가 바뀌고...
이러한 세대들의 등장으로 그 세대들의 특징은 이러하니 이렇게 소비 트렌드가 바뀌고...

읽고 있다보면 세상은 이렇게 변화에 발 빠르게 발 맞춰 변화하는데 나 홀로 가만히 서 있는 듯한 느낌을 아주 아주 아주 아주 강하게 많이 받았다. 정말 읽을 때 마다 심각했다.

이렇게 빠르게 변화하고, 전에 없던 교육의 형태가, 전에 없던 소비의 형태가, 전에 없던 업무의 형태가, 전에 없던 마케팅의 형태가 우후죽순으로 생겨나는데 나는 과거의 방식을 고집하고, 과거의 소비를 선호하고.. 이런 것에 대한 생각이 아주 많아진다.

그래서 읽는 내내, 생각했다. 과연 내가 이 책을 읽고 무엇을 얻어가야하는지? 그리고 내가 어떤 점을 개선하고, 어떤 점은 가치 보존해야하는지를 읽는 내내 생각했다. 

내가 낸 결론은 이렇다. 이 책을 읽고 얻어갈 수 있는 것은 아니, 얻어 가야 하는 것은

먼저 첫째로 트렌드이다. 내가 너무 심각하게 생각을 했는가 싶지만 가장 중요한 것은 현재 세계에서는 이러이러한 현상들이 생겨나고, 이러이러한 트렌드들이 유행이라는 그 사실만을 알아가고, 나도 그렇게 행동하면 된다고 생각했다. 왜냐하면 나 또한 트렌드 코리아 2021에서 설명하는 세계의 구성원이기 때문이다. 그렇게 구성원으로서 유행을 따라 행동하는 과정 속에서 편리라는 이득을 취할 수도 있고, 나의 시간을 절약할 수 있는 여러가지 방법들이 책 곳곳에 알게 모르게 서술되어지고 있다.

그리고 둘째로 미래를 분석하는 눈(사고)이다. 사업 아이템을 떠올리기 위한 수준의 미래 분석이 아니다. 이 책은 이미 사회에서 행해지고 있는 현상들에 대해서 분석하고 쓰여진 책이다. 그러니까 모든 서비스나 사업 형태들이 이미 행해지고 있다는 소리이다. 이러한 시장에는 특별함을 더하지 않고서는 뛰어들면 안될 것이라고 생각한다. 내가 생각한 미래를 분석하는 눈은 바로 이 책의 이런 특성 때문이다. 

"어떠한 현상은 어디에서 기인했다."

내가 읽어본 바로, 이 책에서는 항상 위 내용이 포함되어 있다. 이러이러한 현상은 어떤 세대의 어떤 특징 때문이다. 어떤 시대적인 특징으로 인해서 이런 소비 형태가 나타난다. 이런 설명이 항상 따라다닌다. 

즉, 이런 분석하는 사고, 눈을 기를 수 있지 않을까해서 생각해보았다.

세 번째로 얻어가야 한다고 생각하는 것은 기본이다. 책에는 명시되어있지 않는 나의 생각이다. 코로나라는 특수한 상황 흐름에서 기존의 형태가 아닌 다른 형태로 빠르게 발 바꿔서 서비스를 하는 기업들은 살아남았다.

그러나 과연 이 기업들이 전에 없던 사업으로 바꾸어 살아남는 것일까? 그것은 아니라고 본다. 물론 책에는 Best We Pivot 파트에 사업 자체를 바꾸어 코로나 19 상황에서 살아남는 유형을 보여주기는 하지만, 이는 기업이 이전까지 쌓아왔던 기존의 어떤 인프라, 핵심 역량, 정보 등을 바탕으로 하는 것이다. 이러한 것들을 기본이라고 생각한다. 그리고 또한 이 기본을 갖추는 것은 기업에만 해당하는 것이 아니라 개개인에게도 필요하다고 생각한다. 그렇기 때문에 얻어갈 수 있는 것 중 하나로 넣은 것이다.

세 번째 얻음 포인트에서 볼 수 있듯이 내가 보존해야할 가치는 기본이라고 생각한다. 그 어떤 변화가 발생해도 이 기본이 바탕이 되어야 한다. 이 기본을 쌓으려면 시간을 들여야 한다. 그냥 얻을 수 없다. 세상에 공짜는 없다. 

코로나 19 상황에서 살아남을 수 있었던 기업들은 기본에 충실하며, 이를 위해 들인 시간이 압도적으로 많았고, 이렇게 형성된 기본 위에 코로나 상황에 맞게 형태를 변경했기 때문에 살아남을 수 있었다고 본다. 이 책에서는 이러한 내용을 은연 중에 얘기하는 것 같았다.

위와 같은 결론으로 책에 대한 느낌을 마무리를 짓겠다.

이 책을 읽으려거든 사업을 생각하고 있거나, 본인이 트렌드에 대한 자각이 부족하다거나, 다양한 소비나 경제 활동의 유형들을 알고 싶다거나, 유행의 흐름을 보는 안목을 얻고 싶다면 추천한다!

 

728x90
반응형
728x90
반응형
sort(participant.begin(), participant.end());
sort(completion.begin(), completion.end());

for(int i=0; i<participant.size(); i++)
	if(participant[i] != completion[i])
		return participant[i];

#include <algorithm> 의 sort 함수를 이용하여, 참석자 명단과 완주자 명단을 정렬.

그러면 나란히 인덱스를 비교한다. 인덱스를 증가하면서 비교하다가 서로 틀린 부분이 있다면 참석자 측에 해당 인덱스의 사람이 완주를 못한 것이 된다.

또 다른 풀이

#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <iostream>

using namespace std;

string solution(vector<string> participant, vector<string> completion) {
    string answer = "";
    
    map<string, int> m;
    
    for(auto e : participant)
    {
        if(m.find(e) == m.end())
            m[e] = 1;
        else
            m[e] += 1;
    }
    for(auto e : completion)
        m[e]--;
    
    for(auto e : participant)
    {
        if(m[e] > 0)
        {
            answer = e;
            break;
        }
    }
    
    return answer;
}

1. 참여자들을 key로 해서 1씩 증가시킨다 

2. 완주자들을 key로 해서 1씩 감소시킨다.

3. 0이 아닌 친구들이 존재하면 그 친구들은 완주하지 못한 것이다 ㅋㅋ

728x90
반응형

'프로그래밍응용 > 오답노트' 카테고리의 다른 글

SQL1  (0) 2021.02.15
무식하게 완전 탐색! - 모의고사  (0) 2021.02.15
벡터 복사 및 sort 이용  (0) 2021.02.13
우선순위 큐 이용한 문제 ㅋㅋ  (0) 2021.02.13
stack 주식 가격  (0) 2021.02.13
728x90
반응형
 

가끔은 제정신

착각하지 않는다고 착각하는 당신과 우리, 한국사회에 추천한다!우리가 언제, 어떻게, 왜 착각에 빠지는지 적나라하게 밝힌 책 “당신은 평균 이상입니까”라는 질문을 받는다면? 당신은 이 질

www.yes24.com

허태균 저 | 쌤앤파커스 | 2012년 02월 10일

위에 yes24 링크이고, 책 정보 등을 기재했다. 위의 사진처럼 생겼다. 내가 처음에 접했던 이 책은 2013년 군대에서다. 군대 동기가 그렇게 감명 깊게 읽었다고, 한 번 읽어보라고 했던 책을 약 7년 정도 지난 지금에 와서야 다시 읽어본다.

이 책은 심리학 교수님이 쓴 책이라는 것을 알아야한다. 매우 심리학적인 관점에서 접근하지만 교수님의 주변 일상에서 일어나는 많은 에피소드들에 심리학을 푼 형태로 전개되기 때문에 읽으면서 흥미를 느꼈다.

그러나 나에게는 살짝 어려웠다. 뭐랄까.. 일화가 나오면 이 일화가 큰 주제랑 어떤 상관관계가 있는거지? 하고 다시 읽어보는 경우가 좀 많았다.

 

표지와 제목은?

일단 표지부터 보면 바다의 심해를 연상하는 파란색 표지이다. 아마 깊고 깊은 무궁무진한 우리의 정신 세계(의식과 무의식)를 표현하기 위해 파란색 표지로 하지 않았을까 싶다 ㅎㅎㅎ 책의 사이드로 갈수록 색이 더 짙어진다. 이는 더 넓어지고, 더 깊어지는 바다 혹은 인간의 의식/무의식을 나타내는게 아닐까하고 홀로 검증되지 않은 믿음, 착각을 해본다...ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

제목을 딱 처음 봤을 때의 느낌을 적어두지 못했다.. 이게 너무 아쉽다..ㅠㅠ

그래서 모두 읽어본 입장에서 말하자면, 인간은 착각의 상태로 세상을 바라보고, 해석한다. 그러나 이 책을 읽는 순간만큼은 조금은 객관적인 입장에서 평소의 나를 체크해볼 수 있다. 얼마나 착각하고 살았는가? 가끔은 나를 체크해볼 수 있는, 제 정신 상태라는 의미에서 지어진 책 아닐까 싶다!

그래서 내용은?

인간의 착각에 대해서 아주 아주 풀어서 설명한다. 그냥 설명하는 것도 아닌 순서가 있다.

착각이 무엇인지, 그리고 그로 인해 생기는 문제가 무엇인가를 설명한다.

근데, 그 착각은 인간의 삶에 있어서 필요한거야!

근데 또 착각으로 인해 어떤 문제들이 생기지만 이는 어쩔 수 없어!

이러한 착각들을 이용하여 사람 간의 관계에 활용하여 긍정적인 효과를 얻어 보자!

착각은 정말이지 어쩔 수 없어! 매 순간 스스로에게 착각 중인가 물어보면서 주위의 말을 들어 보자!

뭐 이런 식으로 전개가 되는 것 같다.

그러면 느낌은?

책을 읽을 때에는 와 이런 착각을 해왔구나, 이런 착각을 하는데에는 이런 심리에서 기인이 되었구나, 나는 이렇게 착각을 하면서 살았구나.. 라는 생각을 수도 없이 많이 하게 되었다.

정말 객관적으로 나를 돌아보게 되었다. 하지만 나를 객관적으로 봤다는 사실 또한 착각일 수 있다. 이는 마치 무한 반복 같은 느낌이다. 이렇게 무한 반복에 가깝게 착각을 하면서도 그 정체를 느낄 수 없는 착각은 정말 나의 잘못된 선입견, 잘못된 판단에서 올 수 있지만 내가 살아가는데 있어서 꼭 필요한 필수 요소일 수도 있다. 진실을 교묘하게 피해 간 착각을 믿는 행위로부터 나는 행복해질수도, 그와 동시에 타인이 불행해질 수도 있다. 이렇게 착각은 위험하지만 필요한 모순적인 존재라는 생각이 든다.

그렇지만 이러한 착각에는 개인의 문제도 있지만 사회적인 배경 또한 한 몫을 한다. 그렇기 때문에 착각은 절대로 예방하거나 피할 수 없다. 그렇다면 매사에 우리는 생각해야한다. 나의 믿음에 반하는 의견을 들었을 때, 내가 착각하는 것은 아닐까? 하고 말이다.

내 생각에 착각은 그래도 긍정적인 평가보다는 좀 더 부정적인 평가이고, 이를 인지하려고 최소한의 노력을 해야한다고 생각한다.

착각을 할 경우, 내가 얻을 수 있는 것은 "행복한 기분"뿐이다. 진실은 따로 있으며 만에 하나 착각을 나중에라도 인지할 경우에 오는 당혹스러움, 허탈감 또한 내가 감당해야하며, 착각으로 인해 내가 행복해지면 타인이 불행해질 수도 있다. 
그러나 착각을 하지 않으려고 노력했을 경우, 진실을 바로 알 확률이 높으며, 타인을 불행하게 만들 확률이 매우 적어진다. 나의 착각으로 인해서 타인이 불행해지는 등의 침해를 받게 된다면 더 찝찝할 것 같다.. 물론 끝까지 착각하는 경우라면 할 말이 없지만 말이다....ㅜㅜㅠㅠㅠㅠㅠ

그래도 착각은 나의 자존감과 자신감, 행복의 측면에서 보았을 때에는 필요하기 때문에 매사에 착각일까 아닐까? 라는 합리적인 의심이 동반되어 모두가 행복해질 수 있는 건강한 착각이 사회에 널리 퍼졌으면 좋겠다!

책 평가는?

내가 감히 평가를 해보자면 어려운 책이다. 나는 단원 별 주제(대주제)와 소주제가 어떤 상관 관계가 있는지를 따져가며 읽는 타입인데, 이 상관 관계가 파악하기 힘들었다. 그래, 착각은 착각 맞는데, 이게 대주제랑 무슨 상관이야?

어려웠다ㅋㅋㅋ 20년만에 처음 읽은 책인데 어려운 책을 고른 것 같다. 그래도 나를 객관화 해야하는 이유를 알았고, 착각의 모순을 알았고, 착각을 어떻게 활용하면 좋을지 알았으니 매우 뜻 깊은 시간이었다! ( 또 읽어도 될 것 같다 ㅋ )

728x90
반응형
728x90
반응형

C++은 다른 언어들처럼 가비지 컬렉터가 없다ㅋㅋ 그래서 메모리 관리를 제대로 하지 않으면, 정확히 Heap 영역에 대한 메모리 관리가 제대로 되지 않는다면,

헬이다. 헬.

그러면 어찌해야하는가? RAII 라는 디자인 패턴이 있다.

Resource Acquisition Is Initialization 

위를 줄여서 RAII 라고 부른다.

RAII의 유래

그럼 왜 RAII일까? 유래를 좀 찾아봤는데 자원의 획득은 초기화이고, 반대로 자원의 반환은 객체 소멸 뭐 이런 식으로 확장하여 나타내는 어떤 관용구 같은 느낌의 디자인 패턴 개념이다.

RAII란?

좀 더 자세하게 관련해서 정의를 알아 보자면 RAII 는 객체의 생명주기에 관련된 내용으로, C++에서 객체가 생성되고 사용된 Scope를 벗어나면 객체의 자원을 해제해주는 방법을 이야기한다.

즉, 힙에 동적 할당되는 객체라고 해도, 프로그램 실행 흐름이 해당 객체의 유효 scope를 벗어나면 객체를 메모리 해체하도록 하는 것이 RAII라고 생각하면 될 것 같다.

근데 아쉽게도 힙 영역에 할당된 객체는 지역 scope를 벗어난다고해서 동적할당된 부분이 해체되지 않는다. 왜냐하면 동적할당이 이루어지는 해당 scope 내에는 객체 포인터가 스택에 쌓이고, 해당 scope가 끝나면 그 객체 포인터만 스택에서 소멸된다. 동적할당된 메모리는 힙 영역에 그대로 남아있다.

다음과 같이 말이다.

번호순으로 읽기

위의 사실을 응용하여,

어떤 scope에서 동적 할당이 이루어졌다면, 해당 scope에서 스택 영역에 할당되는 요소에게 동적 할당한 주소를 넘겨주고, 그 스택 영역에 할당된 요소는 스택에서 제거될 때, 넘겨받은 동적 할당된 주소를 함께 delete 하면서 제거되면 되지 않을까? 라는 발상이 떠오른다. 아래와 같이 말이다.

번호순으로 읽기

문제가 되는 부분

자, 일단은 문제가 되는 코드이다. 위의 그림과는 살짝 다르지만 문제 없다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
 
class R
{
    private:
        int *data;
    public:
        R(int len)
        {
            this->data = new int[len];
            std::printf("R() call! : new int[%d]\n",len);
        }
        ~R()
        {
            delete []this->data;
            std::printf("~R() call! : delete [] \n");
        }
};
 
void function(void)
{
    R * r = new R(1000);
 
    std::printf("function() 함수 종료\n");
    return;
}
 
int main(void)
{
    function();
    return 0;
}
cs

위의 코드에서 function 함수라는 지역 scope 내에서 객체 R을 동적할당하고, function 함수를 그냥 종료하는 모습이다. 동적 할당된 R 은 소멸되지 않고 그대로 남다가 해당 프로세스가 종료될 때, 비로소 운영체제에 의해서 메모리 자원이 회수된다. 이런 회수를 원한게 아닌데 말이다.

그렇다면 실행 결과를 보자.

분명히, 소멸자가 호출되지 않은 모습이다. 이것이 바로 메모리 누수(Leak)

스마트 포인터

이를 해결할 방법으로 스마트 포인터라는 것이 등장한다. 포인터 역할을 하는 객체로 이 스마트 포인터를 스택 객체로 할당하고 동적 할당 주소를 넘겨주면 스마트 포인터 객체가 소멸될 때 동적 할당된 힙까지 알아서 똑똑하게 삭제를 해주기 때문이다.

이러한 스마트 포인터를 직접 구현해보았다. 다른 이미 구현된 스마트 포인터만큼 스마트하지는 못해서 그냥 오토 포인터라고 이름을 지었다ㅋㅋㅋ

뭐 아래의 연산자 오버로딩 포스팅 때, 구현을 이미 해봤지만 그래도 새롭게 참고하면서 구현해보았다.

 

21 연산자 오버로딩

연산자 오버로딩 연산자 오버로딩 C++언어에서는 연산자의 오버로딩을 통해서 기존에 존재하던 연산자의 기본 기능 이외에 다른 기능을 추가할 수 있다. 먼저 15번 라인을 통해서 operator+ 라는 함

typingdog.tistory.com

코드 및 실행결과

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <iostream>
 
class R
{
private:
    int* data;
    int len;
public:
    R(int _len)
    {
        this->len = _len;
        this->data = new int[_len];
        for (int i = 0; i < _len; i++)
            this->data[i] = i * 100000;
        std::printf("R() call! : new int[%d]\n", _len);
    }
    ~R()
    {
        delete[]this->data;
        std::printf("~R() call! : delete [] \n");
    }
    void ShowData(voidconst
    {
        for (int i = 0; i < this->len; i++)
            std::printf("%d, "this->data[i]);
        std::cout << std::endl;
        return;
    }
};
 
template <typename T>
class AutoPointer
{
private:
     const T* ptr;
public:
    AutoPointer(T* _ptr) : ptr(_ptr)
    {
    }
    ~AutoPointer()
    {
        delete this->ptr;
    }
    const T& operator* () const
    {
        return *(this->ptr);
    }
    const T* operator-> () const
    {
        return this->ptr;
    }
};
 
void function(void)
{
    AutoPointer<R> r(new R(10));
    r->ShowData();
    std::printf("function() 함수 종료!\n");
    return;
}
 
int main(void)
{
    function();
    return 0;
}
cs
힙 영역의 객체의 소멸까지 책임지는 스마트 포인터 똑똑해^^7

이렇게 힘들게 만들었는데 이미 C++ 11에서는 다음과 같은 문법을 제공한다.

 

unique_ptr<> : #include <memory>

이미 11 문법에서는 겁나 스마트한 포인터 객체로 제공을 해주었던 것이다... 사용 방법은 내가 만든 오토 포인터와 같으니 바로 예제로 들어가보겠다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <memory>
 
class R
{
    private:
        int *data;
    public:
        R(int len)
        {
            this->data = new int[len];
            std::printf("R() call! : new int[%d]\n",len);
        }
        ~R()
        {
            delete []this->data;
            std::printf("~R() call! : delete [] \n");
        }
};
 
void function(void)
{
    std::unique_ptr<R> r(new R(1000));//R * r = new R(1000);
    std::printf("function() 함수 종료\n");
    return;
}
 
int main(void)
{
    function();
    return 0;
}
cs

불안정한 메모리 관리를 이러한 패턴으로 처리한다는게 정말 잔머리를? 기가막히게 잘 굴린듯한 느낌이다. 그래도 GC(가비지 컬렉터)가 제공되면 참 좋겠지만 이렇게라도 일부라도 관리를 틈틈이 하는게 좋은 것 같다.

다음 번 포스팅에서는 (공부하다가 필요한 부분부분 정리하는 포스팅이기 때문에 시리즈물처럼 바로 다음 번은 아니지만) 이 unique_ptr 외에 공유 가능한, 그리고 인자로의 전달 시 어떤 형태로 코드를 짜야하는 지 등에 대해서 올려볼 것이다.

728x90
반응형
728x90
반응형

오늘은 C++에서의 쓰레드이다

지겹게 기억을 더듬어가면서 C기반의 포스팅을 했던 적이 있는데 C++에서도 지원을 한다니 새로웠다.

 

C기반 I/O Multithreading - 12. 멀티 프로세싱? 멀티 쓰레딩?

멀티 프로세싱에 이어서, 멀티 프로세싱의 단점이 보완되는 멀티 쓰레딩 개념이다. 사실 단점이 보완되기는 하는데 함께 딸려오는 문제 거리도 만만치 않기 때문에 좀 상세히 볼 필요가 있다ㅋ

typingdog.tistory.com

위 링크는 쓰레드

C++ 에서의 쓰레드

원래 쓰레드의 생성과 사용은 OS에 종속적이었고, API가 C 기반이었다. 하지만 C++ 11 표준에 쓰레드 라이브러리가 따로 들어가면서 OS에 독립적이고, 프로그래밍 언어 차원에서 지원이 된다.

임계 영역과 관련된 문제는 Mutex를 통해서 상호배제를 처리할 것인데 이 또한 C++ 프로그래밍 언어 차원에서 지원이 된다는 것이다. 그래서 C 기반의 코드를 그대로 C++ 코드로 변경하도록 해보겠다. 

일단 간단하게 쓰레드 사용과 그에 동반하는 문제까지 설명하자면,

공용 데이터 영역의 변수(전역 변수)

쓰레드에서 공통으로 접근할 수 있는 데이터 영역의 변수를 두 쓰레드에서 임계영역에서 사용이 되면서 기대하는 값과 다른 결과가 나오는 것에서부터 문제가 된다.

쓰레드 A와 쓰레드 B에 해당하며 동일한 횟수만큼(백만) 증감

쓰레드 A에서는 동일한 횟수만큼 (1,000,000) 공용 Data 영역 변수를 1씩 증가시키고, 쓰레드 B에서는 동일한 횟수만큼 (1,000,000) 공용 Data 영역 변수를 1씩 감소시킨다.

기대하는 값은 0 이겠지만(동일한 횟수만큼 1씩 증가시키고, 감소시켰기 때문) 쓰레드 동기화가 이루어지지 않은 탓에 0이 아닌 다른 값이 나온다.

문제에 대한 자세한 설명은 아래의 링크를 통해서 확인하면 된다.

 

C기반 I/O Multithreading - 14. 쓰레드의 치명적인 문제점

C기반 I/O MultiThreading - 12. 멀티 프로세싱? 멀티 쓰레딩? 멀티 프로세싱에 이어서, 멀티 프로세싱의 단점이 보완되는 멀티 쓰레딩 개념이다. 사실 단점이 보완되기는 하는데 함께 딸려오는 문제 거

typingdog.tistory.com

C언어 기반 쓰레드 구현(Mutex)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
 
pthread_mutex_t mutex;
int common_value = 0;
 
void* t_main_plus(void *arg);
void* t_main_minus(void *arg);
 
int main(void)
{
    pthread_t tid1, tid2;
 
    pthread_mutex_init(&mutex, NULL);
 
    pthread_create(&tid1, NULL, t_main_plus, NULL); // 쓰레드 생성
    pthread_create(&tid2, NULL, t_main_minus, NULL); // 쓰레드 생성
 
    pthread_detach(tid1); // tid1 에 해당하는 쓰레드가 종료됨과 동시에 소멸.
    pthread_detach(tid2); // tid2 에 해당하는 쓰레드가 종료됨과 동시에 소멸.
 
    sleep(7); // 종료되지 않도록 대기.
    pthread_mutex_destroy(&mutex);
    printf("메인함수가 종료됩니다. [common_value의 최종 값 : %d]\n",common_value);
    return 0;
}
 
void* t_main_plus(void *arg)
{
    int i = 0;
 
    printf("t_main_plus 쓰레드가 연산을 시작합니다. \n");
 
    pthread_mutex_lock(&mutex);
    for(i=0; i<1000000; i++// for을 중복해서 쓴 것은 100번 type을 검사하는 것보단 났다고 생각.
        common_value+=1;
    pthread_mutex_unlock(&mutex);
 
    printf("t_main_plus 쓰레드가 종료됩니다.\n");
    return NULL;
}
 
 
void* t_main_minus(void *arg)
{
    int i = 0;
 
    printf("t_main_minus 쓰레드가 연산을 시작합니다. \n");
 
    pthread_mutex_lock(&mutex);
    for(i=0; i<1000000; i++// for을 중복해서 쓴 것은 100번 type을 검사하는 것보단 났다고 생각.
        common_value-=1;
    pthread_mutex_unlock(&mutex);
 
    printf("t_main_minus 쓰레드가 종료됩니다.\n");
    return NULL;
}
cs

C++언어 기반 쓰레드 구현(Mutex)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <thread>
#include <mutex>
 
std::mutex mtx;
int comm_value = 0;
 
int main(void)
{
    std::thread t1([]() { mtx.lock(); for (int i = 0; i < 1000000; i++)    comm_value--; mtx.unlock(); });
    std::thread t2([]() { mtx.lock();  for (int i = 0; i < 1000000; i++)    comm_value++; mtx.unlock(); });
 
    t1.join();
    t2.join();
 
    std::cout << "comm_value의 값은 : " << comm_value << std::endl;
    return 0;
}
cs

 

위의 코드가 아래의 코드로 변환되었다고 생각하면 된다. 너무 간단하게 몇 줄이면 끝났다ㅋㅋㅋㅋ

끝.

728x90
반응형

+ Recent posts