[9184] 신나는 함수 실행
- 메모이제이션만 하면 된다.
< 소스코드 >
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 <stdio.h> int d[21][21][21]; int w(int a, int b, int c) { if(a <= 0 || b <= 0 || c <= 0) return 1; if(a > 20 || b > 20 || c > 20) return w(20, 20, 20); if(d[a][b][c]) return d[a][b][c]; if(a < b && b < c) return d[a][b][c] = w(a, b, c-1) + w(a, b-1, c-1) - w(a, b-1, c); return d[a][b][c] = w(a-1, b, c) + w(a-1, b-1, c) + w(a-1, b, c-1) - w(a-1, b-1, c-1); } int main() { while(1) { int a, b, c; scanf("%d%d%d", &a, &b, &c); if(a == -1 && b == -1 && c == -1) break; printf("w(%d, %d, %d) = %d\n", a, b, c, w(a, b, c)); } return 0; } | cs |
>> 12 라인을 9번 라인보다 먼저 써서 런타임에러가 발생했었다...
>> 배열의 각 차원의 크기는 21인데, a, b, c 중 20보다 큰 값이 들어오면 저 코드를 먼저 실행하게
되어 런타임 에러가 발생하는 듯 하다.
'BOJ > DP' 카테고리의 다른 글
[2216] 문자열과 점수 (0) | 2018.02.21 |
---|---|
[11048] 이동하기 (0) | 2018.02.18 |
[2302] 극장 좌석 (0) | 2018.02.05 |
[1937] 욕심쟁이 판다 (0) | 2018.02.01 |
[1309] 동물원 (0) | 2018.02.01 |
<2-2> 리스트, 튜플
# Day_02_02_list.py
- Collection
[] : list
() : tuple
{} : set/dictionary
<> : not used
- list
1 2 3 4 5 6 | a = [1, 3, 5] print(a) # [1, 3, 5] print(a[0], a[1], a[2]) # 1 3 5 a[0] = 99 print(a) # [99, 3, 5] | cs |
>> 1 : list 의 선언
>> python 에서는 array 가 없다고 함.
>> 3 : 인덱스를 통한 접근
>> 5 : 값의 변경
- 반복문을 통한 접근
1 2 | for i in range(len(a)): print(a[i]) | cs |
>> len(a) : list 의 갯수를 리턴해준다.
- 문제
- 100 보다 작은 난수 10개로 이루어진 리스트를 반환하는 함수 만들기
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | def makeRandom1(): a = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] for i in range(10): a[i] = random.range(100) return a def makeRandom2(): a = [0]*10 for i in range(10): a[i] = random.range(100) return a def makeRandom3(): a = [] for i in range(10): a.append(random.randrange(100)) return a | cs |
>> makeRandom3() 에서 처럼 append() 를 많이 쓴다고 한다.
>> 하지만 느리다고 한다.
>> append() 는 리스트의 맨 뒤에 내용을 추가.
- 문제
- 리스트를 거꾸로 뒤집는 함수 만들기
1 2 3 4 5 | def reverseList(c): size = len(c) for i in range(size//2): c[i], c[size-1-i] = c[size-1-i], c[i] return c | cs |
-
1 2 | for i in a: print(i, end=' ') | cs |
>> 여기서 a는 리스트
>> i는 인덱스가 아닌, 리스트의 각 요소
- range() 와 리스트의 타입
1 2 3 | print(type(range(5)), type(a)) # <class 'range'> <class 'list'> | cs |
>> range, list 는 utterable 객체
- reversed(obj)
1 2 3 4 5 6 7 8 9 | for i in a: print(i, end=' ') print() # 37 67 44 50 25 65 15 66 5 86 for i in reversed(a): print(i, end=' ') print() # 86 5 66 15 65 25 50 44 67 37 | cs |
>> list 가 뒤집어진 상태로 진행이 된다.
1 2 3 4 | for i in reversed(range(len(a))): print(a[i], end=' ') print() # 86 5 66 15 65 25 50 44 67 37 | cs |
>> 이런식으로도 가능하다.
- enumerate()
1 2 3 4 | for i in enumerate(a): print(i, end=' ') print() # (0, 37) (1, 67) (2, 44) (3, 50) (4, 25) (5, 65) (6, 15) (7, 66) (8, 5) (9, 86) | cs |
>> i는 (index, value) 의 형태를 갖는다. 데이터 타입은 튜플..!!
>> 특정 데이터가 몇번째 데이터인지 알고 싶을 때 enumerate() 을 사용
1 2 3 4 | for i in enumerate(a): print(i[0], i[1], end=' ') print() # 0 37 1 67 2 44 3 50 4 25 5 65 6 15 7 66 8 5 9 86 | cs |
>> 괄호를 없애고 싶을 땐 인덱스를 활용한다.
- 튜플(tuple)은 리스트의 상수버전...
- 리스트와 사용방법이 동일하다. 다만, 내용을 바꿀수 없을 뿐..!!
1 2 3 | t = (1, 2, 3) t[0] = 99 # TypeError: 'tuple' object does not support item assignment | cs |
>> 튜플은 보통 파이썬이 사용한다.
>> 매개변수를 전달하거나, 반환값을 전달할 때.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | def sumOfOddEven(): odd, even = 0, 0 for i in range(1, 100): if i%2 == 1: odd += i else : even += i return odd, even s1, s2 = sumOfOddEven() print(s1, s2) # 2500 2450 s = sumOfOddEven() print(s) # (2500, 2450) print(type(s)) # <class 'tuple'> | cs |
>> 13 : s 의 타입은 튜플이다.
1 2 3 | t = 1, 2 print(t) # (1, 2) print(type(t)) # <class 'tuple'> | cs |
- 그래서 enumerate() 이런식으로 사용한다.
1 2 3 | for i, k in enumerate(a): print(i, k, end=' ') print() | cs |
- list 로 강제 캐스팅하기
1 2 | a = list(range(0, 10, 2)) print(a) # [0, 2, 4, 6, 8] | cs |
- 레퍼런스
1 2 3 4 5 6 7 | a = list(range(0, 10, 2)) print(a) # [0, 2, 4, 6, 8] b = a; a[0] = 99 print(a) # [99, 2, 4, 6, 8] print(b) # [99, 2, 4, 6, 8] | cs |
>> 6 번 라인의 결과는 명확하다.
>> 7 번 라인의 결과는..???
레퍼런스 개념으로 a와 b는 같은 리스트를 가리킨다..!!
>> 4 번 라인을 얕은복사 라고 한다. (shallow copy)
>> 데이터가 같이 바뀌므로 주의해야한다.
- 데이터의 복사 (깊은복사)
1 2 3 4 5 6 7 | a = list(range(0, 10, 2)) print(a) # [0, 2, 4, 6, 8] c = a.copy(); a[0] = 99 print(a) # [99, 2, 4, 6, 8] print(c) # [0, 2, 4, 6, 8] | cs |
>> copy() 를 사용한다.
- 음수 인덱스
1 2 3 | a = list(range(0, 10, 2)) print(a) # [0, 2, 4, 6, 8] print(a[0], a[-1]) # 0 8 | cs |
>> 파이썬은 음수 인덱스를 지원한다. -1은 마지막 값, -2은 뒤에서 두번째 값
'Language > Python' 카테고리의 다른 글
<3-1> 파일 입출력 (0) | 2018.02.23 |
---|---|
<2-3> 기상청의 전국 날씨정보 파싱, 외부 모듈 추가 (0) | 2018.02.22 |
<2-1> 제어문과 반복문의 연결고리 (0) | 2018.02.06 |
<1-7> 정규표현식 with Python (0) | 2018.02.03 |
<1-6> 정규표현식 (Regular Expression) (0) | 2018.02.02 |
180213 튜터링 - 연결리스트, 양방향, 원형 연결리스트
< 숙제 review >
1) 팰린드롬인지 판단한는 함수 재귀함수로 구현하기
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #include <stdio.h> #include <string.h> int isP(char str[], int s, int e) { if(s >= e) return 1; return str[s]==str[e] ? isP(str, s+1, e-1) : 0; } int main() { char str[100]; scanf("%s", str); isP(str, 0, strlen(str)-1) ? puts("True") : puts("False"); return 0; } | cs |
>> 첫번째 인덱스와 마지막 인덱스의 문자가 같을때, 그 안의 문자열이 팰린드롬이면 팰린드롬이다.
2) 리스트의 내용을 모두 출력하는 함수 만들기
1 2 3 4 5 6 7 8 | void printList(List *list) { Node *p = list->head; while(p != NULL) { printf("%d\n", p->data); p = p->next; } } | cs |
< Tutoring >
< 연결리스트의 전체노드 삭제 >
1 2 3 4 5 6 7 8 9 10 | void deleteList(List *list) { Node *p = list->head; while(p != NULL) { Node *tmp = p; p = p->next; free(tmp); } init(list); } | cs |
>> 위 예제의 응용에 불과하다고 생각함.
>> 동적할당으로 생성된 변수는 free() 를 통해 해제를 시킬 수 있다.
>> 9번은 다 지우고 난 다음 초기화를 다시 해주는 역할 정도..
< 연결리스트에서 특정 노드의 삭제 >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | void deleteNode(List *list, int pos) { int k = 1; Node *prev, *cur = list->head; if(pos == 1) { list->head = list->head->next; free(cur); return ; } while(k < pos) { k++; prev = cur; cur = cur->next; } prev->next = cur->next; free(cur); } | cs |
>> 11~14 에서 첫번째 노드가 1번 노드라고 할 때, k번째 노드는 cur 가 가리키게 된다.
>> 하지만 위의 코드는 pos 의 값이 노드의 갯수보다 큰 값이 들어오면 에러가 발생한다.
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 | void deleteNode2(List *list, int pos) { int k = 1; Node *prev, *cur = list->head; if(cur == NULL) return ; if(pos == 1) { list->head = list->head->next; free(cur); return ; } while(cur != NULL && k < pos) { k++; prev = cur; cur = cur->next; } if(cur == NULL) { puts("Position does not exist."); return ; } prev->next = cur->next; free(cur); } | cs |
>> 어떤 부분들이 바뀌었는지 비교해봐 얘들아.. ㅎㅎ
>> 그외 List 주머니에 사이즈 관련 변수 하나 만들어서 노드의 개수를 카운트 해나가면서
pos 값이 그 사이즈 안에 있는 값인지 체크하는 방법으로 해도 되고, 상황에 맞게 하면 될듯.!!
< 원형연결리스트의 삽입 (앞에) >
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 | #include <stdio.h> #include <stdlib.h> typedef struct node { int data; struct node *next; } Node; typedef struct list { Node *head; } List; void init(List *list) { list->head = NULL; } void CircularListAdd(List *list, int data) { Node *p, *newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; if(list->head == NULL) { list->head = newNode; newNode->next = newNode; return ; } p = list->head; while(p->next != list->head) p = p->next; p->next = newNode; newNode->next = list->head; //list->head = newNode; } void printCircularList(List *list) { Node *cur = list->head; if(cur == NULL) return ; do { printf("%d\n", cur->data); cur = cur->next; } while(cur != list->head); } int main() { List list; init(&list); CircularListAdd(&list, 1); CircularListAdd(&list, 3); CircularListAdd(&list, 7); CircularListAdd(&list, 5); printCircularList(&list); return 0; } | cs |
>> 18 : 원형 연결리스트의 데이터를 삽입하는 함수.
>> 38 : 원형 연결리스트의 데이터를 출력하는 함수
>> 60 의 결과는 1, 3, 7, 5
>> 35 의 주석을 해제했을 때, 60의 결과는 5, 7, 3, 1
>> 즉 35가 없으면 뒤로 삽입, 있으면 앞으로 삽입을 하는 결과가 만들어진다.
>> 다만 위의 코드에서는 삽입을 할때, 항상 맨 마지막 노드를 찾아야 하는 번거로움(?)이 있다.
하지만 헤드포인터를 테일이라고 생각하고 코드를 작성하면 그럴필요가 없어진다..!!
1 2 3 4 5 6 7 8 9 10 11 12 13 | void CircularListAdd2(List *list, int data) { Node *newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; if(list->head == NULL) { list->head = newNode; newNode->next = newNode; return ; } newNode->next = list->head->next; list->head->next = newNode; //list->head = newNode; } | cs |
>> head 를 tail 이라고 생각하면 된다.
>> 12 가 없으면 앞으로 삽입, 12가 있으면 뒤로 삽입하는 코드가 된다.
< 원형연결리스트의 노드들 중 홀수의 갯수 세기 >
- printCircularList() 에서 홀수인지만 판단한는 조건만 추가하고 계산 후 그 값을 리턴하면 된다.
- 그러니 우리는 if(cur->data & 1) 이라는 표현에 대해 알아보자.
>> & 는 비트 연산자로 각 비트별 AND 연산을 수행한다.
>> 참고로 모든 홀수의 마지막 비트(2^0)은 항상 1 이다.
모든 짝수의 마지막 비트는 항상 0 이다.
>> 1 은 8비트 기준 00000001 이다.
>> 그러므로 1과 & 연산을 하면, 마지막 비트를 제외한 비트는 1이든 0이든 AND 연산의 결과는
0이 나온다. 그렇기 때문에 홀수와 1에 대해 &(AND) 연산을 하면 항상 1이 나온다.
>> 조건식에서 1은 참을 의미한다..
cf) -1 은 비트로 표현하면 1로만 구성이 된다. 8비트라면 11111111 이 된다.
>> 1을 더하면 0이 되므로 증명 끝..
>> -2는 -1에서 1을 빼면 된다. 그러므로 -2는 8비트기준 11111110 이 된다.
>> -3은 -1에서 2를 빼면 된다. 그러므로 -3은 8비트 기준 11111101 이 된다.
>> 작은 수들은 굳이 2의 보수 취하지 않고도 이런식으로 구할 수 있다.
< 양방향 연결리스트의 삽입 >
- 우리가 지금까지 했던 연결리스트는 한방향으로만 연결이 되어 있다.
하지만, 양방향 연결리스트는 말 그대로 양방향으로 연결이 되어 있다. 그러므로 prev 같은 노드
포인터가 필요없어진다.
- 노드에 대한 디자인도 새로 해야한다.
1 2 3 4 5 | typedef struct node { int data; struct node *next; struct node *prev; } Node; | cs |
>> 4 : 이전 노드를 가리키기 위한 포인터가 추가되었다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | void insertNode(List *list, int data) { Node *newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; newNode->next = NULL; newNode->prev = NULL; if(list->head == NULL) list->head = newNode; else { newNode->next = list->head; list->head->prev = newNode; list->head = newNode; } } | cs |
>> 앞으로 삽입하는 코드.
>> 6, 12번 줄이 추가가 된다.
< 더미노드를 이용한 양방향 연결리스트의 삽입 >
- 더미노드를 사용하면 list->head 가 가리키는 노드가 바뀌는 것에 대한 염려를 안해도 된다.
- 더미노드를 사용하면 init() 함수를 수정해주어야 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | void init(List *list) { list->head = (Node*)malloc(sizeof(Node));; list->head->prev = NULL; list->head->next = NULL; } void insertNode(List *list, int data) { Node *newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; newNode->next = list->head->next; list->head->next = newNode; newNode->prev = list->head; } | cs |
>> 그리고 삽입코드는 위와 같이 쓸 수 있다.
< 숙제 >
- 복습잘하기
- 이중연결리스트에서 position 값이 주어졌을 때, 해당 위치에 노드를 삭제하는 함수 만들기
- 양의 정수를 입력 받았을 때, 3자리 마다 , 를 찍어서 출력해주는 함수(재귀로)
input : 1000000 >> output : 1,000,000
- 스택, 중위식을 후위식으로 표기하는 방법, 후위식을 계산하는 방법 예습해오기
'Tutoring > 17-2 Data Structure (Winter)' 카테고리의 다른 글
180301 튜터링 - 큐(Queue) (0) | 2018.03.01 |
---|---|
180301 튜터링 - 스택의 응용 (수정:180514) (0) | 2018.03.01 |
180220 튜터링 - 스택 (0) | 2018.02.21 |
180206 튜터링 - 연결리스트 (0) | 2018.02.06 |
180130 튜터링 - 재귀함수 만들기, 분석하기 (0) | 2018.02.06 |
<1-2> How To Play "River Flows In You" On Guitar (arranged by Sunga Jung) (guitar lesson / tutorial) Part 2
How To Play "River Flows In You" On Guitar (arranged by Sunga Jung) (guitar lesson / tutorial) Part 2
튜토리얼 영상 : http://www.goliathguitartutorials.com/riverflows-part-2.html
open : 3
4F4S : 4
open : 3, 6 together
2F5S, 2F4S(Em) : 5 then 4
open 3 then hammer up to the 2F3S
3F5S : 2, 5 together
2F4S : 4, 3 then 4, 3, 2 and hammering 1F2S
3F2S, 3F6S : 2, 6 together
4, 3 again.
1F2S : 2 and pull off
2F3S : 4, 3
intro one more time but slight different.
3F1S, 2F4S : 1, 4 together
2F1S, 2F4S : 1, 3 together
3F1S : 1
2F4S : 4 then 2
2F1S : 1, 3 together
3F1S : 1
3F1S, 3F2S, 3F5S : 5 then 3 then 2 then 1
1F2S, 3F4F : 5 then 3 then 2
3F3S, 3F6S : 3, 6 together
4F3S : 3
1F2S : 2 (index finger)
3F2S : 4, 3, 2, toghether quickly
2
2F3S : 4, 3 together
7F1S : 1
5F1S : 1, 4 together
open 4
3F2S, 5F1S : 1, 2 together and
then hammer up to the 7F1S and pull off
3F1S : 1
2F1S : 1
2F1S : 1, 6
2F4S : 4, 3
open 3 and then hammer up
3F5S : 2, 5
2F4S : 4, 3
open : 2 then 4, 3, 2 and hammering 1F2S
3F2S, 3F6S : 2, 6 together
4, 3 again.
1F2S : 2 and pull off
2F3S : 4, 3
'Play the guitar.' 카테고리의 다른 글
시대를 초월할 마음 Ep.01-02 (0) | 2018.03.24 |
---|---|
<1-1> How To Play River Flows In You On Guitar (arranged by Sunga Jung) (guitar lesson / tutorial) Part 1 (0) | 2018.01.29 |
<2> 레퍼런스 (reference)
- 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 | #include <cstdio> typedef struct arr100 { int arr[100]; } Arr100; void c_Swap(int *a, int *b) { int t = *a; *a = *b; *b = t; } void ref_Swap(int &a, int &b) { int t = a; a = b; b = t; } int sum(Arr100 &t) // Decreasing memory overhead. { int Sum=0; for(int i=0; i<100; i++) Sum += t.arr[i]; return Sum; } int main() { int x = 3; int y = 5; // int &ref; => impossible // &ref = x; => impossible int &ref = x; printf("%d %d\n", x, ref); // 3 3 printf("%p %p\n", &x, &ref); // 0x7ffee122ca68 0x7ffee122ca68 c_Swap(&x, &y); printf("%d %d\n", x, y); // 5 3 ref_Swap(x, y); printf("%d %d\n", x, y); // 3 5 Arr100 A; for(int i=0; i<100; i++) A.arr[i] = 100-i; int Sum = sum(A); printf("%d\n", Sum); // 5050 return 0; } | cs |
>> 34 : 선언과 동시에 초기화가 필요하다.
>> 35 : 한번 가리킨 대상을 바꿀 수 없다.
>> 36 : 레퍼런스의 선언. 변수이름 앞에 &를 붙인다.
자료형 &변수명 = 참조할 변수명; 의 형태를 가진다.
>> 37 : x와 x를 reference 로 하는 ref 는 같은 값을 갖는다.
>> 38 : 역시 같은 주소를 갖는다. 즉 어떤 변수에 새로운 이름을 부여한다고 생각하면 된ㄷ
>> 40 : c 언어에서의 swap 함수이다. 포인터를 사용
>> 43 : 레퍼런스를 이용한 swap 으로, 매개변수를 전달할 때 주소를 전달하지 않으며,
14 라인에서 보듯이 매개변수를 참조형으로 선언해서 전달받는다.
>> 51, 21 : 이렇게 참조형으로 매개변수를 전달 받으면, 메모리 오버헤드를 줄일 수 있다.
매개변수도 일종의 지역변수 이므로 그만큼의 메모리를 차지하지만, 참조형으로 전달
받으면 그렇지 않다. 재귀함수에서 변하지 않는 객체를 넘길 경우에서 유용하다.
- 그 외 상수값으로 초기화 할 수 없다. 바인딩을 할 수 없다는 컴파일 에러 발생
1 | int &refConstant = 10; | cs |
error: non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'
int &refConstant = 10;
- 그 외 레퍼런스로 이루어진 배열을 만들 수 없다고 한다.
- 기본적인 내용은 이정도 이며, 나중에 참조형이 참 재미있는(?) 기능임을 알게 될 것이다.
(함수의 리턴형이 참조형인 경우)
- 또한, 래퍼런스의 필요성은 [] 등 오퍼레이터 오버로딩에서 나타난다고 한다.
*vec[10] = 3; 같은 이상한 표현을 쓰지 않아도 된다고 하는데,
이 글을 작성하고 있는 시점에서 아직 은 모르는 내용이다.....
- '레퍼런스로 이루어진 배열'(int &arr[10])은 만들 수 없지만, '배열의 레퍼런스'(int (&arr)[10])은
만들 수 있다고 한다.. 함수의 인자로 넘겨서 항상 특정 길이를 가진 배열만을 받게 할 수도 있지만,
그러느니 그냥 std::array나 std::vector 쓰는 게 낫다고 함.
출처 : http://kks227.blog.me/60204949464
'Language > C++' 카테고리의 다른 글
<3> namespace (네임스페이스) (0) | 2018.02.22 |
---|---|
<1> C++ 에서 확장된 기능 (0) | 2018.02.12 |
<1> C++ 에서 확장된 기능
- 변수를 생성과 동시에 초기화 하는 방법 추가.
1 2 3 4 5 | int a = 5; int a(5); int a=2, b=3; int a(2), b(3); | cs |
>> 모든 자료형에 적용 가능.
>> 배열은 초기화 방법이 다르므로 이런식으로는 불가능
- for 문의 초기식에서 변수 선언 가능
1 2 | for(int i=0; i<n; i++) scanf("%d", &k); | cs |
>> 여기서 i 의 스코프(scope)는 해당 for 문의 안쪽이 된다.
- bool 타입의 자료형 추가.
1 2 | bool isTrue = true; bool isFalse = false; | cs |
- 형변환(type casting) 의 추가.
1 2 3 4 5 | double d = 3.14; int n = (int)d; double f = 3.141592; int k = static_cast<int>(f); | cs |
>> static_cast<자료형>(값) 의 형태를 가지고 있다.
>> 용도는 추후 포스팅..
- c 언어의 헤더파일 사용방법
1 2 3 4 5 | #include <stdio.h> // C #include <stdlib.h> // C #include <cstdio> // C++ #include <cstdlib> // C++ | cs |
>> 뒤의 .h 를 없애고, 앞에 c를 붙인다.
출처 : http://kks227.blog.me/60204924344
'Language > C++' 카테고리의 다른 글
<3> namespace (네임스페이스) (0) | 2018.02.22 |
---|---|
<2> 레퍼런스 (reference) (0) | 2018.02.12 |
[ARTIK530] aptitude 를 이용한 player 설치하기
( https://developer.artik.io/documentation/artik/getting-started/up-to-date.html )
# apt-key add /var/lib/apt/keyrings/artik-platform-keyring.gpg
>> 이전에 안 했을 경우..
# sudo apt-get update
# apt-get upgrade
# apt install build-essential
# apt-get install aptitude
# aptitude install mplayer
(N – Y - Y)
>> 안되면 될때까지..!!
'Etc. > G2C' 카테고리의 다른 글
[ARTIK530] ubuntu로 시작하기 (0) | 2018.01.31 |
---|
180206 튜터링 - 연결리스트
< 재귀함수 숙제 review >
- 1부터 n까지의 숫자중 홀수/짝수의 합 구하기
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include <stdio.h> int oddSum(int n) { if(n < 1) return 0; if(n%2 == 0) n--; return n + oddSum(n-2); } int evenSum(int n) { if(n < 1) return 0; if(n%2 == 1) n--; return n + evenSum(n-2); } int main() { int n = 100; printf("%d\n", oddSum(n)); printf("%d\n", evenSum(n)); return 0; } | cs |
>> 6번째 줄을 if(!(n%2)) 로 쓸 수도 있다.
>> 13번째 줄은 if(n&1) 로 쓸 수 있다.
- 배열의 요소들 중에서 최대값 구하기.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #include <stdio.h> int f(int arr[], int n) { int k; if(n == 0) return arr[0]; k = f(arr, n-1); return k > arr[n] ? k : arr[n]; } int main() { int arr[] = {10, 2, 30, 11, 50, 33}; printf("%d\n", f(arr, 5)); return 0; } | 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 25 | #include <stdio.h> int max; int f2(int arr[], int n) { int k; if(n == 1) { max = arr[n] > arr[n-1] ? arr[n] : arr[n-1]; return arr[n] > arr[n-1] ? arr[n-1] : arr[n]; } k = f2(arr, n-1); if(arr[n] < k) return k; if(arr[n] > max) { int t=max; max=arr[n]; return t; } return arr[n]; } int main() { int arr[] = {50, 10, 2, 30, 11, 33}; printf("%d\n", f2(arr, 5)); return 0; } | cs |
>> n 은 마지막 인덱스
< 연결리스트 >
- 노드 디자인 하기
1 2 3 4 | typedef struct node { int data; struct node *next; } Node; | cs |
>> 자기참조 구조체
>> typedef 의 역할 // ex) typedef int INT;
>> 구조체는 자료형이다. 사용자 정의 자료형. 즉, 우리가 만든 자료형이다.
- List 주머니(?) 디자인 하기.
1 2 3 | typedef struct list { Node *head; } List; | cs |
- 리스트 생성 후 초기화 하기
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include <stdio.h> typedef struct node { int data; struct node *next; } Node; typedef struct list { Node *head; } List; void init(List *list) { list->head = NULL; } int main() { List list; init(&list); return 0; } | cs |
>> 19 : List 타입의 list 변수 생성
>> 20 : list 를 초기화 하는 코드. C++에서 생성자를 수동으로 실행시킨다고 생각하면 될 것 같다.
- 데이터 삽입하기.
1 2 3 4 5 6 7 8 9 10 11 12 13 | void insertNode(List *list, int data) { Node *newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; newNode->next = NULL; if(list->head == NULL) list->head = newNode; else { newNode->next = list->head; list->head = newNode; } } | cs |
>> 3 : 동적할당으로 #include <stdlib.h> 헤더파일이 필요하며,
결과 값으로 이름없는 변수의 주소값을 리턴한다. 그리고 그 주소를 newNode 에 저장.
>> 3, 5, 1 순으로 삽입을 하면 (head)->(1)->(5)->(1)->NULL 모양의 리스트가 만들어 진다.
즉, 앞쪽으로 데이터가 삽입이 된다.
(그림은 머릿속으로.....)
>> newNode->data : newNode가 가리키는 변수의 멤버 data (고요속의 외침..ㅎㅎ)
>> 아래와 같이 분기를 하지 않아도 될 것 같다.
1 2 3 4 5 6 7 | void insertNode(List *list, int data) { Node *newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; newNode->next = list->head; list->head = newNode; } | cs |
>> 검증은 못해봄. 누가 테스트 해보고 결과좀 알려줘. ㅎ
- 데이터 뒤로 삽입하기.
1) 리스트 주머니 수정하지 않고 해보기.
2) 리스트 주머니를 수정해서 해보기.
1) 의 경우
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | void insertNodeBack(List *list, int data) { Node *prev, *newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; newNode->next = NULL; if(list->head == NULL) { list->head = newNode; } else { prev = list->head; while(prev->next != NULL) prev = prev->next; prev->next = newNode; } } | cs |
>> 12-13 : prev 를 통해 맨 마지막 노드를 찾는 코드이다.
>> 14 : 맨 마지막 노드를 찾았으면, 거기에 새 노드를 연결하면 될 듯.
### 자료구조 공부할 때, 특히 포인터등이 헷갈릴때는 그림을 그려가면서 해봐 얘들아 ㅎㅎ
### 숙 제 ###
- 복습 잘하기.
- 어떤 문자열이 주어졌을 때, 해당 문자열이 팰린드롬(회문)인지 판단하는 함수 재귀함수로 만들기
- 리스트의 내용을 모두 출력하는 함수 만들기
- 양방향 연결4리스트, 환형 연결리스트 예습해오기.
'Tutoring > 17-2 Data Structure (Winter)' 카테고리의 다른 글
180301 튜터링 - 큐(Queue) (0) | 2018.03.01 |
---|---|
180301 튜터링 - 스택의 응용 (수정:180514) (0) | 2018.03.01 |
180220 튜터링 - 스택 (0) | 2018.02.21 |
180213 튜터링 - 연결리스트, 양방향, 원형 연결리스트 (0) | 2018.02.14 |
180130 튜터링 - 재귀함수 만들기, 분석하기 (0) | 2018.02.06 |
180130 튜터링 - 재귀함수 만들기, 분석하기
< 180130 튜터링 >
1 재귀함수 만들기.
>> 함수를 잘 정의하고, 그 정의를 그대로 활용하기
>> 어떻게 쪼갤지 생각하기..
>> 언제까지??(재귀의 종료, 탈출조건)
>> 점화식을 알고 있다면 그대로 표현하기.
- 팩토리얼 계산하는 함수
- 1부터 n까지의 합 구하는 함수
- 1 부터 n 까지 출력하는 함수
- n 부터 1까지 거꾸로 출력하는 함수
- a 의 n승 (파워함수)을 구하는 함수
- 배열 요소들의 합 재귀함수로 구하기.
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 | #include <stdio.h> int sum(int n) { if(n < 1) return 0; return n+sum(n-1); } int evenSum(int n) { if(n < 1) return 0; if(n%2 != 0) n--; return n+evenSum(n-2); } void print1(int n) { if(n < 1) return ; print1(n-1); printf("%d\n", n); } void print2(int n) { if(n < 1) return ; printf("%d\n", n); print2(n-1); } int main() { int n; scanf("%d", &n); printf("%d\n", sum(n)); printf("%d\n", evenSum(n)); print1(n); // 1 to n puts(""); print2(n); // n to 1 } | cs |
2. 함수의 호출과정
- 하노이 타워 코드가 왜 그렇지 구현되어 있는지.
(이해 안되면, Hanoi(3, ‘A’, ‘B’, ‘C’); 손으로 써가면서 따라가봐 ㅎㅎㅎㅎ)
- 아래 세 함수의 결과는 같지만, 호출 순서가 어떻게 다른지 생각해보기
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | void f(int n) { if(n == 0) return ; f(n-1); f(n-1); printf(“*”); } void f(int n) { if(n == 0) return ; f(n-1); printf(“*”); f(n-1); } void f(int n) { if(n == 0) return ; printf(“*”); f(n-1); f(n-1); } | cs |
3. 동적 프로그래밍
- 피보나치 함수를 구해주는 함수에서 전달값이 크면 왜 느려지는지 생각해보기.
- 이를 해결하기 위한 방법 중 하나를 소개 했지만, 어려우면 넘어가도 됨.
(메모이제이션)
### 숙제 ###
- 복습 잘 하기.
- 1부터 n 까지의 수 중 홀수(혹은 짝수)의 합 구하는 함수 구하기(재귀)
- 배열의 요소들 중 최대값(혹은 최소값) 재귀함수로 구하기.(재귀)
- 배열의 요소들 중 두번째 최대값 재귀함수로 구하기. (재귀)
(힌트가 필요하면 갠톡으로..)
- 연결리스트 개념 공부해오기
'Tutoring > 17-2 Data Structure (Winter)' 카테고리의 다른 글
180301 튜터링 - 큐(Queue) (0) | 2018.03.01 |
---|---|
180301 튜터링 - 스택의 응용 (수정:180514) (0) | 2018.03.01 |
180220 튜터링 - 스택 (0) | 2018.02.21 |
180213 튜터링 - 연결리스트, 양방향, 원형 연결리스트 (0) | 2018.02.14 |
180206 튜터링 - 연결리스트 (0) | 2018.02.06 |
<2-1> 제어문과 반복문의 연결고리
동영상 강의 : http://pythonkim.tistory.com/notice/77
# Day_02_01_loop.py
# 제어문과 반복문의 연결고리
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 | # 문제 # count 에 0~3 사이의 숫자를 입력 받아서 # 입력받은 숫자 만큼 아침인사를 해봅니다. # 2가지 종류의 코드를 만들어보기. def ans1(): count = int(input('count : ')) if count == 1: print("Good Morning!") elif count == 2: print("Good Morning!") print("Good Morning!") elif count == 3: print("Good Morning!") print("Good Morning!") print("Good Morning!") def ans2(): count = 2 if count >= 1: print("Good Morning!") if count >= 2: print("Good Morning!") if count >= 3: print("Good Morning!") def ans3(): count = 2 i = 0 if i < count: print("Good Morning!") i += 1 if i < count: print("Good Morning!") i += 1 if i < count: print("Good Morning!") i += 1 if i < count: print("Good Morning!") i += 1 if i < count: print("Good Morning!") i += 1 def ans(): count = 3 i = 0 while i < count: print("Good Morning!") i += 1 | cs |
- 규칙
# 규칙을 찾는 것이 중요. (시작, 종료, 증감)
# 1 3 5 7 9 1~9 까지 2칸씩 건너뛴다.
# 0 1 2 3 4 0~4 까지 1칸씩 건너뛴다.
# 5 4 3 2 1 5~1 까지 -1칸씩 건너뛴다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | def rule1(): i = 1 # 시작 while i <= 9: # 종료 print("Hello") i += 2 # 증감 def rule2(): i = 0 while i <= 4: print("Hello") i += 1 def rule3(): i = 5 while i >= 1: print("Hello") i -= 1 | cs |
>> Python 에서는 i++ 과 같은 증감 연산자를 제공하지 않는다고 한다. ㅜㅜ
>> 세 개 모두 "Hello" 를 5번 출력한다.
- 줄이 바뀌지 않게 하기
1 2 3 4 5 | rint('Hello', end=' ') print('python') # 실행결과 # Hello python | cs |
>> end 파라미터를 사용하면 된다.
- end 파라미터의 또 다른 예시.
1 2 3 4 5 | print('Hello', end='***') print('python') # 실행결과 # Hello***python | cs |
- 문제
# 0 ~ 99 까지 출력하는 함수를 만드시오.
1 2 3 4 5 | def show100(): i = 0 while i <= 99: print(i, end=' ') i += 1 | cs |
- for in 문
1 2 3 4 5 6 7 8 9 10 11 12 13 | for i in range(0, 10, 1): print(i, end=' ') print() for i in range(0, 10): print(i, end=' ') print() for i in range(10): print(i, end=' ') print() # 0 1 2 3 4 5 6 7 8 9 | cs |
>> 시작 : 0, 종료 : 10, 증감 : 1
>> 시작, 종료, 증감이 명확한 경우 for 문을 사용한다.
>> 증감의 기본은 1, 시작의 기본은 0
# 문제
# count 에 0~3 사이의 숫자를 입력 받아서
# 입력받은 숫자 만큼 아침인사를 해봅니다.
# 2가지 종류의 코드를 만들어보기.
1 2 3 4 5 6 7 8 9 10 11 | def sumOfOddEven(): odd, even = 0, 0 for i in range(1, 100): if i%2 == 1: odd += i else : even += i return odd, even s1, s2 = sumOfOddEven() print(s1, s2) # 2500 2450 | cs |
# 난수
1 2 3 4 5 | import random print(random.randrange(10)) print(random.randrange(10, 20)) print(random.randrange(10, 20, 2)) | cs |
>> random 모듈을 import 한다.
>> randrange() 는 range() 와 같이 3가지의 종류의 파라미터를 갖는다.
>> 5 줄의 경우 [10, 20) 에서 2씩 증가하는 수들 중에서 난수가 발생함.
# placeholder
1 2 | for _ in range(5): print(random.randrange(10), end=' ') | cs |
>> for i in range(5): 라고 썼을 때, i 를 사용하지 않는다.
>> 하지만 i 를 지우면 에러.
>> 필요가 없는 변수로 의미를 약화시킬 수 있음. _ 로 표현 (placeholder)
>> _ 는 변수이지만 변수로 사용하지 않겠다는 의미..
# random.seed(1)
1 2 3 | random.seed(1) for _ in range(5): print(random.randrange(10), end=' ') # 2 9 1 4 1 | cs |
>> 난수값을 고정시킬 수 있다.
>> seed 가 1이 되고 나서의 첫번째 숫자, 두번째 숫자 ...
>> 프로그램 처음에 딱 한번 호출해서 사용한다.
1 2 3 4 5 | next = 1 def rand(): global next next = next * 1103515245 + 12345 return int(next // 65536) % 32768 | cs |
>> seed() 의 원리 같은 코드라고 한다.
'Language > Python' 카테고리의 다른 글
<2-3> 기상청의 전국 날씨정보 파싱, 외부 모듈 추가 (0) | 2018.02.22 |
---|---|
<2-2> 리스트, 튜플 (0) | 2018.02.15 |
<1-7> 정규표현식 with Python (0) | 2018.02.03 |
<1-6> 정규표현식 (Regular Expression) (0) | 2018.02.02 |
<1-5> 함수(function) (0) | 2018.02.01 |