cURL

운영체제로그/Linux 2011. 2. 18. 19:15

 

curl은 URL 문법을 사용해서 네트웍으로 데이터를 전송할 수 있는  커맨드 라인 툴로,  DICT, FILE, FTP, FTPS, GOPHER, HTTP, HTTPS,

IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP,SMTP, STMPS, TELNET 등 다양한 프로토콜을 지원한다. 

 

curl 명령에 -v 옵션을 사용하여,  curl 명령이 서버에 보내는 명령들을 볼 수 있다. 

 

웹페이지를 요청하는 다음과 같은 요청을 할 수 있다. 

curl http://curl.haxx.se

위와 같이 요청을 하면, 웹페이지 소스를 확인할 수 있다. 

 

-i 옵션을 사용하여, 헤더를 볼수 있으며, -I 옵션을 사용하여 헤더만 볼수도 있다.  

curl -I http://curl.haxx.se

 


GET 방식의 요청

curl "www.hotmail.com/when/junk.cgi?birthday=1906&press=OK"


POST 방식의 요청

curl -d "birthday=1905&press=OK" www.hotmail.com/when/junk.cgi

 

특수문자를 포함하기 위해서  curl에 --data-urlencode 옵션을 사용하여 인코딩할 수 있다. 

curl -data-urlencode "name=I am dDaniel" www.example.com

 

 

File Upload 하기 

 

위와 같이 html 문서내 파일업로드를 다음과 같은 curl 명령으로 수행할 수 있다. 

curl -F upload=@로컬파일이름 -F press=OK www.example.com

 

PUT 방식 

HTTP 서버에 데이터를 업로드하는 가장 좋은 방법은 PUT  을 사용하는 것이다. 물론 서버단에 HTTP PUT 스트림을

받는 방법을 아는 프로그램이나 스크립트가 존재해야한다. 파일을 HTTP 서버로 전송하는 명령이다 .

curl -T 파일 www.upload.com/receive.cgi

 

 

HTTP 인증 

HTTP  인증은 서버에 사용자명과 비밀번호를 전송하여 컨텐츠 접근권한을 허용받는 것이다. HTTP  는 디폴트로 순수 텍스트

기반 인증을 수행하기 때문에 비밀번호가 언제든지 네트워상에서 노출될 위험이 있다. 

curl -u name:password www.secret.com

사이트 마다 다른 인증방식을 요구할 수 있기때문에 서버로부터의 헤더를 확인하여, ---ntlm, --digest, --negotiate, -- anyauth 등

적합한 옵션을 주어야 할 수있다. 

 

User Agent 설정 

웹 요청시 User-Agent 헤더를 설정하여 원하는 버전의 웹페이지를 얻어 올 수 있다. 

 

Window에서 Internet  Explorer를 사용하고 있다면, 

curl -A "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)" www.example.com

 

리눅스에서 Netscape를 사용하고 있다면, 

curl -A "Mozilla/4.0 [en] (X11; U; Linux 2.2.15 i686)"  www.example.com



curl을 사용하여 트위터에 tweet 하기

트위터 API를 사용에서 글을 트윗 하기 위해서, 인증을 거쳐야하는데 curl을 사용하여 인증처리 및 글을 등록해보자!

--basic --user 사용자명:비밀번호

옵션을 사용하여 Basic Auth 을 처리할 수 있다. 그을 트윗하는 완전한 예는 다음과 같다. 

 

curl --basic --user 사용자명:비밀번호 --data status="my test tweet!!" http:// twitter.com/statuses/update.xml

 

 

세션쿠키값을 파일에 저장하여 로그인상태 유지하기

트위터의 특정 사람에게 DM을 보내기 위해 로그인 처리를 다음과 같이 할 수 있다. 

curl --cookie /tmp/cookies.txt --cookie-jar /tmp/cookies.txt --user-agent Mozilla/4.0 --data 
'username=사용자명' --data 'password=비밀번호' --data 'commit=Sign In' http://twitter.com/login

 

--cookie /tmp/cookies.txt --cookie-jar /tmp/cookies.txt

위 옵션은 /tmp/cookies.txt 파일에서 쿠키를 읽어오고 저장하게 한다.  최초에 빈파일이지만, 로그인 완료되면 세션쿠키가 해당 파일에

저장되게 된다. 이후 요청에서는 이 쿠키를 읽어서 별도의 인증과정 없이  아래와 같이 DM을 전송 할 수 있다. 

 

curl --cookie /tmp/cookies.txt --cookie-jar /tmp/cookies.txt --user-agent Mozilla/4.0 --data
"text=보낼 메시지를 이곳에" --data 'commit=Send' http://twitter.com/direct_messages/create/대상사용자아이디(숫자)


이 글은 스프링노트에서 작성되었습니다.

Base64 Encoding

기타 2011. 2. 18. 12:06



1. Base64 Encoding 이란?

Base64는 바이너리 데이터를  64진수 표현으로 변환하여 아스키 문자열로 인코딩하는 방법이다.
Bae64 encoding은 텍스트 데이터를 전송하기 위해 설계된 매체상에서 바이너리 데이터를 전송하거나 
저장하기 위해 사용되는 방식이다. 전송중에 데이터가 변경되지 않고, 파괴되지 않았음을 보장해준다. 
MIME를 사용하는 이메일을 포함한 많은 애플리케이션에서 사용된다.



2. Base64 Encoding 절차
3바이트 단위로 인코딩을 수행하며, 3으로 나누어 떨어지지 않는 데이터는 =문자로 패딩바이트를 삽입한다. 
(즉 3으로 나누어 떨어지지 않으면, =문자 1개, 또는 2개가 패딩된다.)
3바이트 데이터는 가장 상위비트부터 64진수로 표현하기 위해 6 비트씩 구분하여, 4개의 아스키 문자로 변환한다.
이 때 사용하는 64개의 문자는  A~Z (26개) , a~z(26개), 0~9(10개), +. / (2개) 이다.  0은   A로 인코딩되며,
63은 /로 인코딩이 된다. Base64Encoding 된 데이터는 원래 데이터보다 약 37% 증가한다. 


다음은 name 이라는 데이터가 Base64 Encoding 된후, 결과를 나타낸다.  

먼저 nam 이 가장 상위비트부터 6개의 비트씩 추출이 되어진다. e는 6개의 비트가 추출되어 인코딩이 되면
2개의 비트가 남게되는데, 여기에 4개의 0비트를 패딩하여 인코딩이 된다. 3바이트의 데이터는 인코딩된 
4개의 문자로 출력되는데,  위에서는 ZQ에 2개의 = 문자가 패딩이 된다. 
 
Base64 인코딩된 결과를 디코딩 할 때는 반대의 과정을 거치면 된다. 
인코딩 결과에서,  4개의 문자로부터 6개의 비트씩 추출하여 3바이트로 조합을 하여 한 바이트를 온전한 데이터로
읽으면 된다. 나누어 떨어지지 않는 문자는 =문자가 2개이면, 1개의 바이트(8비트)만을 추출하고 =문자가 1개이면,  
2개의 바이트(8비트씩 2개)를 추출하여 읽어내면 디코딩을 수행할 수 가 있다.  


 

'기타' 카테고리의 다른 글

지갑  (0) 2011.05.26
2011년 자바 개발자 컨퍼런스 등록!!  (1) 2011.05.23
Base64 Encoding  (0) 2011.02.18
muju  (33) 2011.02.14
정규표현식(Regular Expression)  (0) 2010.12.10
MD5(Message-Digest algorithm 5)  (0) 2010.12.10

문제5 그래픽편집기

알고리즘.데이터구조 2011. 2. 18. 11:41


이미지를 M X N 배열로 표현하는 간단한 대화형 그래픽 편집기  프로그램을 만들어보자.

 

 입력

한 줄에 하나씩의 1개 문자의 명령으로 구성됨.  매개변수는 스페이스로 분리됨 

픽셀좌표는 1 이상 M이하의 열, 1이상 N이하의 행 으로 표현됨. 

표의 왼쪽 위 꼭지점이 원점이며, 색은 대문자로 지정함 

 

 

출력

명령을 제외한 문자는 무시하고,  S Name 명령은 Name 으로 주어진 파일명 출력 후

현재 이미지 내용을 출력함.

 

I M N   M X N 이미지를 새로 생성 후, 흰색(O)으로 초기화
C  모든 픽셀을 흰색으로 칠한다
L X Y C  (X, Y) 픽셀을 주어진 색(C)로 칠한다
V X Y1 Y2 C  X열에 Y1행과 Y2행 (Y1, Y2포함)사이에 색(C)으로 수직방향 직선을 그린다 
H X1 X2 Y C  Y행에 X1열과 X2행(X1, X2포함)사이에 색(C)으로 수평방향 직선을 그린다
K X1 Y1 X2 Y2 C  주어진 색(C)로 채워진 직사각형을 그리되, X1 Y1은 왼쪽 위끝점 X2 Y2는 오른쪽 아래 끝점
F X Y C  R영역을 색 C로 채운다. R 영역은 X Y 점이 포함되고, 해당 점과 상 하 좌 우  이웃하는 점이 R영역으로 포함된다.
S Name  파일명을 입력받은 대로 출력 후, 현재 이미지 내용을 출력한다.
X  프로그램 종료 


 



graphic_editor.c


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_SIZE 100

typedef struct _Image {
	char *pixels;
	int r, c;
} Image;

typedef struct _Point {
	int x, y;
} Point;


Point make_point(int x, int y);

 
Image* initiate(int row, int col);
void fill_color(Image *image, Point point, char color);
void show(Image *image);
void flood(Image *image, Point point, char color);
void flood_recur(Image *image, Point point, char color, char r_color); 
void horizontal_line(Image *image, int x, int y1, int y2, char color);
void vertical_line(Image *image, int x1, int x2, int y, char color);
void rectangle(Image *image, Point left_top, Point right_bottom, char color);
void clear(Image *image, char color);


int main (int argc, char const* argv[])
{
	char cmd, color;
	char buf[MAX_SIZE], name[MAX_SIZE];
	int m, n, x1, x2, y1, y2;
	Image *image = 0;

	while (fgets(buf, 100, stdin) != NULL && strncmp(buf, "X", 1) != 0) {
	 	if (strncmp(buf, "I ", 2) == 0) {
		
			sscanf(buf, "%c %d %d", &cmd, &m, &n);
			image = initiate(n, m);
			
		} else if (strncmp(buf, "C", 1) == 0) {\
	
			clear(image, '0');
			
		} else if (strncmp(buf, "L ", 2) == 0) {
			
			sscanf(buf, "%c %d %d %c", &cmd, &x1, &y1, &color);
			fill_color(image, make_point(x1-1, y1-1), color);	
			
		} else if (strncmp(buf, "V ", 2) == 0) {
			
			sscanf(buf, "%c %d %d %d %c", &cmd, &x1, &y1, &y2, &color);
			vertical_line(image, x1-1, y1-1, y2-1, color);
			
		} else if (strncmp(buf, "H ", 2) == 0) {
			
			sscanf(buf, "%c %d %d %d %c", &cmd, &x1, &x2, &y1, &color);
			horizontal_line(image, x1-1, x2-1, y1-1, color);
			
		} else if (strncmp(buf, "K ", 2) == 0) {
			
			sscanf(buf, "%c %d %d %d %d %c", &cmd, &x1, &y1, &x2, &y2, &color);
			rectangle(image, make_point(x1-1, y1-1), make_point(x2-1, y2-1), color);
			
		} else if (strncmp(buf, "F ", 2) == 0) {
		
			sscanf(buf, "%c %d %d %c", &cmd, &x1, &y1, &color);
			flood(image, make_point(x1-1, y1-1), color);
			
		} else if (strncmp(buf, "S ", 2) == 0) {
			
			sscanf(buf, "%c %s", &cmd, name);
			printf("%s \n", name);
			show(image);
		}
	}
	
	return 0;
}

Point make_point(int x, int y) {
	return (Point){x, y};
}



// 이미지 생성 - I m n 
Image* initiate(int row, int col) {
	Image *image = (Image*)malloc(sizeof(Image));
	
	image->pixels = (char*)malloc(row*col); 
	image->r = row;
	image->c = col;
	
	clear(image, '0');
	
	return image;
}

// 주어진 픽셀에 칠하기 - L x y c
void fill_color(Image *image, Point point, char color) {
	image->pixels[point.y*image->c +  point.x] = color;
}

// 이미지 출력 
void show(Image *image) {
	int i;
	
	for (i = 0; i < image->r * image->c; i++) {
		putchar(image->pixels[i]);
		
		if (i % image->c == image->c - 1) {
			putchar('\n');
		}
	}
}

// 점람 채우기 
void flood(Image *image, Point point, char color) {
	char r_color = image->pixels[point.y*image->c +  point.x];
	flood_recur(image, point, color, r_color);
}


void flood_recur(Image *image, Point point, char color, char r_color) {
	int x = point.x;
	int y = point.y;
	int index = y*image->c + x;
	
	// 경계를 벗어났거나 같은 영역이 아니면 종료 
	if (image->pixels[index] != r_color || x < 0 || y < 0 || x >= image->c || y >= image->r) {
		return;
	}
	image->pixels[index] = color;
	
	flood_recur(image, make_point(x, y+1), color, r_color);
	flood_recur(image, make_point(x+1, y), color, r_color);
	flood_recur(image, make_point(x, y-1), color, r_color);
	flood_recur(image, make_point(x-1, y), color, r_color);
}


// 수평 직선  - H
void vertical_line(Image *image, int x, int y1, int y2, char color) {
	Point left_top, right_bottom;
	
	left_top.x = right_bottom.x = x;
	left_top.y = y1;
	right_bottom.y = y2;
	
	rectangle(image, left_top, right_bottom, color);
}


// 수직 직선  - V
void horizontal_line(Image *image, int x1, int x2, int y, char color) {
	Point left_top, right_bottom;
	
	left_top.x = x1;
	right_bottom.x = x2;
	left_top.y = right_bottom.y = y;
	
	rectangle(image, left_top, right_bottom, color);
}

// 사각형 그리고 채우기 - K
void rectangle(Image *image, Point left_top, Point right_bottom, char color) {
	int i, j;
	
	for (i = left_top.y; i <= right_bottom.y; i++) {
		for (j = left_top.x; j <= right_bottom.x; j++) {
			image->pixels[i*image->c + j] = color;
		}
	}
}


void clear(Image *image, char color) {
	int i;
	for (i = 0; i < image->r * image->c; i++) {
		image->pixels[i] = color;
	}
}



'알고리즘.데이터구조' 카테고리의 다른 글

합병정렬(Merge Sort)  (0) 2011.03.23
HMAC-SHA1  (0) 2011.03.11
문제5 그래픽편집기  (0) 2011.02.18
문제4 LCD디스플레이  (0) 2011.02.18
문제3 여행  (0) 2011.02.18
문제2 지뢰찾기  (0) 2011.02.18

문제4 LCD디스플레이

알고리즘.데이터구조 2011. 2. 18. 11:40


 

LCD 디스플레이 형태로 숫자를 출력하되 크기 입력 s에 의해 출력하는 숫자의 크기를 조절할 수 있다.

이 때 각 숫자는 s+2개의 열과  2s+3 개의 행 크기를 차지하게  된다. 행문자는 ' | ',  열 ' -' 를 사용. 

각 자리 수 사이에는 1칸씩 공백을 둔다. 


입력 : s n  (크기 s, 출력할 정수 n)

출력 :  LCD 디스플레이 형태로 n을 출력 

 

 

문제해결

두 가지 방법으로 해결법을 찾아 보았다. 첫번째는 0 ~ 9 까지 각 수를 인자 s에 따라 출력하는 

일반적인 방법이다. 두번 째는 LCD 패널을 7가지 구성요소로 분리하고, 각 요소를 7개의 함수로 

만들고, 0~9중 해당하는 수가 입력된 경우에만 해당 요소를 출력하는 방법이다. 

 


 

lcd_display.c


/*
	입력 : s(크기) , n(출력할 수)
	출력 : LCD Display 형태로 n를 출력 
	조건 : s+2 열, 2s+3 행을 사용 
*/

#include <stdio.h>
#include <stdlib.h>

#define ROW(s) (2*s + 3)
#define COL(s) (s+2)

#define ROW_CHAR '@'
#define COL_CHAR '@'
#define SPACE ' '

void f0(int n, int s);
void f1(int n, int s);
void f2(int n, int s);
void f3(int n, int s);
void f4(int n, int s);
void f5(int n, int s);
void f6(int n, int s);

void lcd_display(int s, char *buf);

int main (int argc, char const* argv[])
{
	int s;
	char buf[10];
	
	scanf("%d %s", &s, buf);
	
	lcd_display(s, buf);

	return 0;
}


void lcd_display(int s, char *buf) {
	int i;
	char *p = buf;
	
	if (s == 0 && atoi(buf) == 0) {
		return ;
	}

	p = buf;
	while (*p != '\n' && *p != '\0') {
		f0(*p-'0', s);
		p++;
	}
	putchar('\n');
	
	for (i = 0; i < (ROW(s)-1)/2; i++) {	
		p = buf;
		while (*p != '\n' && *p != '\0') {
			f1(*p-'0', s);
			p++;
		}
		putchar('\n');
	}
	
	p = buf;
	while (*p != '\n' && *p != '\0') {
		f3(*p-'0', s);
		p++;
	}
	putchar('\n');

	for (i = 0; i < (ROW(s)-1)/2; i++) {
		p = buf;
		while (*p != '\n' && *p != '\0') {
			f4(*p-'0', s);
			p++;
		}
		putchar('\n');
	}
		
	p = buf;
	while (*p != '\n' && *p != '\0') {
		f6(*p-'0', s);
		p++;
	}
	putchar('\n');
}


// 가장 첫행 
void f0(int n, int s) {
	int i;
	char ch = COL_CHAR;
	
	if (n == 1 || n == 4){
		ch = SPACE;
	} 
	for (i = 0; i < COL(s)-1; i++) {
		putchar(ch);
	}
	putchar(SPACE);
}

void f1(int n, int s) {
	int i;
	char ch = ROW_CHAR;
	
	if (n == 1 || n == 2 || n == 3 || n == 7) {
		ch = SPACE;
	}
	putchar(ch);
	for (i = 0; i < COL(s)-3; i++) {
		putchar(SPACE);
	}
	f2(n, s);
}

void f2(int n, int s) {
	char ch = ROW_CHAR;
	
	if (n == 5 || n == 6){
		ch = ' ';
	}
	putchar(ch);
	putchar(SPACE);
}
// 중간 행 
void f3(int n, int s) {
	int i;
	char ch = COL_CHAR;
	
	if (n == 0 || n == 1 || n == 7){
		ch = ' ';
	}
	for (i = 0; i < COL(s)-1; i++) {
		putchar(ch);
	}
	putchar(SPACE);
}

void f4(int n, int s) {
	int i;
	char ch = ROW_CHAR;
	
	if (n == 1 || n == 3 || n == 4 || n == 5 || n == 7 || n == 9){
		ch = SPACE;
	}
	putchar(ch);
	for (i = 0; i < COL(s)-3; i++) {
		putchar(SPACE);
	}
	f5(n, s);
}

void f5(int n, int s) {
	char ch = ROW_CHAR;
	
	if (n == 2){
		ch = ' ';
	}
	putchar(ch);
	putchar(' ');
}

// 끝행 
void f6(int n, int s) {
	int i;
	char ch = COL_CHAR;
	
	if (n == 1 || n == 4 || n == 7){
		ch = SPACE;
	}
	for (i = 0; i < COL(s)-1; i++) {
		putchar(ch);
	}
	putchar(SPACE);
}


'알고리즘.데이터구조' 카테고리의 다른 글

HMAC-SHA1  (0) 2011.03.11
문제5 그래픽편집기  (0) 2011.02.18
문제4 LCD디스플레이  (0) 2011.02.18
문제3 여행  (0) 2011.02.18
문제2 지뢰찾기  (0) 2011.02.18
문제1 3n+1문제  (0) 2011.02.18

문제3 여행

알고리즘.데이터구조 2011. 2. 18. 11:40


 

여행에 참석한 학생들이 식비, 호텔비, 택시비,  비행기표를 한명씩 부담하고, 나중에 1센트 단위 내에서  

쓴 돈이 같아지고, 돈을 주고 받을 때 서로 전달 해야하는 최소액수를 구해보자.

 

입력

여행에 참석한 학생 수와 각 학생이 부담한 비용을 입력으로 받는다. 단 학생수는 1000명 이하이고, 

어떤 학생도 10,000.00 달러 이상 지출하지 않는다. 단위는 달려이고, 0이 입력되면 종료한다.

 

출력

각 학생이 사용한 금액이 같아지기 위해 전달되어야 하는 금액의 총합

 

ex)

입력

3

15.00

15.01

3.00

3.01

0

 

출력

$11.99

 

해결과정

각 학생이 소비한 금액의 평균을 구해서, 평균액보다 적은 돈을 낸 사람에 대해  평균액과 낸 금액의 차에 합을  

구하면 된다. 이 때 1센트 이내에  차이가 있어야 하기 때문에  평균액을 구할 때 소수 셋째짜리에서 반올림을 수행한다.

반올림을 위해, 평균액에 1000을 곱하고, 1의 자리에서 반올림 후 다시 1000으로 나눠주는 과정을 거치게 된다. 

 

trip_fee.c


/*
	입력 : 여행에 참여한 학생수 (정수 n <= 1000), 각 학생이 낸 경비 
	출력 : 각 학생이 사용한 금액이 같아지기 위한 금액 총합 	
*/

#include <stdio.h>
#include <stdlib.h>

double total_fee(double* fees, int n);

int main (int argc, char const* argv[])
{
	int i, n;
	double total, *fees;
	
	scanf("%d", &n);
	fees = (double*)malloc(n * sizeof(double));
	
	for (i = 0; i < n; i++) {
		scanf("%lf", fees + i);
	}
	
	total = total_fee(fees, n);
	
	printf("$%.2lf \n",  total);
	
	free(fees);
	
	return 0;
}


double total_fee(double* fees, int n) {
	int i, share, rem;
	float sum, d_share, total; 
		
	sum = d_share = total = 0.0;
	for (i = 0; i < n; i++) {
		sum += fees[i];
	}
	share = (sum * 1000) / n;
	
	if ((rem = share % 10) >= 5) {
		share += 10;
	}
	share -= rem;
	d_share = share / 1000.0;

	for (i = 0; i < n; i++) {
		if (fees[i] > d_share) {
			total += fees[i] - d_share;
		}
	}
	
	return total;
}


'알고리즘.데이터구조' 카테고리의 다른 글

HMAC-SHA1  (0) 2011.03.11
문제5 그래픽편집기  (0) 2011.02.18
문제4 LCD디스플레이  (0) 2011.02.18
문제3 여행  (0) 2011.02.18
문제2 지뢰찾기  (0) 2011.02.18
문제1 3n+1문제  (0) 2011.02.18

문제2 지뢰찾기

알고리즘.데이터구조 2011. 2. 18. 11:40


윈도우의 지뢰찾기 게임을 기억할 것이다. M x N 크기 지뢰밭 각 셀은 인접한 셀에 몇개의 지뢰가 존재하는지

나타내는 수를 가지고 있다.  *를 지뢰하고 하면...

 

 * . . .

  . . . . 

 . * . .

  . . . .

 

와 같은 지뢰밭은 다음과 같은 값을 가지게 된다.

 

* 1 0 0

2 2 1 0

1 * 1  0

1 1 1 0

 

입력 : 행의 개수 n, 열의 개수 m /   n행 m열의 지뢰밭 

출력 : 인접한 8개의 이웃에 있는 지뢰의 개수가 계산된 지뢰밭  출력

 

ex) 

입력  

4 4

* . . . 

. . . . 

. . . .

. * . .

 

출력

* 1 0 0

2 2 1 0

1 * 1 0

1 1 1 0

 

문제해결

지뢰가 아닌 모든 셀에 대해서 이웃하는 지뢰의 개수를 카운팅한다. 카운팅은 상 하 좌 우 인덱스를 변화시켜 지뢰의 개수를 

카운팅하되 행과 열에 대한 바운더리를 초과하지 않도록 검사를 수행한다.


mine_sweeper.c


/*
	입력 : 행과 열의 개수 n m / 지뢰밭 
	출력 : 이웃하는 지뢰개수가 계산된 지뢰밭 
*/

#include <stdio.h>
#include <stdlib.h>

#define MINE '*'
#define EMPTY '.'
#define MAX_BUF 200

typedef struct _Mine {
	int n, m;
	char *mines;
} Mine;


Mine *input();
void construct_mine(Mine *_mine);
void destruct_mine(Mine *_mine);

int count_mines(Mine *mine, int r, int c);
void output();


int main (int argc, char const* argv[])
{
	Mine *mine;
	
	while (mine = input()) {
		construct_mine(mine);
		output(mine);
		destruct_mine(mine);
	} 
	
	return 0;
}

Mine *input() {
	int m, n, i, j;
	Mine *mine;
	char buf[MAX_BUF];
	char *p_buf = buf;
	
	scanf("%d %d", &m, &n);
	getchar(); // 개행 문제를 버림 
		
	if (m == 0 && n == 0) {
		return 0;
	}
	
	mine = (Mine*)malloc(sizeof(Mine));
	mine->m = m;
	mine->n = n;
	mine->mines = (char*)malloc(m * n + 1);
	
	for (i = 0; i < m; i++) {
		p_buf = buf;
		fgets(buf, MAX_BUF, stdin);
		j = 0;
		while (*p_buf != '\0') {
			if (*p_buf == '*' || *p_buf == '.') {
				mine->mines[n*i + j] = *p_buf;
				j++;
			}
			p_buf++;
		}
	}	
	return mine;
}

// 모든 셀에 지뢰 개수를 카운팅 
void construct_mine(Mine *_mine) {
	int i, j;
	Mine *mine = _mine;
	int m = mine->m, n = mine->n;
	
	for (i = 0; i < m; i++) {
		for (j = 0; j < n; j++) {
			if (mine->mines[i*n + j] != '*') {
				mine->mines[i*n + j] = count_mines(mine, i, j);
			}
		}
	}
}

void destruct_mine(Mine *_mine) {
	free(_mine->mines);
	free(_mine);
}


//  특정 셀의 인접한 이웃의 지뢰의 개수를 카운팅 
int count_mines(Mine *mine, int r, int c) {
	int index, count = 0;
	int m = mine->m, n = mine->n;
	char *cell = mine->mines;
	
	if (r - 1 >= 0 && c - 1 >= 0) {
		index = (r - 1)*n + c - 1;
		if (*(cell + index) == '*') {
			count++;
		}
	}
	if (r - 1 >= 0) {
		index = (r - 1)*n + c;
		if (*(cell + index) == '*') {
			count++;
		}
	}
	if (r - 1 >= 0 && c + 1 < n) {
		index = (r - 1)*n + c + 1;
		if (*(cell + index) == '*') {
			count++;
		}
	}
	if (c - 1 >= 0) {
		index = r*n + c - 1;
		if (*(cell + index) == '*') {
			count++;
		}
	}
	if (c + 1 < n) {
		index = r*n + c + 1;
		if (*(cell + index) == '*') {
			count++;
		}
	}
	if (r + 1 < m && c - 1 >= 0) {
		index = (r + 1)*n + c - 1;
		if (*(cell + index) == '*') {
			count++;
		}
	}
	if (r + 1 < m) {
		index = (r + 1)*n + c;
		if (*(cell + index) == '*') {
			count++;
		}
	}
	if (r + 1 < m && c + 1 < n) {
		index = (r + 1)*n + c + 1;
		if (*(cell + index) == '*') {
			count++;
		}
	}
	return count;
}


// 결과 출력 
void output(Mine *mine) {
	int i;
	printf("Field #:");
	for (i = 0; i < mine->m * mine->n; i++) {
		if (*(mine->mines + i) == '*') {
			printf("%c ", *(mine->mines + i));
		} else {
			printf("%d ", *(mine->mines + i));
		}
		if (i % mine->n == mine->n - 1) {
			printf("\n");
		}
	}
	printf("\n");
}


'알고리즘.데이터구조' 카테고리의 다른 글

HMAC-SHA1  (0) 2011.03.11
문제5 그래픽편집기  (0) 2011.02.18
문제4 LCD디스플레이  (0) 2011.02.18
문제3 여행  (0) 2011.02.18
문제2 지뢰찾기  (0) 2011.02.18
문제1 3n+1문제  (0) 2011.02.18

문제1 3n+1문제

알고리즘.데이터구조 2011. 2. 18. 11:39

 

정수 n에서 n이 짝수면 2로 나누고, 홀수면 3을 곱하고 1을 더한다. 이렇게 만들어지는 수를 

다시 n으로 놓고,  n=1이 될 때까지 반복해서 나오는 수들의 개수를 정수 n의 사이클 길이(cycle length)라고 한다. 

(1을 포함)

 

i, j 두개의 수가 주어졌을 때, 두 수 사이의 모든 수(i, j 포함)들 중 최대 사이클 길이를 구하라 

 

입력 : i j     (  0 <= i, j <= 1000000)

출력 : i j cycle_length

 

ex) 입력 : 1 10

       출력 : 1 10 20

 

3n_1.c


/*
	입력 : 정수 i, j
	출력 : 정수 i, j, 최대 사이클 길이 
*/

#include <stdio.h>

int cycle_length(int num);

int main (int argc, char const* argv[])
{
	int left_bound, right_bound, max = 0;
	int i, cycle_len;
	
	scanf("%d %d", &left_bound, &right_bound);
	
	for (i = left_bound; i <= right_bound; i++) {
		cycle_len = cycle_length(i);
		if (cycle_len > max) {
			max = cycle_len;
		}
	}
	
	printf("%d %d %d \n", left_bound, right_bound, max);
	
	return 0;
}

int cycle_length(int num) {
	int n = num, cn = 1;
	
	while (n != 1) {
		if (n % 2) {
			n = 3*n + 1;
		} else {
			n = n >> 1;
		}
		cn++;
	}
	return cn;
}


'알고리즘.데이터구조' 카테고리의 다른 글

HMAC-SHA1  (0) 2011.03.11
문제5 그래픽편집기  (0) 2011.02.18
문제4 LCD디스플레이  (0) 2011.02.18
문제3 여행  (0) 2011.02.18
문제2 지뢰찾기  (0) 2011.02.18
문제1 3n+1문제  (0) 2011.02.18