전자공학과를 졸업하고 개발쪽일을 한다고하면 주변 사람들은 컴퓨터 박사네 뭐네 이야기하지만

아실 분들은 모두 아실겁니다. 그건 큰 착각이라는걸.

분야가 얼마나 넓은데 대부분은 자기 하는 것만 알지 두루두루 알진 못하죠. ㅎㅎ

 

대학교때부터 지금까지 쭉 노트북만 사용하다보니 데스크탑 구매를 결심했지만 어렵더군요.

 

커뮤니티에 들어가서 구매해야되는 부품들이 뭐가있고 어떤 걸 보고 골라야하는지 공부도 하고 유튜브에서 조립 영상이나 시세 비교 영상도 이것 저것 찾아봤죠. 그래도!~ 아직도 어렵습니다. ㅠㅠ

링크1 링크2

 

그래도 이러나저러나 컴퓨터를 구매했습니다.

 

구매 내역

케이스는 퀘이사존에서 매 주말마다 특가로 판매하는 걸로 사서 저렴하게 샀습니다.

처음엔 본체만 80만원 생각했는데 계산해보니까 총 873,180 원 결제했네요. ㄷㄷ

주변에서 "이게 좋다, 저건 바꿔야된다" 얘기를 들으니 7만원 정도 초과했습니다.. (팔랑귀의 숙명이란...ㅋㅋ)

 

그래도 택배를 받을 땐 기분이 참 좋죠.

조립은 설명서를 보면서 했습니다.

조립중 두 가지 문제를 겪었는데요.

 

    1. 메인보드와 케이스 결합

    2. 메인보드에 그래픽카드 결합

 

1번 문제는 결합 나사를 잘못 선택해서 발생한 문제였습니다.

MSI 메인보드 설명서

설명서 그림에 나온 모양의 나사는 그래픽카드 결합나사였구요.

(이 것 때문에 얼마나 진땀을 흘렸는지 설명서 만든 사람 꿀밤을 맥여주고 싶네요.)

 

아래 나사가 메인보드 결합나사입니다. 초보자분들은 주의하세요!!!

메인보드 결합나사

잘보면 나사 밑이 쟁반?접시? 모양입니다.

 

2번 문제는 결합된 메인보드에 그래픽카드가 안꽂아지는 문제였는데요.

메인보드나사를 다 풀고 그래픽카드 꼽고 메인보드 잘 밀어넣어서 나사를 조이니 됐습니다.

흔히들 얘기하는 아다리가 안맞는 문제였던거죠.

 

참 힘들었지만 그래도 재미도 있었던 것같네요.

다음엔 더 잘할 수 있을 것 같습니다. ㅋ

이렇게 인생 첫 조립컴 구입기를 마칩니다! (뿌듯)

'OLD > 생활' 카테고리의 다른 글

중소기업청년전세대출 후기  (0) 2020.05.19
고시원 생활 후기  (3) 2020.05.06
혀 깨물어서 병원간 후기  (0) 2020.04.29
[구매 후기] 80만원대 동생 데스크탑 컴퓨터  (0) 2020.04.21
지방종 제거 수술 후기  (2) 2020.04.07

회사 들어온게 엊그제 같은데 벌써 10달이 지났다.

지금까진 기존에 누가 MFC로 작성해놓은 앱 코드를 가지고 분석하고 변경하는 일을 했다.

MFC는 MSDN이라는 가이드를 제공하는데 한글판은 너무 발번역이고 영어판은 영어를 못해서 읽기가 힘들다.

그나마 MFC가 오래된 덕인지 블로그나 카페에 자료가 많아 검색하는 족족 어렵지 않게 원하는 내용을 찾을 수 있었다.

 

이번엔 Apple Accessories와 관련된 일을 하게됐다.

필요한 자료를 찾아보는데 한글로 된건 역시나 발번역본이고 그나마도 복붙을 한건지 비슷한게 여러벌 돌아다닌다.

결국 영어로 제공되는 자료를 읽는데 이해도 안될뿐더러 시간도 굉장히 오래걸린다.

너무 비효율적이다.

 

이전에 MSDN 페이지에서 글을 읽는데 소요되는 예상시간이 적혀있던게 기억난다.

보통 2분, 3분 등 짧은 시간이 적혀있다.

당시엔 읽는 것 자체를 포기했지만, 읽었더라도 절대 2분, 3분만 걸리진 않았을 것이다.

원어민이 새삼 부럽다.

 

내가 이 일을 계속하게된다면 앞으로 영어 자료를 많이 읽게 될 것이다.

영어 자료를 쉽게 잘 읽을 수 있는가? 하는 것은 정말 중요한 능력인것 같다.

시간대비 효율이 좋다는 거니까.

앞으로 시간이 날 때마다 조금씩이라도 영어 자료를 읽고 내용을 이해하는 연습을 해보려한다.

 

가성비 좋은 개발자가 되어보자.

복기

 

먼저 이 문제는 제가 풀지못한 문제입니다. 결국 다른 사람의 풀이를 보고 풀었죠...ㅜㅜ

 

구슬이 중간에서 터지면 위의 구슬이 떨어져서 밑이랑 색이 같으면 또 터지는 뿌요뿌요 게임처럼 삭제된 문자열 좌우 문자를 붙혀서 A 문자열이 나오면 또 삭제를 해줘야하는 점이 아마 이 문제를 까다롭게 만드는 점인 것 같은데요.

 

먼저, 아래는 다른 사람 풀이를 보고 작성한 코드입니다.

 

더보기

 

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
// 검열
#include <stdio.h>
#pragma warning(disable : 4996)
char A[35], T[300015], s1[300015], s2[300015], b;
int len, l, r, t1, t2;
 
char check(void) {
    if (0 == b) {
        if (t1 < len) return 0;
        for (int i = 1; i <= len; i++) {
            if (s1[t1 - i] != A[len - i]) {
                return 0;
            }
        }
    }
    else {
        if (t2 < len) return 0;
        for (int i = 1; i <= len; i++) {
            if (s2[t2 - i] != A[i - 1]) {
                return 0;
            }
        }
    }
    return 1;
}
int main(void) {
    scanf("%s %s", A, T);
    for (len = 0; A[len]; len++);
    for (r = 0; T[r + 1]; r++);
 
    while (l <= r) {
        if (0 == b) {
            s1[t1++= T[l++];
            if (s1[t1 - 1== A[len - 1]) {
                if (check()) {
                    t1 -= len;
                    b ^= 1;
                }
            }
        }
        else {
            s2[t2++= T[r--];
            if (s2[t2 - 1== A[0]) {
                if (check()) {
                    t2 -= len;
                    b ^= 1;
                }
            }
        }
    }
    b = 0;
    while (t2) {
        s1[t1++= s2[--t2];
        if (s1[t1 - 1== A[len - 1]) {
            if (check())
                t1 -= len;
        }
    }
    s1[t1] = 0;
    return !printf("%s\n", s1);
}// 1
cs

 

위 코드가 제가 맨처음 작성했던 코드와 다른 점은 비교를 앞에서부터 하는가 뒤에서부터 하는가 입니다.

 

글이 좀 애매한데 어떤 의미인가 하면

 

 
 A: aac


 T: aaaaaaccc

 

위의 입력이 주어졌을 때, T의 왼쪽에서부터 A 문자열과 일치하는 문자열을 찾는 상황에서

 

앞에서부터 비교한다는건 (a a c 순으로 비교) 아래와 같이 일치하는 문자열을 찾았을 때 인덱스가 4 가 되는 것이고

 

뒤에서부터 비교한다는건 (c a a 순으로 비교) 인덱스가 6 일 때 아래 상황이 되는 겁니다. 

 

 
 aaaa (aac) cc



별 것 아닌 차이 같지만 앞문자부터 비교하면 삭제후 다음 인덱스부터 앞방향 탐색 범위에 삭제 때문에 끊기고 뒤에 남은 문자들이 포함되지 못합니다. 추가로 뭔 짓거리를 더 해줘야 하는 셈이죠. : aaaa (c->) c

 

반면에 뒷문자부터 비교하면 삭제후 다음 인덱스로 옮겨도 버퍼 안의 내용과 비교하면 탐색하던 방향 그대로 뒤에 남은 문자들을 포함해서 비교할 수 있죠 : aaaa (<-c) c

 

물론 전자처럼 구현해도 관계는 없을 겁니다. 하지만, 확실히 후자가 쉬운 길인 것 같네요.

 

더보기
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
67
68
69
70
71
72
73
74
75
76
77
// 검열
#include <stdio.h>
#include <string.h>
#pragma warning(disable : 4996)
volatile char A[33], T[300015];
volatile int len, f, r;
 
struct Stack {
    char data[300015];
    int top;
} s1, s2;
void Push(Stack *ps, char in)    { ps->data[ps->top++= in;    }
char Pop(Stack *ps)                { return ps->data[--(ps->top)];    }
int GetCount(Stack *ps)            { return ps->top; }
 
int main(void) {
    scanf("%s %s", A, T);
    for (len = 0; A[len]; len++);
    for (r = 0; T[r]; r++);
    
    char bSame;
    int n;
    while (r - f >= len) {
        while (r - f >= len) {
            bSame = 1;
            for (int i = 0; i < len; i++) {
                if (T[f + i] != A[i]) {
                    bSame = 0;
                    break;
                }
            }
            if (bSame == 0
                Push(&s1, T[f++]);
            else {
                n = GetCount(&s1);
                n = n < len - 1 ? n : len - 1;
                f += len - n;
                for (int i = n - 1; i >= 0; i--)
                    T[f + i] = Pop(&s1);
            }
            while (GetCount(&s2) > 0 && r - f < len) {
                T[r++= Pop(&s2);
                T[r] = 0;
            }
            if (bSame == 1break;
        }
        while (r - f >= len) {
            bSame = 1;
            n = r - len;
            for (int i = 0; i < len; i++) {
                if (T[n + i] != A[i]) {
                    bSame = 0;
                    break;
                }
            }
            if (bSame == 0
                Push(&s2, T[--r]);
            else {
                n = GetCount(&s2);
                n = n < len - 1 ? n : len - 1;
                r -= len - n;
                T[r] = 0;
                for (int i = n; i > 0; i--)
                    T[r - i] = Pop(&s2);
            }
            while (GetCount(&s1) > 0 && r - f < len) 
                T[--f] = Pop(&s1);
            if (bSame == 1break;
        }
    }
    while (GetCount(&s1) > 0)
        T[--f] = Pop(&s1);
    while (GetCount(&s2) > 0)
        T[r++= Pop(&s2);
    T[r] = 0;
    return !printf("%s\n", T + f);
} // 2
cs

 

 

위 코드는 전자 방법으로 푼 코드이고 문자열 삭제후 뒤에 남은 문자랑 비교하려고 (A 문자열 길이 -1) 개 문자를 저장 버퍼에서 빼는... 쓰잘데기 없이 일을 만들어서 하는 방법입니다. 

 

그리고, 사실 이 코드는 틀린 코드입니다. 이유는 잘 모르겠지만 "출력 초과"로 나오네요.. ㅠ_ㅠ

 

'일단 머리좀 식히고 답을 잊을 때쯤 다시와서 틀린 이유를 찾아보자' 는 의미에서 이 코드도 남깁니다.

 

혹여 지나가던 고수님께서 이유를 집어 주신다면 감사할 따름이고요 ㅎㅎ.

 

복기끝

 

 

사실 지금 든 생각이지만 이 것도 시작 문자 한 개만 버퍼랑 비교하고 나머지는 T랑 비교하면 전자나 후자나 다를게 없겠다는 생각이 드네요............. 

지금까지 쓴 글이... ++'

'개발 > c' 카테고리의 다른 글

[백준] 17825 주사위 윷놀이  (0) 2020.04.24
[백준] 17822 원판 돌리기  (0) 2020.04.22
[백준] 4179 불!  (0) 2018.12.13
winpcap pcap_pkthdr 구조체에서 caplen과 len의 차이  (0) 2018.12.01
ffmpeg 라이브러리 사용법  (2) 2018.11.16



복기



이 전에 이와 비슷한 문제를 푼 적이 있었고 풀면 풀리겠다 생각했습니다. 


네... 방심을 했던거죠. 저의 전략은 이랬습니다.


일단, 불을 BFS로 먼저 퍼뜨립니다.


이 때, 맵의 각 칸에 언제 불이 도달하는지에 대한 값을 써넣습니다.


이후 지훈이를 큐에 넣고 똑같이 BFS를 돌립니다.


큐안에 들어간 지훈이는 현재의 시간값?!을 가졌기 때문에 주위 칸에 도착했을 때


이 칸이 이미 옛날 옛적에 불에 뒤덮힌 칸인지, 아직 불이 오지 않은 칸인지 알 수 있습니다.



사실 위와 같은 풀이는 방문 여부를 check하는 배열을 맵으로 대신해서 메모리를 아껴보고자 하는 욕심에서


비롯된 풀이였습니다만, 이때 저는 지훈이의 방문을 check하지 않는 실수를 범합니다.


지훈이가 시간 값을 가지기 때문에 불이 일찍이 덮친 칸들로 이동하지 못하고 (큐에 들어가지 못하고)


루프가 종료될 것으로 생각했습니다.



하지만, 불이 애초에 가지 못한 곳은 지훈이가 이동하면서 check해주지 않으면 영원히 0의 값을 가지게 됩니다.


큐가 터지게 되는거죠...


런타임 에러를 보고도 여기까지 생각하지 못하고 뭐지? 하며 황당했던 지난 날의 나를 용서합니다. ㅋ


결국 답답함을 이기지 못하고 다지우고 visit 배열을 사용해서 문제를 풀었고


다시 푸는 과정에서 위와 같은 케이스, 예를 들면, 5 5 에서


 #

 #

 #

 #

 #

 #

 .

 .

 .

 #

 #

 .

 J

 .

 #

 #

 .

 .

 .

 #

 #

 #

 #

 #

 #

 

이와 같이 입력이 주어져 지훈이가 벽 안에서 계속 싸돌아 다니게 되는... 경우를 생각하게 됐습니다.


이후 지훈이의 방문 확인도 맵을 이용하면서 결국 visit 배열 메모리를 아껴서 문제를 다시 풀었습니다.


오기로 풀었습니다. ㅋㅋ




코드
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
#include <stdio.h>
 
struct Crd { int x, y; };
int in[1010][1010];
Crd q[1000010];
int f, r;
int main(void) {
    int R, C, sx, sy, x, y, xx, yy, i, j;
    char ct;
    scanf("%d %d"&R, &C); getchar();
    for (i = 0; i < R; i++) {
        for (j = 0; j < C; j++) {
            ct = (char)getchar();
            if (ct == 'J') sx = i, sy = j;
            else if (ct == '#') in[i][j] = -1;
            else if (ct == 'F') in[i][j] = 1, q[r].x = i, q[r++].y = j;
        }
        getchar();
    }
 
    while (f < r) {
        x = q[f].x, y = q[f++].y;
 
        for (i = 0; i < 4; i++) {
            xx = x + "1210"[i] - '1';
            yy = y + "2101"[i] - '1';
 
            if (xx < 0 || R <= xx || yy < 0 || C <= yy || in[xx][yy]) continue;
            in[xx][yy] = in[x][y] + 1;
            q[r].x = xx, q[r++].y = yy;
        }
    }
 
    f = r = 0;
    q[r].x = sx, q[r++].y = sy;
    in[sx][sy] = 1;
    int ans = 0x7fffffff;
 
    while (f < r) {
        x = q[f].x, y = q[f++].y;
        if (x == 0 || y == 0 || x == R - 1 || y == C - 1) {
            ans = in[x][y];
            break;
        }
 
        for (i = 0; i < 4; i++) {
            xx = x + "1210"[i] - '1';
            yy = y + "2101"[i] - '1';
 
            if (xx < 0 || R <= xx || yy < 0 || C <= yy) continue;
            if (in[xx][yy] && in[xx][yy] <= in[x][y] + 1continue;
            in[xx][yy] = in[x][y] + 1;
            q[r].x = xx, q[r++].y = yy;
        }
    }
 
    if (ans == 0x7fffffffprintf("IMPOSSIBLE");
    else                   printf("%d", ans);
    return 0;
}
cs


복기 끝.

'개발 > c' 카테고리의 다른 글

[백준] 17822 원판 돌리기  (0) 2020.04.22
[백준] 3111 검열  (0) 2019.03.05
winpcap pcap_pkthdr 구조체에서 caplen과 len의 차이  (0) 2018.12.01
ffmpeg 라이브러리 사용법  (2) 2018.11.16
ffmpeg 이란?  (1) 2018.11.02

winpcap man page에서 "pcap_pkthdr" 이란 구조체를 봤습니다.

 

확실하진 않지만 winpcap을 사용하면 LAN으로 들어오는 데이터들을 Packet 단위로 읽을 수 있는 것 같습니다.

 

이 때, 각 Packet은 "헤더 + 페이로드" 로 분류가 되고

 

"pcap_pkthdr" (packet capture - packet header) 는 그 이름처럼 헤더에 대한 정보를 받아옵니다.

 

이 구조체에는 아래처럼 딱 세가지 멤버가 있습니다.

 



struct timeval ts;
bpf_u_int32 caplen;
bpf_u_int32 len;

 

여기서 caplen과 len의 차이가 뭘까? 궁금해서 찾아봤습니다. 출처

 

결론만 말하자면 caplen은 captured length 실제 읽은 길이를 뜻하고

 

len은 이번에 capture한 packet의 length를 뜻하는 것 같습니다.

 

 

무슨 말인고... 영어는 잘못하지만 나름 해석을 해보니

 

packet을 받기전에 앞으로 받을 packet의 최대 길이를 설정할 수 있다는 것 같습니다.

 

 

예를 들면, pcap은 packet 단위로 데이터를 가져다 주는데 이번에 들어온 packet은 길이가 100입니다.

 

그런데 처음에 한 번에 읽을 최대 길이를 60으로 설정했다면

 

실제 읽은 데이터 길이 (caplen) 은 60이 되고 capture한 packet의 실제 길이 (len)은 100이 됩니다.

'개발 > c' 카테고리의 다른 글

[백준] 17822 원판 돌리기  (0) 2020.04.22
[백준] 3111 검열  (0) 2019.03.05
[백준] 4179 불!  (0) 2018.12.13
ffmpeg 라이브러리 사용법  (2) 2018.11.16
ffmpeg 이란?  (1) 2018.11.02

+ Recent posts