hmku1의 등록된 링크

 hmku1로 등록된 네이버 블로그 포스트 수는 59건입니다.

C (getchar, putchar) [내부링크]

getchar 함수 원형 : int getchar(void); standard input으로부터 입력 받은 문자를 반환하는 함수. 콘솔 창에서 우리가 입력하는 표준 입력들을 바로 int 타입으로 하나씩 반환해주는 함수이다. ex) char c = (char)getchar(); int c = getchar(); putchar 함수 원형 : int putchar(int c); 매개변수로 들어온 문자가 'c'라고 할 때, 'c'를 standard output에 문자로 출력해주는 함수. 콘솔창에 'c'를 반환해준다. 함수 원형의 데이터 타입이 int로 되어있는데, int 타입으로 인식을 해서 char 타입으로 변환한다. 아스키 코드표와 대응된다고 보면 된다. ex) putchar(80); -> 'P' 반환 putchar('P'); -> 'P' 반환 아래의 블로그를 참고하여 작성된 포스트입니다. [C언어/C++] getchar,putchar 문자 입출력 함수에 대해서. 안녕하세

C (파일 입출력) [내부링크]

C언어에서는 직접적으로 컴퓨터에 존재하는 파일을 수정할 수 있기에 보안이라는 측면에서 아주 중요하다. create, open, read, close, write, rename, delete를 통해 파일 입출력을 다룰 수 있다. int main() { FILE* fp = NULL; fp = fopen("output.txt", "w"); // w는 write 모드, r은 read 모드. read모드는 파일이 존재해야 열 수 있음 // 파일 여는 걸 성공 여부는 아래와 같은 코드로 출력 if (fp == NULL) { printf("파일 열기 실패\n"); } else { printf("파일 열기 성공"); } fputc('h', fp); // fputc는 한 글자 write 하는 것 fputc('e', fp); fputc('l', fp); fputc('l', fp); fputc('o', fp); fclose(fp); // 파일을 open했으면 꼭 close 해줘야 한다. return 0

C ( 문자열 공백 입력) [내부링크]

1. char str[100]; scanf("%[^\n]s", &str); 형식지정자 [^]를 사용하는 방법. [^\n]처럼 작성하면 \n이 나오기 이전까지 scanf를 계속 입력 받는다. 2. char str[100]; gets(str); 그저 gets(str)이라고 작성하면된다. 하지만 어떤 곳에서는 비표준적인 함수로 인정되지 않으니 참고하자. 3. char str[100]; fgets(str, 100, stdin); 일반적으로 fgets는 파일을 읽을 때 사용하지만, stdin을 사용하면 문자열을 입력받을 수 있다.

C (동적 메모리) [내부링크]

동적 메모리는 메모리의 유연한 관리를 위해 존재한다. 실행 도중에 동적으로 필요한 만큼 메모리를 할당 받고, 사용이 끝나면 메모리를 반납한다. 이 때 명시적으로 반납해주어야 한다. #include <stdio.h> #include <stdlib.h> //malloc은 stdlib.h 헤더 파일에 포함되어 있다. int main() { int* pi; // malloc 메모리를 할당해라. 그리고 int* 형으로 형변환해라 // sizeof(int) = 4바이트 pi = (int*)malloc(sizeof(int)); if (pi == NULL) { printf("동적 메모리 할당 실패\n"); exit(1); //실행하고 있는 지금 프로그램 자체를 종료 } *pi = 100; printf("%d\n", *pi); //동적 메모리 사용 이후에는 무조건 해당 메모리 반환해야한다. free(pi);//pi에 할당한 메모리를 반환. 주소값 넣어줘야한다. return 0; } free() 함수

The Future of Transport Layer Protocols - 메모 1 [내부링크]

이경한 교수님의 The Future of Transport Layer Protocols 영상을 보며 메모 형식으로 남긴 것입니다. UDP는 TCP와는 달리 application들에서 요구하는 reliability들을 추가할 수 있다 c전송 계층 프로토콜의 덕목 : unreliable한 채널을 가능한 reliable한 것처럼 보이게 하는 것 -> 이것만 만족하면 되느냐냐? 아니다. 그럼 어떤 것을 해줘야할까? Pipelining 송신과 수신으로 이어지는 loop를 어떻게 컨트롤하느냐 -> loop 컨트롤 따라서 전송 계층이 낼 수 있는 효율 달라짐 무작정 utilization을 끌어올리는 것은 latency가 증가하므로 QoS(Quality of Service) 관점에서 그닥 좋은 일은 아님. 따라서 Throughput과 latency의 trade-off 그 사이 어딘가에서 최적의 값을 찾아야 함 cTCP의 중요한 구현 사항 2가지 Flow control : 수신단이 버퍼링할 수 있는

UORA 논문 조사 [내부링크]

이번에 IEEE 802.11ax UORA 환경에서의 성능 향상에 관한 논문을 작성하였는데, 기존 연구자들이 다양한 방법으로 성능 향상에 대한 연구를 진행한 것들을 정리하고자 포스트를 씁니다. 연구실 미팅 자료로 만들어두었던 것을 사진으로 첨부하였습니다. 크게 다음과 같이 구분하였습니다. 적응형 그룹화(Adaptive grouping) 공간 클러스터링(Spatial Clustering) 서브채널 호핑(Subchannel hopping) BO 대신 상보적확률 사용(complementary probability instead of backoff) 추가 반송파 감지(Additional carrier sensing) 재전송 인식(Retransmission awareness) OBO 조절(OBO modification) 그룹화 기반 채널 액세스(grouping based channel access) 인접 채널 간섭 고려(considering adjacent channel interference

The Future of Transport Layer Protocols - 메모 2 [내부링크]

이경한 교수님의 The Future of Transport Layer Protocols 영상을 보며 메모 형식으로 남긴 것입니다. 아래의 포스트에서 이어지는 글입니다. The Future of Transport Layer Protocols - 메모 1 이경한 교수님의 The Future of Transport Layer Protocols 영상을 보며 메모 형식으로 남긴 것입니다... blog.naver.com c 미래의 전송 계층 프로토콜의 KPI Throughput High throughput에 빠르게 도달하는 fast convergence Low latency Fairness throughput과 Low latency를 end-to-end(이하 E2E) 말고, application 관점에서 바라본다고 하면 end-to-end Latency가 곧 높은 처리량이자 저지연이다. 결국 수신단에 도착하는 시간 줄일 수 있다고 한다면 그것이 곧 높은 처리량이자 저지연이다. 여기서 Fairn

[Kotlin] 비트 연산 [내부링크]

비트 연산은 정수형 변수를 10진법 대신 2진법으로 연산할 수 있는 기능이다. 실무에서는 비트 연산은 거의 계산에는 사용하지 않으며 정수형 값을 비트 단위로 나누어 데이터를 좀 더 작은 단위로 담아 경제성을 높이기 위한 용도로 사용된다. 주로 플래그 값(여러 개의 상태값을 0과 1로 담는 방법)을 처리하거나 네트워크 등에서 프로토콜의 데이터 양을 줄이기 위해 자주 사용된다. 0001010111011000101101010 ↑ ↑ 상위 비트 ~ 하위비트 최상위 비트는 0이면 양수, 1이면 음수인 부호비트로 사용하므로 이 부분에는 데이터를 담지 않는 것이 좋다. 먼저 비트를 밀어주는 bitwise shift operators가 있다. shl(shift left)는 부호 비트를 제외한 모든 비트를 좌측으로 밀어주는 기능, shr(shift right)이 있다. 또한 부호 비트를 포함하여 모든 비트를 우측으로 밀어주는 ushr(unsigned shift right)이 있다. 다음은 일반적으로

[Kotlin] kotlinx import 문제(unresolved reference) [내부링크]

kotlinx를 import 하려 시도했을 때 unresolved reference가 뜨는 것을 확인 후 해결을 위해 구글링을 시작했다. 찾아보니 생각보다 쉬운 문제였다. 먼저 Gradle Scripts 폴더의 build.gradle(module)로 들어가보자. 먼저 dependencies 내부에 다음을 복사 후 붙여넣자. implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4") 버전이 다를 수 있으니 아래 Kotlin 깃허브의 Android 부분을 참고하자. GitHub - Kotlin/kotlinx.coroutines: Library support for Kotlin coroutines Library support for Kotlin coroutines . Contribute to Kotlin/kotlinx.coroutines development by creating an account on GitHub.

[Kotlin] 코루틴을 통한 비동기 처리 [내부링크]

비동기로 여러 개의 루틴을 처리하는 동시에 처리할 수 있는 방법을 알아보자. 여태까지 하나의 구문이 끝나면 다른 구문을 실행하는 식으로 모든 구문을 '동기적'으로 실행하였다. 하지만 여러 개의 루틴을 동시에 실행하여 결과를 내고 싶다면 '비동기'처리를 지원하는 코루틴(coroutine)을 사용하면 된다. 코루틴은 메인이 되는 루틴과 별도로 진행이 가능한 루틴으로 개발자가 루틴의 실행과 종료를 마음대로 제어할 수 있는 단위이다. 코루틴을 사용할 때는 코틀린 extension에 kotlinx.coroutines을 모두 import 해야한다. import kotlinx.coroutines.* 코루틴은 제어범위 및 실행범위를 지정할 수 있다. 이를 코루틴의 Scope라고 한다. 기본적으로 GlobalScope와 CoutoutineScope를 지원한다. GlobalScope : 프로그램 어디서나 제어, 동작 가능한 기본 범위 CoroutineScope : 특정한 목적의 Dispatcher를

[Kotlin] View Binding(뷰 바인딩) [내부링크]

21년 이후 코틀린 익스텐션이 지원 중단 되었기에 뷰 바인딩을 사용할 수 밖에 없는 상황이다. 우선 뷰 바인딩 옵션을 Gradle에서 활성화 시켜줘야 한다. build.gradle(Module) 파일의 android 중괄호 내부에 다음을 작성한다. buildFeatures{ biewBinding true } 그리고 우측 상단의 Sync Now 메시지를 클릭한다. 이제 프로젝트 상의 레이아웃 파일들에 바인딩 클래스가 생기고, 이는 각 파일에서 선언했던 뷰들의 id들의 참조가 포함된다. 바인딩 클래스의 이름은 다음과 같은 규칙으로 정해진다. 첫 번째 글자와 언더바의 다음의 첫글자는 대문자, 나머지는 소문자 + Binding 예시 : activity_main_xml → ActivityMainBinding 먼저 activity_main.xml에서 텍스트뷰에 text= "click to hello" id="@+id/click_hello" 를 선언했다고 가정하면, MainActivity.kt

어려운 일 [내부링크]

기도란 그저 한숨 같은 것. 할 수 있는 것이 그것 뿐이니 그저 하는 것.

C (변수, 자료형, 연산자) [내부링크]

1학년 과목에 조교로 투입하게 되어 정리도 할 겸 쓰기로 맘을 먹었다. 일주일 내로 C와 C++ 문법과 개념 등 기초적인 것들을 훑어봐야지! 1학년 친구들의 질문 공세에 답을 선명하게 하지 못하면 몹시 쪽팔릴테니 1학년의 마음으로 접근해 예상 질문도 좀 써봐야겠다. 쓸데없는 질문을 많이도 했던 나에게 친절히 답해준 1학년 때의 조교분들에게 감사하...기는 개뿔 세상에서 제일 불친절했다. 다시 생각하니 한 대 쥐어박고 싶다. 우선 이 글은 맥락과 순서 없이, 내가 정리하고 싶은 것만 쓴다! 내 맘이니 칭얼거리지 말자. C는 고급 언어에 속하면서도 거의 어셈블리어 취급을 받는다. 어셈블리어란 기계어와 일대일 대응이 되는 컴퓨터 프로그래밍의 저급 언어를 뜻한다. python이나 java 같은 객체지향적인 언어들보다 고급 언어들이 많이 나왔고, 그렇기에 C가 어셈블리어 취급을 받는다고 말하는 것이다. 또 C언어에서 사용자 정의 함수, 배열, 문자열, 포인터가 주요하게 다루어지는데, 이를 손

C (조건문, 반복문) [내부링크]

첫 번째 포스트를 끝내고 두 번째로 왔다. 역시 초반부는 껌이다. 정리할 것도 별로 없다. 뒷부분의 포인터를 좀 유심히 다시 봐야겠다. 이번 내용도 1학년의 시선으로 잘 훑어봐야겠다. 우선 이전 포스트에서 다룬 것 중에서 헷갈릴만한 것 하나를 설명하고자 한다. 1번 100 < x < 200 2번 (100 < x) && (x < 200) 임의로 x = 101이라고 하자. 여기서 1번과 같이 표현하면 우선 100 < x 를 연산하여 true 즉 1을 반환하고, x < 200을 연산하니 true 즉 1을 반환한다. 만약 대수학에서의 100 < x < 200을 표현하고 싶다면 2번과 같이 표현하자. 조건문 if~elseif~else부터 switch까지. 이전에 배운 연산자까지 활용한 간단한 예시. 많이도 보았던 윤년이다. #include <stdio.h> int main() { int year = 2016; if ((year % 4 == 0 && year % 100 == 0) || year

C (기본 입출력, 사용자 정의 함수) [내부링크]

우선 1학년 때 흔히들 하는 실수 중 하나인 버퍼 비우기에 대해 이야기 하고자 한다. 형식 지정자를 %c로 하면 enter도 하나의 공백 문자로서 입력 받을 수 있다. 이 enter가 버퍼에 들어가 다음 scanf로 입력을 해야할 때 우리가 아무 것도 입력하지 않았는데도 enter가 입력이 되는 것이다. 이러할 때에는 버퍼를 처리해줄 필요가 있다. getchar()를 사용하면 단 1개의 문자를 버퍼에서 받아낼 수 있다. 그러면 버퍼에 저장된 enter를 효율적으로 처리해줄 수 있다. 기본 입출력 먼저, 아래의 코드에서 &를 붙인 &a는 a의 메모리 주소값을 의미한다. scanf("%d", &a); scanf와 printf 이들은 텍스트 기반의 입출력이며 나중에 GUI를 배우게 되면 사용자에게 글자 뿐만 아니라 이미지를 보여줄 수도 있다. 사용자 정의 함수 정해진 특정한 기능을 수행하는 모듈을 의미하며 함수를 적절히 활용하면 하나의 문제를 잘게 분해할 수 있다. 예를 들어 이진 탐색

C (반복함수, 재귀함수, 배열) [내부링크]

반복함수, 재귀함수 먼저 반복함수는 단순히 while, for 문법을 이용하여 특정한 처리를 반복하는 방식으로 문제를 해결하는 함수이고, 재귀함수는 자신의 함수 내부에서 스스로를 호출함으로써 재귀적으로 문제를 해결하는 함수이다. 재귀함수는 경우에 따라서 아주 간결하고 직관적인 코드로 문제를 해결할 수 있게 해주지만 때에 따라서는 심각한 비효율성을 낳을 수 있기에 알고리즘을 작성할 때 유의할 필요가 있다. 조합을 재귀함수로 구현해보자. 조합은 우선 nCr은 r이 0이거나 n이라면 1이며, nCr(n-1, r-1) + nCr(n-1,r)과 같다. #include <stdio.h> int nCr(int n, int r) { if (r == 0 || r == n) { return 1; } else { return nCr(n - 1, r - 1) + nCr(n - 1, r); } } int main() { int n, r; scanf("%d %d", &n, &r); printf("%d", n

C (포인터) [내부링크]

대망의 포인터! 포인터 예제 중 가장 대표적인 swap 함수 구현이다. #include <stdio.h> void swap(int* x, int* y) { int temp; temp = *x; *x = *y; *y = temp; } int main() { int x = 1; int y = 2; swap(&x, &y); printf("x = %d\ny = %d", x, y); } x = 2 y = 1 실제로 두 변수의 값을 변환할 때는 포인터를 이용해서 함수를 만들어야 한다. 그 이유는 포인터를 이용하지 않게 되면 매개변수로 넘어온 값들은 함수 내에서만 처리가 되기 때문이다. 따라서 포인터를 이용하지 않은 경우에는 두 변수의 값이 바뀌지 않는다. int x = 100; int* y = &x; 라고 한다면 x의 값은 100을 담고 있고, y는 x의 주소값을 갖고 있다. 그리고 *y는 x의 값인 100을 나타낸다. 여기서 x, *y를 바꾸면 100이라는 값이 바뀌는 것이다. 내가 1학년

C (문자열) [내부링크]

문자열 C언어에서 문자열은 char 타입의 배열로 이루어져 있고 이것은 포인터와 같다고 할 수 있다. 그리고 하나 기억해야할 사실! #include <stdio.h> int main() { char a = 'ㄱ'; printf("%c", a); return 0; } ? 위와 같은 코드에서 char a를 'ㄱ'으로 초기화했는데 출력은 ?로 나오는 것을 볼 수 있다. 이는 char 자료형이 1바이트를 할당하는데, 한글은 2바이트를 필요로 하는 탓에 나타나는 현상이다. char array[10]; 마찬가지로 위와 같이 선언하면 영어로 초기화한다면 10글자를 쓸 수 있겠지만, 한글로 초기화한다면 5글자만을 쓸 수 있다. 유의하자! 위의 표를 이전에 선언한 array[10]이라고 하고, 다음과 같이 주솟값이 부여되었다고 생각해보자. 내부적으로 배열은 포인터라고 볼 수 있다. array가 어떠한 값들의 모임을 의미한다면, 값들 중에서 첫 번째 값의 주솟값이 바로 array 자체가 되는 것이다.

C (구조체, 구조체 활용) [내부링크]

이번 포스트에서는 객체지향 프로그래밍에서 사용하는 클래스(Class)와 흡사한 개념으로 사용되는 구조체(Structure)에 대해 알아보자. 구조체란 클래스의 모체가 되는 것으로 여러 개의 자료형을 묶어서 새로운 자료형으로 만드는 방법이다. 배열이 여러 개의 같은 자료형들을 하나로 묶는 것이었다면 구조체는 서로 다른 자료형들을 하나로 묶어서 한꺼번에 다루는 것이다. struct place{ int x, y; char name[] = "우리 집"; } 어떠한 틀이 있을 때 그 안에 들어갈 수 있는 내부적인 변수들을 한꺼번에 지정해줌으로써 위를 예로 들면 place 라는 구조체 변수를 하나 만들어 주게 되면 x, y, name[]과 같은 변수들이 한꺼번에 따라온다. 이러한 구조체가 없다면 코딩은 가능하겠지만 상당히 불편하고, 설계적인 측면에서 굉장히 큰 단점일 것이다. #include <stdio.h> #include <stdlib.h> struct student { int number

[Pandas] 데이터 시각화 [내부링크]

데이터 시각화의 필요성 import seaborn as sns anscombe = sns.load_dataset("anscombe") print(anscombe) print(type(anscombe)) 데이터 시각화를 보여주는 전형적인 사례로 앤스콤 4분할 그래프가 있다. 데이터를 시각화하지 않고 수치만 확인할 때 발생할 수 있는 함정을 보여주기 위한 것이다. 위의 코드를 통해 아래에 'anscombe' 데이터를 출력했다. I, II, III, IV로 분류된 데이터는 각 그룹마다 평균, 분산과 같은 수칫값, 상관관계와 회귀선이 같다. 그래서 이러한 결과만으로 데이터 그룹 I, II, III, IV가 모두 같을 것이라는 '착각'을 할 수 있다. 하지만 시각화하면 데이터 그룹들이 서로 다른 데이터 패턴을 가지고 있다는 것을 금방 알 수 있다. 앤스콤 데이터 집합은 seaborn 라이브러리에 포함되어 있다. 앞서 Pandas에서 read_csv로 csv파일과 tsv 파일을 읽어왔다. se

[Kotlin] 제너릭(Generic) [내부링크]

제너릭(Generic) : 클래스나 함수에서 사용하는 자료형을 외부에서 지정할 수 있는 기능 수퍼 클래스 A와 A를 상속하는 서브 클래스 B가 있다고 해보자. 이 두 클래스의 인스턴스를 공용으로 사용하는 하나의 함수에 패러미터로 받으려면 어떻게 해야할까? 지난 포스트에서 확인한 것처럼 수퍼 클래스인 A의 자료형으로 받으면 B는 자동으로 A로 캐스팅된다. 또한 B의 자료형으로 받아도 A로 캐스팅된다. 따라서 두 클래스 모두 함수의 패러미터로 사용할 수 있다. 하지만 캐스팅은 프로그램의 속도를 저하시킬 수 있다는 단점이 있다. 그래서 제너릭(Generic)이라는 개념이 등장했다. 제너릭(Generic)은 함수나 클래스를 선언할 때 고정적인 자료형 대신 실제 자료형으로 대체되는 타입 패러미터를 받아 사용하는 방법이다. 이 타입 패러미터에 특정 자료형이 할당되면 제너릭을 사용하는 모든 코드는 할당된 특정 자료형으로 대체되어 컴파일된다. 따라서 캐스팅 연산 없이도 자료형을 그대로 사용할 수

[Kotlin] 리스트 [내부링크]

리스트 : 데이터를 모아 관리하는 Collection 클래스를 상속 받는 서브 클래스 중 가장 단순한 형태로 여러 개의 데이터를 원하는 순서대로 넣어 관리하는 형태 리스트 종류 - List<out T> : 생성 시에 넣은 객체를 변경하거나, 추가, 삭제 불가능 - MutableList<T> : 생성 시에 넣은 객체를 변경, 추가, 삭제 가능 리스트를 만들 때는 전용 함수인 listOf(), mutableListOf()를 쓰고 괄호 안에 리스트에 담을 데이터 요소를 나열하면 된다. 또한 MutableList에서는 요소 추가 - add(데이터) - add(인덱스, 데이터) 요소 삭제 - remove(데이터) - removeAt(인덱스) 기타 - 무작위 섞기 : shuffle() - 정렬 : sort() 또한 당연히 list[인덱스] = 데이터 와 같은 형태로 변경도 가능하다. fun main(){ var a = listOf("사과", "딸기", "배") println(a[1]) for(

[Kotlin] 문자열 [내부링크]

이미 String이라는 클래스로 문자열을 다루어보았다. 코틀린에서는 String 클래스와 관련한 여러 속성과 함수가 있다. fun main(){ val test1 = "Test.Kotlin.String" println(test1.length) println(test1.lowercase()) println(test1.uppercase()) val test2 = test1.split(".") println(test2) println(test2.joinToString()) println(test2.joinToString("-")) println(test1.substring(5..10)) } 18 test.kotlin.string TEST.KOTLIN.STRING [Test, Kotlin, String] Test, Kotlin, String Test-Kotlin-String Kotlin 아래에서는 문자열이 비어있는지 여부를 판단하여 boolean 값으로 반환하는 함수들을 알아보자. fun

[Kotlin]null 값 처리 [내부링크]

nullable 변수에서 null을 처리하는 법과 변수 간에 동일성을 확인하는 법을 알아보자. 코틀린에서 nullable 변수를 만들어 객체가 들어있지 않은 null 상태를 만들 수 있다. 하지만 null 상태로 속성이나 함수를 쓰려고 하면 null pointer exception이 발생하기 때문에 nullable 변수를 사용할 때는 null check 없이는 코드가 컴파일 되지 않는다. 예시는 다음과 같다. var sample : String? = null if(sample != null) println(sample.toUpperCase()) null check를 하기 위해 일일히 if문으로 조건을 체크하는 대신 다음도 사용할 수 있다. ?. 참조 연산자 앞에 물음표를 붙여 사용하는 null safe operator 참조 연산자를 실행하기 전에 먼저 객체가 null인지 확인부터 하고 객체가 null이라면 뒤따라오는 구문을 실행하지 않는다. 아래의 예시에서는 객체가 null일 경우

[Kotlin] 함수의 argument다루기, infix 함수 [내부링크]

코틀린에서도 대부분의 언어에서 지원하는 overloading이 지원된다. 이것은 같은 scope 안에서 같은 이름의 함수를 여러개 만들 수 있는 기능이다. 이름이 같더라도 패러미터의 자료형이 다르거나, 패러미터의 개수가 다르다면 서로 다른 함수로 동작할 수 있다. 다만, 패러미터의 이름만 다르고 개수가 동일하다면 overloading할 수 없다. fun main() { read(7) read("Hello") } fun read(x:Int){ println("숫자 ${x}입니다.") } fun read(x:String){ println(x) } 숫자 7입니다. Hello 실행해보면 함수의 이름은 같지만 자료형을 구분하여 함수가 매칭되어 실행되는 것을 확인할 수 있다. 조금 다른 고민을 해보면, 패러미터를 받아야 하는 함수이지만 별다른 패러미터가 없더라도 기본값으로 동작해야 한다면 어떻게 해야할까? 이 때는 default arguments를 사용한다. fun main() { delive

[Kotlin] 중첩 클래스와 내부 클래스 [내부링크]

중첩 클래스는 하나의 클래스가 다른 클래스의 기능과 강하게 연관되어 있다는 의미를 전달하기 위해 만들어진 형식으로 사용할 때는 Outer.Nested()와 같이 외부클래스이름.중첩클래스이름으로 사용하게 된다. class Outer{ class nested{ } } Outer.Nested() 이 때 중첩 클래스 대신 내부 클래스라는 것을 사용할 수도 있다. class 앞에 inner를 붙인 내부 클래스는 혼자서 객체를 만들수는 없고 외부 클래스의 객체가 있어야만 생성과 사용이 가능한 클래스이다. class Outer{ inner class nested{ } } 중첩 클래스는 형태만 내부에 존재할 뿐 실질적으로는 서로 내용을 공유할 수 없는 별개의 클래스인 반면, 내부 클래스는 외부 클래스 안에서 사용되는 클래스이므로 외부 클래스의 속성과 함수의 사용이 가능하다. fun main() { Outer.Nested().introduce() val outer = Outer() val inner

[Kotlin] Data Class와 Enum Class [내부링크]

Data Class : 데이터를 다루는 데에 최적화된 클래스로 5가지 기능을 내부적으로 자동으로 생성해준다. 내용의 동일성을 판단하는 equal()의 자동 구현 객체의 내용에서 고유한 코드를 생성하는 hashcode()의 자동구현 포함된 속성을 보기 쉽게 나타내는 toString()의 자동구현 객체를 복사하여 똑같은 내용의 새 객체를 만드는 copy()의 자동 구현 -> 여기서 copy()를 통해 새 객체를 생성할 때는 똑같은 내용의 객체를 생성할 수도 있지만, 생성자의 패러미터와 똑같은 패러미터를 주어 일부 속성을 변경할 수 있다. val a = Data("A", 1) val b = a.copy("B") --- b는 Data("B", 1)로 생성 속성을 순서대로 반환하는 componentX()의 자동 구현 --> 위의 Data인 b에서는 component1()는 "B", component2()는 1이다. 이 함수는 사용자가 직접 호출하기 위한 함수가 아닌 배열이나 리스트 등에 데이

[Kotlin] 컬렉션(Set, Map) [내부링크]

Set는 List와 달리 순서가 정렬되지 않고, 중복이 허용되지 않는 컬렉션이다. 따라서 Set은 인덱스로 위치를 지정하여 객체를 참조할 수 없으며 contains 함수로 객체가 Set 안에 존재하는지 확인하는 식으로만 사용한다. sampleSet.contains("HELLO") Set 역시 MutableSet이 존재하는데 List와 마찬가지로 객체의 추가, 삭제가 가능가 가능한지 여부에 따라 사용하게 된다. 추가는 add(데이터), 삭제는 remove(데이터)로 사용하게 된다. fun main() { val a = mutableSetOf("귤", "바나나", "키위") for(item in a){ println("${item}") } a.add("자몽") println(a) a.remove("바나나") println(a) println(a.contains("귤")) } 귤 바나나 키위 [귤, 바나나, 키위, 자몽] [귤, 키위, 자몽] true Map은 객체를 넣을 때, 그 객체를

[Kotlin] 컬렉션 함수 1 [내부링크]

이제껏 컬렉션을 for문으로 반복하여 포함된 아이템을 하나하나 꺼내어 사용했다. 하지만 코틀린은 함수형 언어의 특징을 가지고 있기 때문에 좀 더 편리하게 컬렉션을 사용할 수 있다. 컬렉션 함수는 list나 set, map과 같은 컬렉션 또는 배열에 일반 함수 또는 람다 함수 형태를 사용하여 for문 없이도 아이템을 순회하며 참조하거나 조건을 걸고, 구조의 변경까지 가능한 여러가지 함수를 지칭한다. 그 중 하나를 소개하자면 forEach()이다. collection.forEach(){ println(it) } 중괄호 안에서 포함된 모든 아이템을 it이라는 변수로 순서대로 참조할 수 있다. 이렇게 단순히 반복만 하는 함수도 있지만, 특정한 조건을 걸 수도 있다. colletion.filter{ it < 4 } filter 함수는 포함된 모든 아이템 중 주어진 조건에 맞는 객체만 다시 컬렉션으로 만들어서 반환한다. collection.map{ it * 2 } map 함수는 중괄호 안에서

[Kotlin] 컬렉션 함수 2 [내부링크]

이제 조금 더 복잡한 기능을 가진 컬렉션 함수들을 알아보자. 먼저 associateBy 함수이다. 이 함수는 아이템에서 Key를 추출하여 map으로 변환하는 함수이다. 예를 들어 이름과 출생년도가 들어 있는 Person 객체가 있고 이를 List에 넣어두었다고 가정하자. 이 List를 이름을 Key로 하고 객체를 value로 하는 map으로 변경하려면 아래와 같이 하면 된다. 중괄호 안에 Key로 사용할 이름, 속성을 넣어주면 자동으로 반환해준다. name year 김준호 1999 이지환 2000 정재민 2000 --- collection.associateBy{ it.name } 다음은 groupBy 함수이다. 이는 Key가 같은 아이템끼리 배열로 묶어 map으로 만드는 함수이다. 특정한 값을 Key로 지정하여 해당 값을 가진 객체끼리 묶은 배열을 value로 하는 map을 만들어 준다. collection.groupBy{ it.year } --- 1999 -> [ 김준호 ] 200

[Kotlin] 변수의 활용(상수, lateinit, lazy) [내부링크]

변수에 대한 몇 가지 주의할 내용과 다른 방법으로 사용하는 것을 알아보자. var은 한 번 할당한 객체가 있더라도 다른 객체로 변경하여 할당할 수 있고, val은 한 번 객체를 할당하면 다시 할당된 객체를 변경할 수 없다. 하지만 주의해야할 점은 val은 할당된 객체를 바꿀 수 없을 뿐이지, 객체 내부의 속성을 변경할 수 없는 것은 아니라는 것이다. 그런데 절대 변경이 불가능한 것도 있는데, 바로 상수이다. 상수는 컴파일 시점에 결정되어 절대 바꿀 수 없는 값이다. 선언은 아래와 같이 val 앞에 const를 붙이면 된다. const val CONST_A = 1234 상수로 선언될 수 있는 값은 기본 자료형만 가능하며 런타임에 생성될 수 있는 일반적인 다른 클래스 객체들은 담을 수 없다. 상수는 클래스의 속성이나 지역 변수 등으로는 사용할 수 없으며 반드시 companion object 안에 선언하여 객체의 생성과 관계없이 클래스와 관계된 고정적인 값으로만 사용하게 된다. 상수의 이

[Kotlin] 클래스의 기본 구조 [내부링크]

클래스 : '값'과 그 값을 사용하는 '기능'들을 묶어놓은 것 우리가 이제껏 사용한 자료형들도 코틀린 내부에서는 클래스로 만들어져 있다. 클래스는 고유의 특징값인 '속성'과 기능의 구현인 '함수'로 이루어져 있다. 클래스는 인스턴스를 만드는 틀이다. 인스턴스란 클래스를 이용해서 만들어내는 서로 다른 속성의 객체를 지칭하는 용어이다. 예를 들어 입력할 데이터로 사람의 정보를 저장하는 클래스에서 A, B, C라는 사람의 정보를 저장한다고 하면 A,B,C라는 인스턴스가 만들어지는 것이다. 자주 사용하는 공통 기능은 클래스 내에 함수로 넣어주게 된다. fun main() { var a = Person("A", 1999) var b = Person("B", 1998) var c = Person("C", 2000) println("안녕하세요, ${a.birthYear}년생 ${a.name}입니다.") a.introduce() b.introduce() c.introduce() } class Pe

[Kotlin] 클래스 생성자 [내부링크]

클래스 옆 괄호에 들어가는 속성들이 바로 생성자이다. class Person(var name:String, val birthYear:Int) 이것은 클래스의 '속성'들을 선언함과 동시에 생성자 역시 선언하는 방법이다. 생성자 : 새로운 인스턴스를 만들기 위해 호출하는 특수한 함수 생성자 호출하면 클래스의 인스턴스를 만들어 반환 받을 수 있다. 생성자의 기능 : - 인스턴스 속성을 초기화 - 인스턴스 생성시 구문을 수행 -> 이는 init이라는 함수를 통해 수행 가능 init 함수 : 패러미터나 반환형이 없는 특수한 함수. 생성자를 통해 인스턴스가 만들어질 때 호출되는 함수 fun main() { var a = Person("A", 1999) var b = Person("B", 1998) var c = Person("C", 2000) println("안녕하세요, ${a.birthYear}년생 ${a.name}입니다.") a.introduce() b.introduce() c.introd

[Kotlin] 클래스 상속 [내부링크]

실무자 관점에서 상속이 필요한 경우 - 이미 존재하는 클래스를 확장하여 새로운 속성이나 함수를 추가한 클래스를 만들 때 - 여러개의 클래스를 만들었는데 클래스들의 공통점을 뽑아 코드 관리를 편하게 할 때 속성과 함수를 물려주는 쪽을 수퍼 클래스, 물려 받는 쪽을 서브 클래스라고 한다. class Animal (var name : String, var age : Int, var type : String){ fun introduce(){ println("저는 ${type} ${name}이고, ${age}살 입니다.") } } 위는 동물의 이름, 나이, 종류를 구분하는 Animal 클래스이고 introduce 함수를 추가했다. 이를 Dog과 Cat 클래스로 확장해보자. 현재 Animal 클래스는 'open' 상태가 아니기 때문에 상속을 받을 수 없다. (코틀린은 상속 금지가 기본값이다. ) open은 클래스가 상속될 수 있도록 클래스 선언 시에 붙여줄 수 있는 키워드이다. 아래와 같이 적

[Kotlin] 오버라이딩, 추상화 [내부링크]

상속 시에는 기본적으로 수퍼 클래스에 있는 같은 이름과 형태를 가진 함수는 서브 클래스에 만들 수 없다. 하지만 수퍼 클래스에서 허용만 한다면 오버라이딩이라는 방법으로 서브 클래스에서 같은 이름과 형태로 된 함수의 내용을 다시 구현할 수 있다. fun main(){ var t = Tiger() t.eat() } open class Animal(){ fun eat(){ println("음식 먹는다") } } class Tiger : Animal() 음식 먹는다 여기서 만약 Tiger 클래스에서 "음식 먹는다" 대신에 "고기 먹는다" 출력하려고 한다고 생각해보자. 하지만 이미 eat 함수는 Animal에서 "음식 먹는다"로 구현되어 있기에 서브 클래스에서 함수를 재구현할 수 없다. 만약 Animal 클래스 내부의 eat 함수에 open이 다음과 같이 붙어있다면 Tiger에서 재구현이 허용된다. open class Animal(){ open fun eat(){ println("음식 먹는다

[Kotlin] 프로젝트 구조 [내부링크]

프로젝트 : 코틀린으로 어플리케이션을 만들 때 관련한 모든 내용을 담는 큰 틀 모듈 : 하나의 프로젝트는 여러 개의 모듈로 이루어질 수 있다. 이 모듈은 직접 만들 수도 있고, 필요한 기능을 이미 구현해둔 라이브러리 모듈을 가져와 붙일 수도 있다. 모듈 내부에는 코틀린 코드 파일 뿐만 아니라 모듈과 관련된 설정 및 리소스 파일 등도 포함될 수 있다. 프로젝트, 모듈, 폴더, 파일이 실제 파일 시스템에 기반한 물리적인 구조를 담당한다고 하면 논리적인 구조로는 패키지가 있다. 패키지 : 개발 시에 소스 코드의 '소속'을 지정하기 위한 논리적 단위 코드를 작성할 때는 코드 내에서 사용하는 이름이 용도에 따라 서로 충돌하지 않도록 유니크한 패키지 이름을 지어주는 것이 좋다. 일반적으로 패키지 이름을 지을 때는 개발한 회사의 도메인을 거꾸로 배열하고, 그 뒤에 프로젝트 명을 붙인다. 예를 들면 youandme.com의 hello 프로젝트 -> com.youandme.hello 그리고 그 아래

[Kotlin] 스코프, 접근제한자 [내부링크]

스코프 : 변수, 함수, 클래스의 공용 범위를 제어하는 단위 접근제한자 : 스코프 외부에서 스코프 내부로의 접근을 제어한다 스코프는 언어차원에서 변수나 함수, 클래스 같은 '멤버'들을 서로 공유하여 사용할 수 있는 범위를 지정해둔 단위이다. 스코프가 지정되는 범위는 패키지 내부, 클래스 내부, 함수 내부 등이 있다. 예를 들어 하나의 패키지 안에 변수, 함수, 클래스가 있다면 그것들은 모두 하나의 스코프 안에 있는 멤버들이지만 다시 그 안에 있는 함수나 클래스 내부의 변수나 함수들이 존재한다면 패키지 스코프 안에 하위 스코프로 동작하게 된다. 스코프에 대한 규칙 1. 스코프 외부에서는 스코프 내부의 멤버를 참조연산자로만 참조가 가능하다. --> 클래스의 멤버를 참조할 때 클래스 외부에서 a.eat()처럼 참조연산자 점(.)을 통해 접근했던 것이 그 예시 또한 패키지를 참조할 때도 import를 사용하거나 참조연산자를 사용해야 했다. ex) com.youandme.hello.A 2.

[Kotlin] 고차함수와 람다함수 [내부링크]

고차함수 : 함수를 마치 클래스에서 만들어 낸 '인스턴스'처럼 취급하는 방법 함수를 패러미터로 넘겨줄 수도 있고, 결과값으로도 반환 받을 수 있는 방법이다. 코틀린에서는 모든 함수를 고차함수로 사용 가능하다. fun main(){ } fun a (str:String){ println("$str 함수 a") } fun b(function_name: ???????){} 그럼 여기서 의문이 드는 것은 함수의 자료형은 무엇으로 적어야할지이다. 함수의 형식은 함수가 받을 패러미터의 자료형을 괄호 안에 나열하고, 화살표로 함수의 반환 자료형을 써주면 된다. 이렇게 하면 기술한 형태와 같은 형식의 함수는 모두 패러미터로 받을 수 있다. a 함수는 문자열을 패러미터로 받고 반환을 하지 않는다. 따라서 b 함수에서 함수의 자료형을 다음과 같이 작성하면 된다. fun b(function_name: (String)-> Unit){} (String) -> Unit도 일종의 자료형이다. 이제 main 함수

[Kotlin] 스코프함수 [내부링크]

람다함수의 특별한 케이스 1. 람다함수도 일반 함수처럼 여러 구문 수행 가능하다. val c: (String)->Unit = {str -> println("$str 람다함수") println("여러 구문을") println("사용가능하다") } 참고로 람다함수가 여러 구문이 되는 경우 마지막 구문의 결과 값이 반환된다. 2. 람다함수에 패러미터가 없는 경우 실행할 구문들만 나열하면 된다. val a : () -> Unit = {println("패러미터 없다")} 3. 패러미터가 하나 뿐이라면 it 사용 val c: (String)->Unit = {str -> println("$str 람다함수")} 위의 코드를 패러미터가 하나라면 아래처럼 해도 된다. val c: (String)->Unit = {println("$it 람다함수")} 스코프 함수 : 함수형 언어의 특징을 좀 더 편리하게 사용할 수 있도록 기본 제공하는 함수들 클래스에서 생성한 인스턴스를 스코프 함수에 전달하면 인스턴스의

[Kotlin] 오브젝트 [내부링크]

기존에 배웠던 class는 단지 인스턴스 객체를 만들기 위한 툴이기에 내부에 있는 속성이나 함수를 사용하려면 실제가 되는 인스턴스 객체를 만들어야 했다. 그러나 여러개의 인스턴스 객체가 필요하지 않으며 단 하나의 객체만으로 공통적인 속성과 함수를 사용해야 하는 코드에서는 굳이 클래스를 쓸 필요 없이 Object를 사용하면 된다. 이는 singleton pattern으로 클래스의 인스턴스를 단 하나만 만들어 사용하도록 하는 코딩 아키텍쳐 패턴이다. 오브젝트는 인스턴스를 생성하지 않고 그 자체로 객체이다. 고로 생성자는 사용하지 않는다. 또한 오브젝트의 이름에 직접 참조 연산자를 붙여 사용한다. ex) Counter.멤버 fun main(){ println(Counter.count) Counter.countUp() Counter.countUp() println(Counter.count) Counter.clear() println(Counter.count) } object Counter

[Kotlin] 익명 객체와 옵저버 패턴 [내부링크]

옵저버 : 코딩에서 이벤트가 일어나는 것을 감시하는 감시자 역할 안드로이드로 예를 들자면 키가 입력된다든지, 터치가 발생한다든지, 데이터가 수신된다든지 등 함수로 직접 요청하지는 않았지만 시스템 또는 루틴에 의해 발생하게 되는 동작들을 이벤트라고 부른다. 이 이벤트들을 즉각적으로 처리할 수 있도록 만드는 프로그래밍 패턴을 옵저버 패턴이라고 부른다. 옵저버 패턴을 구현할 때는 2개의 클래스가 필요하다. 하나는 이벤트를 수신하는 클래스(A) 또 하나는 이벤트의 발생 및 전달하는 클래스(B) 이 두 클래스는 어떻게 통신할까? B에서 이벤트가 발생할 때 A에 있는 이벤트를 처리하는 함수를 호출하여 알려주면 된다. 그런데 문제가 있다. 일반적으로 이벤트를 수신하는 클래스 측의 필요에 따라 이벤트를 발생시키는 클래스의 인스턴스를 생성하여 사용하기 때문에 A는 B를 직접 참조할 수 있지만, B는 A를 참조할 방법이 없다는 것. 그래서 우리는 이 사이에 인터페이스를 끼워넣는다. B에서는 자신의 이

[Kotlin] 클래스의 다형성 [내부링크]

'클래스의 상속'을 통해 클래스를 확장하는 법을 배웠다. 하지만 클래스를 다형성의 관점에서 살펴본 적은 없다. 예를 들어 음료를 마실 때 목이 말라서 아무거나 마셔도 될 때가 있지만 원하는 음료를 선택하 때도 있을 것이다. 이 때 콜라를 콜라 자체로도 볼 수 있지만 음료라는 특성으로도 볼 수 있도록 만드는 것이 다형성의 개념이다. Drink 클래스가 수퍼 클래스, Cola가 서브 클래스라고 한다면 Cola 인스턴스에 Drink의 객체공간과 Cola의 추가 공간이 생성된다. var a : Drink = Cola() 처럼 하면 음료의 기능만 사용할 수 있고 var b : Cola = Cola() 처럼 하면 음료와 콜라의 기능까지 모두 사용할 수 있다. 이 때 콜라 인스턴스를 음료 변수에 담는 행위를 상위 자료형인 수퍼 클래스로 변환한다고 하여 Up-Casting이라고 한다. Up-Casting된 인스턴스를 다시 하위 자료형으로 변환하면 Down-Casting이라고 한다. Up-Casti

허상 [내부링크]

모든 것이 허상이라면, 나는 내 가슴이 뛰는 곳으로 가겠다.

Box plot(박스 그래프) [내부링크]

박스 그래프는 최솟값, 1분위수, 중간값, 3분위수, 최댓값, 이상치 등 다양한 통계량을 한 번에 표현하는 그래프이다. 박스 플롯(box plot) 설명 오늘 아는 분이 박스 플롯의 의미가 무엇이고 어떻게 그리는지 궁금하다고 말씀하셔서 이야기 나온김에 정리를 해본다. 박스 플롯을 사용하는 이유는 많은 데이터를 눈으로 확인하기 어려울 때 그림을 이용해 데.. leebaro.tistory.com 다음 링크를 참고해 정리하자면 다음과 같다. 최솟값 Q1 - 1.5 * IQR 제1사분위(Q1) 25% 위치 제2사분위(Q2) 50%위치로 중앙값 의미 제3사분위(Q3) 75% 위치 최댓값 Q3 - 1.5 * IQR 최댓값과 최솟값을 넘어가는 위치에 있는 값이 이상치(Outlier) 이다. IQR(InterQuartile range) : 제 3분위 - 제 1분위

[Kotlin] 자료형과 변수 [내부링크]

변수 - var, val property : 클래스에 선언된 변수 local variable : scope 내에 선언된 변수 kotlin은 null값 허용하지 않는다. 또한 변수에 값을 할당하지 않은 채로 사용하게 되면 문법 에러 표시하고 컴파일 막아준다. 이를 통해 의도치 않은 동작이나 Null pointer exception 등을 원천적으로 차단해준다. 다만, 변수에 값 할당하지 않았다는 걸 정보로 사용하는 경우도 있을 수 있다. 이 때는 자료형 옆에 물음표 넣으면 null 값 할당 가능 ex) var a:Int? = null nullable 변수 : 값이 null인 상태로 연산할 시 null pointer exception 발생할 수 있으므로 꼭 필요할 때만 주의해서 사용하자. 변수의 초기화를 늦추는 lateinit이나 lazy 속성도 있으나 클래스에 대한 지식 필요하니 추후에 이해하자. 정수형 - Byte : 8bits - Short : 16bits - Int : 32bits

[Kotlin] 형변환과 배열 [내부링크]

형변환 : 변수에 지정된 자료형을 호환되는 다른 자료형으로 변경하는 기능. 단, 논리형은 변환 불가능 *형변환 함수 -toByte() -toShort() -toInt() -toLong() -toFloat() -toDouble() -toChar() var a: Int = 54321 var b : Long = a 코틀린에서는 위와 같은 방법이 불가능하다. var a: Int = 54321 var b : Long = a.toLong() 이렇게 해야한다. 이것을 명시적 형변환이라고 한다. 코틀린은 형변환시 발생 가능한 오류 막기 위해 암시적 형변환은 지원 안 한다. 형 변환시 호환 가능 여부 체크하는 방법은 클래스 배울 때 다시 다뤄보자. var intArr = arrayOf(1,2,3,4,5) 배열은 내부적으로 Array 클래스로 제공된다. 배열을 선언할 때는 위처럼 arrayOf 함수를 통해 배열에 저장할 값들 나열하면 된다. var nullArr = arrayOfNulls<Int>(5

[Kotlin] 타입 추론과 함수 [내부링크]

타입추론 : 변수, 함수 선언할 떄, 또 연산 이루어질 때에 자료형을 코드에 명시하지 않아도 코틀린이 자동으로 자료형을 추론해주는 기능 val stringValue = "하이 헬로" 여기서도 val stringValue: String = "하이 헬로" 처럼 String이라는 자료형 생략했다. var intArr = arrayOf(1,2,3,4,5) 에서도 var intArr : Array<Int> = arrayOf(1,2,3,4,5) 마찬가지로 생략했다. 변수가 선언될 때 할당된 값의 형태로 해당 변수가 어떤 자료형 가지는지 추론 가능하기 때문에 이처럼 타입 추론이 가능하다. 기본 자료형들도 선언 시 값만 할당해주면 대부분 자료형 명시할 필요 없다. 따라서 특정 자료형으로 반드시 지정해야하는 것이 아닌 상황에서는 대부분 타입추론 기능 통해 코드량 줄일 수 있다. 함수 좀 더 간단하게 표현 -> 단일 표현식 함수 fun add(a:Int, b:Int,c:Int):Int { retur

[Kotlin] 조건문, 비교연산자 [내부링크]

if는 다른 언어와 다를 것이 없다. 비교연산자 - 자료형이 맞는지 체크하는 is 연산자. - 자료형이 틀린지 체크하는 !is 연산자. a is Int 여기서 좌측 변수가 우측 자료형에 호환되는지 체크하고 형변환까지 시켜준다. 다중 조건문 when은 다른 언어의 switch 문을 좀 더 편리하게 바꾼 기능이다. fun doWhen (a:Any){ when(a) { 1 -> println("정수 1") "hello" -> println("hello") is Long -> println("Long 타입") !is String -> println("String 타입 아님") else -> println("어떤 조건도 안 맞음") } } else는 위의 다른 조건 아무 것도 부합하지 않을 때 동작한다. 또 when에서 등호나 부등호 사용은 불가능하다. 참고로 여러개의 조건 맞는 경우에도 먼저 부합하는 조건이 실행된다. 이 예제는 When을 조건문으로서 이용한 경우이다. when 조건 맞을

[Kotlin] 반복문, 증감연산자 [내부링크]

조건 참인 경우 반복 유지 -> 조건형 반복문(while, do...while) 반복 범위 정해 반복 수행 -> 범위형 반복문 증가연산자, 감소연산자 --a, a-- ++a, a++ for의 사용법은 고전적인 언어들과는 사뭇 다르다. 최신 언어들이 제공하고 있는 형태다. for(i in 0..9) 여기서 인덱스로 사용할 i에는 var 등 자료형을 붙이지 않아도 된다. 증가값이 1이 아닌 다른 값으로 하려면 step을 옵션으로 붙여주면 된다. for(i in 0..9 step 3) 감소 시키는 건 downTo를 사용하면 되는데, for(i in 9 downTo 0) 처럼 하면 된다. 마찬가지로 step 붙이기 가능하다. 또한 char 자료형에도 사용할 수 있는데, for(i in 'a'..'e') 라고 하면 된다. print는 println과 달리 행변환 없이 출력할 때 사용하는 함수이다.

[Kotlin] 흐름제어, 논리연산자 [내부링크]

코드의 흐름을 바꾸는 흐름제어와 조건 합쳐 판단하는 논리연산자 흐름 제어 종류 - return : 함수를 종료하고 값을 반환함 - break, continue : 반복문에서 흔히 쓰는 그것 - loop 다른 언어들과 다른 한 가지 기능이 코틀린에는 더 추가되었다. 바로 다중 반복문에서 break나 continue가 적용되는 반복문을 Label을 통해 지정할 수 있는 기능 fun main() { loop@for (i in 1..10){ for (j in 1..10){ if(i==1&&j==2) break@loop println("i : $i, j: $j") } } } loop@ @loop를 통해서 두개의 반복문 모두 한 번에 break 할 수 있다. continue도 마찬가지이다. 또한, 따옴표 안에 $를 변수 앞에 붙여 변수 내용 출력할 수 있다. 논리연산자. - && - || - ! boolean 값보다 실제로는 조건식과 조건식을 연산하는 경우가 더 많다.

백준 2941 [파이썬] [내부링크]

문제 Note 파이썬의 라이브러리들이 익숙하지 않은 내가 이 문제를 보자마자 노트에 적은 것은 '크로아티안 알파벳 리스트를 만들어서 입력된 문자열과 비교하면 되겠다'라는 문장이다. 하지만 파이썬 라이브러리는 역시나 강력했다. Code croatian = ['c=', 'c-', 'dz=', 'd-', 'lj', 'nj', 's=', 'z='] word = input() for i in croatian : word = word.replace(i, '*') print(len(word)) Study point replace 함수의 정의 문자열을 *과 같은 특정 문자로 치환하여 길이를 계산하는 관점 replace 함수 - 문자열을 변경하는 함수 변수.replace(old, new, [count]) - old : 현재 문자열에서 변경하고 싶은 문자 - new : 새로 바꿀 문자 - count : 변경할 횟수. 입력하지 않으면 old 문자열 전체를 변경. 예시) >>> 'oxoxoxoxox'.r

Github 토큰 생성 [내부링크]

Github가 21년 8월 13일부로 더이상 패스워드 방식의 인증을 지원하지 않게 됨에 따라 개개인의 Github token을 생성해야 한다. 토큰 생성 방법은 다음과 같다. 1. Github 메인 화면 우측 상단의 프로필 - Settings 2. 좌측 하단의 Developer settings 3. Personal access tokens - generate new token Personal access tokens 누른 화면 generate new tokens 누른 화면 이제 token의 Note를 기입하고 목적(Scope), 만료기한(Expiration)을 선택 후 Generate token을 누르면 끝이다! token은 생성 후 다시 들어가 확인할 수 없으니 바로 복사해두자.

소스트리 푸시 오류(Sourcetree push error) [내부링크]

완료된 커밋, 준비된 손가락. 눌러버린 푸시 버튼 위로 다음과 같은 창이 떠오른다. 오류가 나면서 완료됨 이제 자질구레한 오류가 있을 때마다 한숨이 나오는 것보다 구글링을 하는 것이 더 빠르다. 다행스럽게도 구글에 'source tree 오류가 나면서 완료됨'이라고 검색하면 첫 번째로 관련 내용을 소개하는 블로그가 나온 덕에 바로 수정할 수 있었다. 굳이 구분하자면 2가지 과정이 필요하다. Github 토큰 생성 소스트리 원격저장소 경로 설정 1. Github 토큰 생성 토큰 생성 방법은 다음 링크에서 확인할 수 있다. Github 토큰 생성 Github가 21년 8월 13일부로 더이상 패스워드 방식의 인증을 지원하지 않게 됨에 따라 개개인의 Github t... blog.naver.com 2. 소스트리 원격저장소 경로 설정 소스트리 상단에 [저장소 - 저장소 설정] 으로 들어가면 다음과 같은 화면이 되는 것을 확인할 수 있다. [저장소 - 저장소 설정] 해당 원격 저장소를 선택 후

백준 1316 [파이썬] [내부링크]

문제 Note 연속되는 문자를 임의의 변수에 저장 연속되는 문자 끝나고 뒤의 문자열에서 앞서 저장한 문자가 있는지 확인 Code num = int(input()) group_word = 0 for _ in range(num): word = input() error = 0 for i in range(len(word)-1): #입력 받은 단어의 길이-1까지 if word[i] != word[i+1]: #연속되는 두 문자가 다르면 new_word = word[i+1:] #이후의 문자열을 new_word에 저장 if new_word.count(word[i]) > 0: #new_word에 방금까지 연속한 문자가 있다면 error += 1 #에러 증가 if error == 0: group_word += 1 #에러가 0이면 그룹단어 print(group_word) Study point 새로운 변수에 뒷 문자열을 담는 관점 문자열 슬라이싱 문제를 더 다뤄서 익숙해질 것

백준 2292 [파이썬] [내부링크]

문제 Note 1, 7, 19, 37, 61이 각 칸에서 가장 큰 숫자이다. 1 < x < 7 과 같이 범위로 나누면 될 듯 Code n = int(input()) num = 1 cnt = 1 while n > num : num += 6 * cnt cnt += 1 print(cnt) Study point 코드를 만드는 것에 있어 너무 인간의 사고를 사용하는 것 같다. 예를 들면 if문을 남발하는 것이 있겠다. 조금 더 컴퓨터의 사고를 할 필요가 있을 것 같다.

백준 1463 [파이썬] [내부링크]

문제 Note 3, 2로 나누기, 1 빼기로 하는데 2로 나누는 건 1 또는 2를 빼서 3의 배수를 만들어 나눠주는 게 더 빠르니 안 해줘도 되지 않을까? Code n = int(input()) d = [0] * (n + 1) for i in range(2, n + 1): d[i] = d[i - 1] + 1 if i % 3 == 0: d[i] = min(d[i], d[i // 3] + 1) if i % 2 == 0: d[i] = min(d[i], d[i // 2] + 1) print(d[n]) 다이나믹 프로그래밍(동적 계획법)을 이용해야 한다. 피보나치 문제도 이와 같은 방식으로 풀 수 있다. n = int(input()) d = [0] * (n + 1) 우선 정수 n을 입력 받고, 동적 계획법을 사용할 테이블을 만들어준다. 여기서 각 정수와 리스트의 인덱스를 동일하게 만들어주기 위해서 n+1 크기로 만든다. for i in range(2, n + 1): d[i] = d[i - 1]

[Pandas] 입문 [내부링크]

데이터 집합 불러오기 import pandas as pd df = pd.read_csv('../data/gapminder.tsv', sep = '\t') 데이터 집합을 불러오려면 read_csv 메서드를 사용해야 한다. read_csv는 기본적으로 쉼표(,)로 열이 구분되어 있는 데이터를 불러온다. 하지만 여기서 불러오는 gapminder는 탭으로 구분되어 있는 tsv 파일이다. 따라서 read_csv를 호출할 때 sep 속성값으로 \t를 지정해야 한다. 여기서 csv와 tsv은 다음의 약자이다. Comma-Separated-Values Tab-Separated-values print(df.head()) #1 print(type(df)) #2 print(df.shape) #3 print(df.columns) #4 print(df.dtypes) #5 print(df.info) #6 #1 country continent year lifeExp pop gdpPercap 0 Afghanis

[Pandas] 데이터 프레임과 시리즈 [내부링크]

판다스의 데이터 프레임과 시리즈는 많은 양의 데이터를 저장할 수 있을 뿐만 아니라 행과 열 단위로 원하는 데이터를 조작할 수 있습니다. 시리즈 만들기 import pandas as pd s = pd.Series(['banana', 42]) print(s) #1 s = pd.Series(['Wes McKinney','Creator of Pandas']) print(s) #2 s = pd.Series(['Wes McKinney', 'Creator of Pandas'], index = ['Person', 'Who']) print(s) #3 #1 0 banana 1 42 dtype: object #2 0 Wes McKinney 1 Creator of Pandas dtype: object #3 Person Wes McKinney Who Creator of Pandas dtype: object 데이터 프레임 만들기 scientists = pd.DataFrame({ 'Name' : ['Rosal

기묘한 모험 [내부링크]

세상엔 무엇이 내 발걸음을 이끈지도 모른 채 떠나는 여행이 많다.