study2015. 4. 2. 11:41

Visual Studio를 사용해서 알고리즘 연습혹은 구현하다 보면 TC (Test Case)의 데이터를 파일로 부터 읽어올 일이 생긴다.

예를 들면 아래코드에서 주석 처리된 부분, input.txt를 freopen을 이용해서 stdin으로 출력 할 수 있지만,

Visual Studio Project properties에 Command line을 설정해서 간단하게 처리 할 수 있다.

#include <stdio.h>


int main(void)

{

int T;

int N, K;


  //freopen("input.txt", "r", stdin);

setbuf(stdout, NULL);

scanf("%d", &T);


for (int tcIdx = 1; tcIdx <= T; ++tcIdx)

{

scanf("%d\n", &N);

scanf("%d\n", &K);

printf("%d, %d, %d\n", tcIdx, N, K);

}


return 0;

}


Visual Studio Menu -> Project -> (your project name) Properties... -> Configuration Properties -> Debugging -> Command Arguments 를 보면 텍스트 필드가 있는데 아래처럼 적는다.

< input.txt


만약 Console에 출력되는 값을 파일로 저장하고 싶다면? 이때도 Command Arguments 을 이용하면 된다.


< input.txt > output.txt

이렇게 하면 입력은 input.txt로 출력은 output.txt로 한다.


++ 추가 

setbuf를 썼는데 빌드 할 때 아래와 같은 에러가 발생하면.

error C4996: 'setbuf': This function or variable may be unsafe. Consider using setvbuf instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.


Visual Studio Menu -> Project -> (your project name) Properties... -> Configuration Properties -> C/C++ ->Preprocessor -> Preprocessor Definitions 에 _CRT_SECURE_NO_WARNINGS을 추가 해주자.


Visual Studio Menu -> Project -> (your project name) Properties... -> Configuration Properties -> Linker -> System -> SubSystem 을

Console (/SUBSYSTEM:CONSOLE) 으로 하면 프로그램 실행 이후에도 콘솔창이 사라지지 않는다.






Posted by 평면우주
study2015. 1. 29. 15:41

카운팅 소트 설명.

http://en.wikipedia.org/wiki/Counting_sort 

역시 C언어로 간단하게 구현해 보았다.


//# counting sort.

#include <stdio.h>


#define MAXLEN 10


void main()

{

int Data[MAXLEN] = {8, 1, 3, 2, 9, 9, 7, 10, 5, 2}; // item is 1 <= N <= 10

int ret[MAXLEN] = { 0, };

int count[MAXLEN];

int idx = 0;


//init count index

for (int i = 0; i <= MAXLEN; i++)

count[i] = 0;


for (int i = 0; i < MAXLEN; i++)

{

count[Data[i]] += 1;

}

idx = MAXLEN - 1;

for (int i = MAXLEN; i > 0; i--)

{

while (count[i] > 0)

{

ret[idx--] = i;

count[i] -= 1;

}

}


printf("{");

for (int i = 0; i < MAXLEN; i++)

{

printf("%d,", ret[i]);

}

printf("}\n");

}





Posted by 평면우주
study2015. 1. 29. 11:05

문자열 검색 알고리즘 간단히 설명하면 문자열을 검색할 때 앞에서 부터 하는게 아니라 뒤에서 부터 시작하는 알고리즘이다.

비교를 하다가 문자가 다르다는 것을 알았다면, 그 문자가 검색키 문자열에 포함되어 있다면 그 만큼 이동함.

그 문자가 포함되어 있지 않다면 검색키 문자열 길이만큼 점프.

자세한건 아래 참고.

http://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm

간단하게 C언어로 구현해 보았다.

#include <stdio.h>


#define MAXLEN 1000


int mystrlen(char *m)

{

int n = 0;

while (*m != '\0') {

*m++;

n++;

}

return n;

}


bool compareString(char s[], char k[], int idx, int keyLen, int* jumpIdx)

{

int last = keyLen-1;

bool matchFlag = true;


for (int i = (idx + last); i >= 0; i--)

{

//printf("s[%d]=(%c), key[%d]=(%c)\n", i, s[i], last, k[last]);


if (s[i] == k[last])

{

if (last == 0)

{

*jumpIdx = keyLen;

return true;

}

}

else {

for (int j = last-1; j >=0; j--)

{

if (k[j] == s[i])

{

*jumpIdx = keyLen-j-1;

return false;

}

}


*jumpIdx = keyLen;

return false;

}


last--;

}

return false;

}


void main()

{

char source[MAXLEN] = "tomato dog cat radio good";

char key[10] = "cat";

int keyLen = mystrlen(key);

for (int i = 0; source[i] != '\0';)

{

int jump = 0;


//printf("\n==>\n");

//for (int j = 0; j < keyLen && source[i + j] != '\0'; j++)

//{

// printf("%c", source[i + j]);

//}


//printf("\n");

//for (int j = 0; j < keyLen ; j++)

//{

// printf("%c", key[j]);

//}


//printf("\n==<\n");


bool a = compareString(source, key, i, keyLen, &jump);

if (a)

printf("match");


i += jump;

}

printf("n=%d", mystrlen(key));


printf("\n");

}





Posted by 평면우주
study2015. 1. 9. 15:39

#include <stdio.h>
#define MAX_LEN 10

void swap(int*a, int* b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}

int partition(int d[], int l, int r) //l is left, r is right.
{

int first = l;
int pivot = d[first];
++l; //shift.

while (l < r)

{
while (d[l] <= pivot)
++l;
while (d[r] > pivot)
--r;

if (l < r)
swap(&d[r], &d[l]);
else
break;
}

swap(&d[first], &d[r]);
return r;
}


int partition2(int d[], int l, int r) // p is pivot index.

{

int last = d[r];
int sortIdx = l;

for (int i = l; i <= r-1; i++)

{

if (d[i] <= last)
{
swap(&d[i], &d[sortIdx]);
sortIdx++;
}
}

swap(&d[sortIdx], &d[r]);
return sortIdx;

}

void qsort(int d[], int l, int r)

{
printf("l=%d, r=%d\n", l, r);

if (r > l){
//int idx = partition(d, l, r);
int idx = partition2(d, l, r);
qsort(d, l, idx - 1);
qsort(d, idx + 1, r);
}
}


int main()

{

int i = 1;

int j = 2;

int data[MAX_LEN] = { 3, 7, 8, 5, 2, 1, 9, 5, 4, 6};
qsort(data, 0, MAX_LEN-1);

for (int k = 0; k < MAX_LEN; k++)
     {
    printf("%d,", data[k]);

}

printf("\n%d\n", i);

}


분할 정복 알고리즘의 대표적인 소팅 알고리즘 partition 값을 구하는 방법은 전통적인 알고리즘 버젼과 MIT에서 제안한 방법 2가지 모두 구현해 보았다.

Posted by 평면우주
bicycle2014. 6. 2. 09:57

자전거로 출근 중 갑자기 자전거에서 잡소리가 나기 시작했다.


불규칙적으로 딱... 딱... 거리는 소리.


패달링을 하지 않고, 타력 주행 중에서도 소리가 난다. 


BB는 패달링을 해야지 잡소리가 나는 거라서 BB쪽 문제는 아닐거라고 확신하고.


처음엔 스포크 쪽에서 문제가 생긴거 아닐까? 점검했지만 스포크도 정상이고 휠 정렬도 양호한 상태였음.


바디도 물론 정상. 


심지어는 자전거를 끌고 가도 가끔 소리가 났다. 


딱딱 소리도, 보통은 딱..딱 이어서 나고, 종 종 딱... 한번만 나기도 했다.


휠 분해를 해서 점검을 하는데, 베어링이 이상하다는 것을 알게됨.


zipp 303 188 허브+ 바디 에는 베어링이 모두 4개가 들어 가는데 (2개는 허브, 2개는 바디.) 허브쪽 베어링을 손으로 굴리면 걸리는 느낌이 났다.


zipp 188 hub는 스위스에서 만든 61803 type 베이링을 쓴다. (http://www.zipp.com/support/identify/bearings.php)


이베이에서 zipp 베어링 가격이 2개 한 세트에 40달러. 2 세트 필요하니 총 80 달러에 살 수 도 있지만. 


한국 옥션에서 베어링을 검색 1개에 3천원 짜리 독일 61830 베어링을 구입했다.  (총 12000 원 + 2500(배송비)


샾에서 베어링을 교체했더니 소리가 싹 사라졌다. 


만약 위와 같은 사례라면 베어링도 의심 해보길.






Posted by 평면우주
everythings2014. 5. 15. 09:02



기특한 고양이 , 45초 뒤 부터는 혐짤이 있으니 주의 바람.

Posted by 평면우주
universe2014. 5. 14. 15:12


MIT에서 초기 우주로 부터 130억년 동안을 시뮬레이션 했다. 8000개의 cpu를 사용해서 3개월 동안 작업을 했다고 하는데.


만약 일반 PC로 작업했으면 2000년 걸릴 연산량이라고 한다.


막상 동영상은 들인 시간에 비해서 다이나믹 하지는 않지만, 신기하게 현재 관측 가능한 우주에서 볼 수 있는 거품구조가 시뮬레이션을 통해서 재현이 이 된다.


Posted by 평면우주
bicycle2014. 5. 8. 16:19

 

시마노 Di2 사용하면서 가장 큰 불만은 매끈한 자전거 프레임에 보기 싫게 툭 튀어 나온 배터리였다.


보통은 다운 튜브 물통 케이지 아래 부분에 오게 설치하고, 몇 몇 프레임은 BB 아래 설치를 하는데 어찌 되었던 보기가 좋지 않다.


특히 배터리와 배터리 마운트 색이 단일 회색 + 검정색!!! 


하얀색 프레임에는 하얀 건반에 코딱지가 묻은 것 같은 느낌이 든다. ㅋ~


중고로 시마노 울테그라 Di2 6770을 구입해서 설치할 때 부터 저 배터리가 맘에 걸렸다.


  

<여러가지 배터리 마운트 모습, 특히 다운 튜브에 고정하기 위해서 케이블 타이를 두른 모습, 정말 참을 수 없었다.!!!>


그래서 시마노에서 싯포스트 내장형 배터리를 내 놓기 전부터 사설 업체에서 배터리를 프레임 혹은 싯포스트 안으로 매립하는 부품들을 팔았다.


가격은 300 달러 정도.  비싸다...


 

< icarus- 싯포스트 안에 넣는 방식, 시마노 di2 내장 배터리 SM-BTR2>


이후 시마노에서 프레임 안으로 매립할 수 있는 인터널 배터리 SM-BTR2를 내 놓았지만 가격이 ... 역시 비싸다..


SM-BTR2는 그 전 모델의 배터리 + 배터리 마운트 기능을 합쳐 놓은 것이다. 아마도 6770에 꼽으면 바로 사용 할 수 있을 것이다. (추측임)


하지만 배터리가 내장형이기 때문에 충전할 때 마다 안장을 뽑기 귀찮다...잘 못하다간 잘 맞춰놓은 피팅이 틀어져버릴 수 도 있다.


싯포스트를 분해하지 않고 충전을 하기 위해서는 앞 프론트 정션을 신형(SM-EW90)으로 바꾸고, 충전기도 신형(SM-BCR2)으로 바꿔야 한다.


거기에 추가 케이블(EW-SD50) 2개까지...


지금 6770에서 배터리를 내장형으로 바꿀 경우 가격을 계산 해보자.


인터널 배터리 (SM-BTR2) : 207,000

신형 프론트 정션 (SM-EW90) : 158,000 

신형 충전기 (SM-BCR2) : 139,000

케이블 2개 ( EW-SD50) : 60,000


총 : 564,000 원. 왠만한 하이브리드 자전거 가격이 나온다. -_-;;


그래서 지름신을 참고 지내 왔지만, 자전거 정비중 배터리를 고정시키는 저 케이블 타이(맨 처음 이미지 참고)를 보고 이성을 잃고, 


정신을 차렸을 때는 배터리 케이스를 톱질하고 있는 나를 발견했다. 헐~


욱하는 마음에 시작한 작업이지만 사실 조사는 많이 했다.


일단 작업할 프레임이 서벨로 R3 2014 - 기계식 & 전동식 공용 프레임이라 작업하기가 많이 쉬웠다. 


일반 프레임인 경우 어떤 사람은 BB 안쪽을 뚫기 까지 했다.  


( 참고 => http://weightweenies.starbike.com/forum/viewtopic.php?f=3&t=108188)



잡설은 여기 까지 하고 방법은 크게 두 가지.


1. 기존 배터리를 분해해 재활용한다.


배터리팩에서 배터리와 배터리 보호회로 분해 그리고 배터리 마운트에서 회로 분해.


배터리 팩에 앞부분은 잘 남겨 놓았다가. 위 사진 처럼 충전기 연결 부분 만들 때 사용하도록 한다.

( 블로그 참고 http://blog.naver.com/iamsinna?Redirect=Log&logNo=20161878888)


배터리 -- 배터리 보호회로 -- 커넥터 -- 배터리 마운트 회로  -- 정션

                                               |
                                                ------- 기존 충전기


커넥터는 프레임 안 쪽에 숨겨져 있고 평소에는 배터리 마운트 회로랑 연결되어 di2에 전력을 공급하고, 충전이 필요 할 때 뽑아서 충전기에 연결한다.


2. 새로운 배터리 팩을 넣는다.


영원 싸이클에서 잘 정리해 놓은 포스트가 있으니 참고바람 ( http://blog.naver.com/ywcycle?Redirect=Log&logNo=80207551504 )


2번 방법 같은 경우는 7.4v 배터리팩과 충전기를 따로 구매 해야 하기 때문에 추가 비용이 발생한다. 



아무튼 새로운 배터리 팩을 넣을려면 배터리 가격 + 충전기 가격이 들기 때문에 1번 방법으로 작업을 하려고 했는데.


일단 배터리 팩을 분해해야 하는데 힘들었다. 천천히 분해하다가 너무 힘들어서 될 때로 되라 하고 막 분해하기를 시작했는데.


쇼트가 발생해서 배터리 보호 회로가 맛이 가버렸다. ㅠ.ㅠ


[분해의 흔적]

배터리 보호회로는 물론 충전기도 못 쓰게 되는 상황이 발생했음.... 순식간에 9만원이 날라 갔음.


약 30분 동안 보호회로 살릴려고 노력했지만 실패... 보통 보호회로 reset해주면 회로가 살아나는데 완전히 죽어 버린것 같음.

잠시 멘붕의 시간이 지나고 집에 남아있는 부품을 가지고 작업을 진행했다. 배터리는 살아 있었기 때문에 이를 사용하기로 하고 죽은 보호 회로 대신 

1cell용 PCM을 연결하고 커넥터를 연결 충전할 때는 병렬로 각 셀로 4.2v가 흐르게 하고, di2시스템에 연결 될때는 직렬로 연결되 8.4v가 되게 했다.

 

[배터리 셀에 PCM을 붙이고 USB커넥터에 연결한 모습]


보호회로도 없이 리튜이온 배터리를 프레임 내부에 넣는 용자도 있는데, 만약 쇼트라도 되면 프레임안에서 불이 나고 심하면 폭발할지도 모른다.


[프레임에 붙은 브라켓 분해한 모습 이를 다운튜브에 넣었음. 위는 배터리와 연결되고 아래는 뒷 정션과 연결된다.]



[배터리를 방수를 위해 비닐팩으로 감싸고 usb 케이블과 연결, 저기 감겨 있는 케이블타이는 싯포에서 빠지지 않는 역활도 한다. ]

 

[싯포스트에 배터리 밀어 넣는다]

서벨로 프레임은 di2 / 기계식 구동계 호환 프레임이기 때문에 다운 튜브에 사진처럼 크게 구멍이 나 있다. 그래서 작업이 훨씬 편했다.


암커넥터는 배터리에서 나온 거 숫커넥터는 윗 사진 배터리 마운트와 연결된다.


즉 [원래 배터리 - 배터리 마운트 - di2 시스템] 연결과 동일하다.


[충전 커넥터 모습]

충전 커넥터에 연결하면 4.2v가 각 셀에 연결된다. 즉 충전 커넥터는 병렬.


Di2 쪽 커넥터에 연결하면 각 셀이 직렬로 연결되면서 7.4v를 내게 된다.


집에서 돌아다니는 5V 충방전 회로를 이용한 충전기를 만들었다.


 

커넥터 부분을 방수를 위해서 전기테입으로 잘 묶고, 낚시줄은 커넥터를 쉽게 빼기 위해서 묶어 놓은것. 프레임에 넣고 깔끔하게 고무마개로 막는다.


배터리 마운트가 제거되 깔끔하게 바뀐 모습.

 


참고로 di2 외장형 배터리 스펙은 512mA가 직렬로 연결되 7.4V로 출력된다. 


즉 배터리 용량은 512mA 요즘 많이 쓰는 18650을 쓰면 최대 4배 사용 시간이 더 길어 질 수 있다. 


보통 Di2가 1000km 이면 충전해줘야 하는데 18650은 4000km에 한번 충전 해주면 될 것이다. 


물론 고용량을 쓰기 때문에 따라오는 위험은 감수해야 겠지만.


http://bestbattery.biz/US14430VR.html



Posted by 평면우주
talk2013. 11. 29. 02:10

가끔 프로그램을 짜다 보면 16진수 문자열을 2진수 문자열로 바꾸는 문제가 발생한다.
예를 들어  int a = 'F'; 를 '1111' 로 보기를 원하는 것이다.

표준함수들을 이용하면 간단하게 처리 할 수 있지만 가끔 표준함수를 쓸 수 없을 때 아래를 참고하면 유용하게 사용 할 수 있다.

static unsigned long pow(int a, int b)
{
int result = 1;
for (int i= 0; i < b ; i++)
result *= a;

return result;
}

static unsigned long hex2Num(char* str, int num)
{

unsigned long result = 0;
int tmp = 0;
for (int idx =0; idx < num; idx++)
{
tmp = 0;
if (str[idx] >= '0' && str[idx] <='9')
tmp = str[idx] - '0';
else if (str[idx] >='A' && str[idx] <= 'F')
tmp = str[idx] -'A' + 10;

result += tmp*pow(16, num-idx-1); //자리수 계산
}
return result;
}

void main(void)

{

char a[4] = "ABCD";

unsigned long result = hex2Num(a, 4);

char re[4*4+1] = {'0',};

for ( int i = 15; i >= 0 ; i--)

re[15-i] = ((result & (0x1 << i))? '1': '0');

printf("%s\n", re);

return;
}




Posted by 평면우주
bicycle2013. 9. 5. 10:17

가민 엣지 800/810에는 엣지 500과 다르게 GPS Mode를 선택하는 페이지가 있다. 

On, Off, Demo Mode는 알겠는데 WAAS/EGNOS는 뭐냐? 라는 질문이 이 포스팅을 시작하게 된 계기다.

결론부터 이야기하면, 한국에서 가민 엣지 800/810을 사용할 때 WAAS/EGNOS을 켜면 GPS의 정확도를 높혀준다. 단 베터리 소모는 많아진다.

<그림 gps mode 선택 화면>

우선 WAAS/EGNOS 무엇인지 찾아 보았다. 

간단하게 설명하면 GPS 신호는 여러가지 요인 때문에 오차가 발생하고, 이를 보정시켜 오차를 최소한으로 줄이는 시스템이다. 

DGPS라고 부르며  (goo.gl/4Pw2Tr  <-이 URL에 잘 설명이 되어있다.) WAAS는 북미지역, EGNOS는 유럽, MSAS는 일본의 DGPS 시스템 이름이다.

위 3개의 DGPS는 보정을 위해 지상국은 물론 정지위성을 따로 띄워서 보정에 필요한 전파를 쏴준다.

우리나라는 MSAS의 커버리지 안에 들어 가기 때문에 DGPS를 사용할 수 있지만 가민에서 지원을 안해주니 무용지물이다!!!!!라고 생각했는데.... 대부분의 비싼 GPS 칩셋들은 WAAS/EGNOS/MSAS를 지원한다는 걸 검색을 하다가 알게 되었다.

DGPS 기능이 없는 chipset은 있었어도, MSAS만 쏙 빼버린 제품이 있던가?? GPS칩에서 WAAS/EGNOS가 되면 MSAS도 되야 하는거 아냐?

그래서 가민 edge 관련 GPS chipset 스펙을 찾아 구글을 한 참 뒤졌지만 없었다. 혹시 알고 계신 분은 알려주길 바랍니다. 


반쯤 포기하고 2.5으로 버젼업을 했을 때 EGNOS가 안 잡힌다는 가민 포럼을 읽다가 MSAS의 NMEA Code가 42번과 50번인걸 알게 된다. (https://forums.garmin.com/showthread.php?37088-Garmin-FEnix-Egnos-WAAS-with-Firmware-2-50/page2)

위키 페이지에서 MSAS에 대한 자세한 데이터를 찾을 수 있었다. (http://en.wikipedia.org/wiki/Multi-functional_Satellite_Augmentation_System)


그럼 WAAS/EGNOS 키면 MSAS 위성데이터도 수신하지 않을까? 라는 생각이 들어서 실험을 해봤다.


    

<그림 gps 수신 화면>

위 화면에서 번호가 NMEA 프로토콜에서 위성 번호이다. (위성 고유 코드는 PRN 이다.) 첫번째 이미지는 Normal mode일 때 위성 정보이다. 두번째, 세번째 이미지는 WAAS/EGNOS를 켰을 때인데, 42번과 50번 위성이 잡힌다. DGPS 위성 정보를 받고 있다는 것이다.

하지만 단순히 위성 정보만 수신하는 건지? 아니면 정말 보정이 되는지 모르겠다. 제일 정확한 방법은 엣지 내부에 NMEA를 직접 받아보면 확실 하게 알 수 있지만 이건 불가능 하고...


그래서 간단한 실험 즉 WAAS/EGNOS을 켰을 때 보정이 되는지 로그를 비교해보기로 했다.

코스는 집에서 회사 출근하는 5km, 이 코스를 선택한 이유는 전자회사라서 그런지 회사에 들어오기만 하면 GPS가 엄청 튄다.



<WAAS/EGNOS를 켰을 때>


<WAAS/EGNOS를 껐을 때.>


2일 Normal Mode, 3일 WAAS/EGNOS 총 5일에 걸쳐서 테스트 해봤는데 위 사진 처럼 WAAS/EGNOS 일 때 튀는 정도가 훨씬 줄어들지만, 맘에는 안든다. 가민 510의 글로나스 + GPS 모드를 쓰면 거의 오차가 없는 로그를 볼 수 있다.


결론

 정확한 로깅을 얻고 싶으면. 가민 510을 지르면 되고

시간이 많은 사람들은 810 후속을 기다리면 됩니다.


이번에 알게 된거.

  • 가민 500, 800, 810은 같은 GPS chipset을 사용한다.
  • 가민 500도 waas/egnos를 수신 할 수 있는데도 메뉴에서 걍 빼버렸다, 항상 disable 상태.
  • 가민 510은 러시아의 GPS 글로나스를 사용할 수 있다. 단 배터리 소모가 많아진다. 왜? 810은 글로나스를 빼버렸을까????
  • 가민 시리즈의 hardware 스펙은 베일에 가려져 있다.
  • DGPS보정이 동작하는지는 NMEA를 까보면 쉽게 알 수 있다. 아래가 NMEA인데  (http://www.gpsinformation.org/dale/nmea.htm)
    $GPGGA,120558.916,5058.7457,N,00647.0514,E,2,06,1.7,109.0,M,47.6,M,1.5,0000*71
    위에서 2가 DGPS로 보정이 되었다는 의미이다.
  • 810은 글로나스가 빠져서 아쉽다.




Posted by 평면우주