과학

자바로 프로그래밍에 입문할래요: 1.4. 배열 (3)

1.4. 배열 (2)

1.4 배열 (1)

1.3. 조건문과 반복문 (2)

1.3. 조건문과 반복문 (1)

1.2. 내장 자료형 (2)

1.2. 내장 자료형 (1)

0.0. 여는 글, 1.1. 첫 프로그램 만들기

 

========================

 

 2차원 배열(Two-dimensional arrays)

  많은 응용프로그램에서 정보를 저장하기 위해 사용하는 편리한 방법 중 하나는 사각형의 표에서 행과 열을 이용해 참조하는 것입니다.

  i행 j열의 2차원 배열 요소에 접근하기 위해서 우리는 a[i][j] 라는 표기법을 사용합니다. 2차원의 배열을 선언하기 위해서는, 대괄호쌍 하나를 더 사용해야 합니다. 생성하기 위해서는, 각 괄호 안에 행의 수와 열의 수를 명시합니다.

 

 
double[][] a = new double[M][N];

 

  우리는 이를 M*N(M-by-N) 배열이라고 합니다. 1차원 배열과 같이 모든 숫자는 0으로, boolean 값은 false로 초기화됩니다.

 

 

초기화

  2차원 배열을 초기화하기 위해서는, 이중 반복문을 이용합니다. 다음은 2차원 배열을 초기화하는 코드 조각입니다.

 

 
doubled [] a;
a = new double[M][N];
for (int i = 0; i < M; i++)
{ // Initialize the ith row.
	for (int j = 0; j < N; j++)
		a[i][j] = 0.0;
}

 

  곧 보겠지만, 이 코드는 2차원 배열의 요소를 접근하고 수정하기 위해 흔히 사용되는 방법입니다. 

 

 

출력

  우리는 2차원 배열을 출력하기 위해 다음 코드 조각을 활용할 수 있습니다.

 

 
doubled [] a;
a = new double[M][N];
for (int i = 0; i < M; i++)
{ // Initialize the ith row.
	for (int j = 0; j < N; j++)
		System.out.print(a[i][j] + " ");
	System.out.println();
}

 

 

메모리 표현

  자바는 2차원 배열을, 배열의 배열로 표현합니다. M*N 배열은, 크기가 N인 배열을 원소로 가지는, 크기가 M인 배열입니다. 자바의 2차원 배열 a[][]에서, 우리는 a[i]를 통해 i번째 행을 참조할 수 있습니다.(마치 1차원 배열처럼 말이죠) 하지만 2차원이니, 열을 참조할 방법이 결국 필요하겠죠.

 

 

 

컴파일 시기에 값을 설정하기

  2차원 배열을 초기화 하기 위해서는, 각 중괄호 안에서 한 행씩을 초기화 하고, 그것들을 쉼표로 구분합니다. 다음 코드 조각을 참고하세요.

 

 
int[][] a =
	{
		{ 99, 85, 98, 0 },
		{ 98, 57, 78, 0 },
		{ 92, 77, 76, 0 },
		{ 94, 32, 11. 0 },
		{ 99, 34, 22, 0 },
		{ 90, 46, 54, 0 },
		{ 76, 59, 88, 0 },
		{ 92, 66, 89, 0 },
		{ 97, 71, 24, 0 },
		{ 89, 29, 38, 0 },
		{  0,  0,  0, 0 }
	};

 

 

스프레드시트(Spreadsheets)

  배열의 흔한 사용법 중 하나는 표의 숫자들을 활용하는 스프레드시트입니다. 예를 들어, 교사가 M명의 학생과 N개의 과목 점수, 각 마지막 줄은 평균 점수를 담는 (M+1)*(N+1) 배열을 이용 할 수 있습니다. 다음 그림을 참고하세요.

 

 

 

 

행렬 연산

  과학과 공학 분야에서는 행렬 연산을 위해 흔히 2차원 배열을 사용합니다. 두 N*N 행렬을 다음과 같이 더해볼 수 있겠죠.

 

 

 

 
double[][] c = new double[N][N];
for (int i = 0; i < N; i++)
	for (int j = 0; j < N; j++)
		c[i][j] = a[i][j] + b[i][j];

 

  비슷하게, 행렬곱도 해볼 수 있을 것입니다. 삼중 반복문이 조금은 익숙지 않으실 수도 있겠지만, 천천히 눈으로 따라가보세요.

 


 
double[][] c = new double[N][N];
for (int i = 0; i < N; i++)
{
	for (int j = 0; j < N; j++)
	{
		// Compute dot product of row i and column j,
		for (int k = 0; k < N; k++)
			c[i][j] += a[i][k] * b[k][j];
	}
}

 

 

그 외의 행렬 곱들

  이는 간단히 그림만 첨부합니다. 흥미가 생긴다면 직접 코딩해서 따라해보세요.

 

 

 

 

 

 

가변 배열(Ragged arrays)

  모두 같은 크기의 열을 굳이 사용할 필요가 없는 경우도 있습니다. 열의 개수가 일정하지 않은 배열을 가변 배열이라고 합니다. 가변 배열이 가능하다면, 배열을 처리하는 코드들에 좀 더 신경을 써야 합니다. 다음은 가변 배열의 요소들을 출력하는 코드입니다.

 

 
for (int i = 0; i < a.length; i++)
{
	for (int j = 0; j < a[i].length; j++)
		System.out.print(a[i][j] + " ");
	System.out.println();
}

 

  이전에 봤던 코드와 뭐가 다를까요? 이 코드는 여러분이 자바 배열을 얼마나 이해했는지 시험합니다. 우리는 일반적으로 정사각 혹은 직사각형의 2차원 배열을 사용했습니다. 코드의 두 번째 for문에서 a[i].length를 사용한다는 것은, 곧 이 배열이 가변이라는 사실을 암시하는 것입니다.

 

 

다차원 배열(Multidimensional arrays)

  같은 표기법으로 몇 차원이든 계속해서 확장할 수 있습니다. 예를 들어 3차원 배열은 다음과 같이 사용할 수 있습니다.

 

 
double[][][] a = new double[N][N][N];

 

  또한 마찬가지로 a[i][j][k]와 같은 방식으로 참조하면 됩니다.

 

  2차원 배열은 행렬에 대한 자연스러운 표현을 가능하게 해주며, 이는 과학, 수학, 공학 등 다양한 분야에서 활용할 수 있게 해줍니다. 또한 아주 많은 양의 데이터를 쉽게 처리할 수 있게 해주며, 스프레드시트같이 활용할 수도 있습니다. 데카르트 좌표계를 통해, 2차, 3차원의 배열은 물리적 세계를 기반으로 한 모델들도 제공합니다. 

 

 

예제: self-avoiding random walks(자기 회피 무작위 보행)

  촘촘한 격자 형태로 설계된 거대한 도시의 길거리를 여러분의 애완견과 함께 걷는다고 생각해봅시다. 수직으로 N개의 거리, 수평으로 N개의 거리, 총 N*N개의 교차로가 있는 도시를 걷는 것이죠. 

 

 

 

 

  여러분은 도시의 정중앙에서 애완견과 함께 이 도시를 탈출하고 싶습니다. 다만, 교차로에서 어떤 방향으로 나아갈지는 무작위로 선택합니다. 애완견은 냄새에 예민하여 이미 방문한 적 있는 교차로는 방문하지 않으려고 합니다. 그렇다면 어느 순간에는 네 방향 전부 이미 방문한 교차로여서, 어느 곳도 갈 수 없는 상황에 맞닥뜨릴 수도 있습니다. 이를 dead-end라고 하죠. 아니면 다행히도 dead-end를 맞닥뜨리지 않고 도시 바깥으로 탈출할 수 있을지도 모릅니다.

 

  우리가 N*N 크기의 도시를 탈출할 가능성은 얼마나 있을까요? 이는 self-avoiding random walk라는 유명한 모델이며, 고분자학과 통계학 등 다양한 분야에서 대표적으로 응용되는 문제 중 하나입니다. 

 

 

프로그램 1.4.4: Self-avoiding random walks

 
public class SelfAvoidingWalk
{
	public static void main(String[] args)
	{ 	// Do T random self-avoiding walks
		// in an N-byN lattice
		int N = Integer.parseInt(args[0]);
		int T = Integer.parseInt(args[1]);;
		int deadEnds = 0;
		for (int t = 0; t < T; t++)
		{
			boolean[][] a = new boolean[N][N];
			int x = N / 2, y = N / 2;
			while (x > 0 && x < N - 1 && y > 0 && y < N - 1)
			{ // Check for dead end and make a random move.
				a[x][y] = true;
				if (a[x - 1][y] && a[x + 1][y] && a[x][y - 1] && a[x][y + 1])
				{
					deadEnds++;
					break;
				}
				double r = Math.random();
				if (r < 0.25)
				{
					if (!a[x + 1][y])
						x++;
				} else if (r < 0.50)
				{
					if (!a[x - 1][y])
						x--;
				} else if (r < 0.75)
				{
					if (!a[x][y + 1])
						y++;
				} else if (r < 1.00)
				{
					if (!a[x][y - 1])
						y--;
				}
			}
		}
		System.out.println(100 * deadEnds / T + "% dead ends");
	}
}
% java SelfAvoidingWalk 5 100
0% dead ends
% java SelfAvoidingWalk 40 100
80% dead ends
% java SelfAvoidingWalk 160 100
100% dead ends

 

  <프로그램 1.4.4>는 N과 T를 명령행 인자로 받아, N*N 도시 크기에서 T번 탈출을 시도합니다. 이후에 얼마나 dead-end에 도달하는지 비율을 출력합니다.

 

  이 프로그램을 이해하는 것은 어려운 도전이 될지도 모릅니다. 2차원 배열 a[][]는 해당 교차로의 방문 여부를 저장하는 배열입니다. true이면 방문한 것이고, false이면 방문하지 않은 것입니다. 또한 x와 y는 현재 위치한 교차로의 좌표입니다. 무작위로 생성된 r의 값에 따라, 각각 if문을 통해서 해당 방향의 교차로에 방문하지 않았다면 좌표를 해당 방향으로 수정해 방문합니다. dead-end에 도달하거나, 도시의 범위를 벗어날 때까지 이를 반복합니다.

 

 

 

 

  배열은 자바를 포함한 모든 프로그래밍 언어에서 찾을 수 있는 기초 요소입니다. 여지껏 배운 것들을 활용하면, 어떤 문제든지 프로그램을 통해 해결해낼 수 있을 것입니다. 이는 허투루 하는 소리가 아닙니다. 대부분의 알고리즘 테스팅은, 기본 자료형과 조건문, 반복문, 배열만으로도 충분히 해결할 수 있습니다. 여러분이 어떤 현실의 문제이든, 적절한 추상화를 통해 프로그램으로써 해결해낼 수 있는 역량을 갖추게 된 것입니다.

 

끝.

1개의 댓글

2021.05.03

잘보고 있어요

 

0
무분별한 사용은 차단될 수 있습니다.
번호 제목 글쓴이 추천 수 날짜
11292 [호러 괴담] [살인자 이야기] SNS를 통해 만난 남성. 그녀는 그를 친구라 ... 그그그그 1 8 시간 전
11291 [역사] 명동거리 인물전 8 멍멍이 4 18 시간 전
11290 [기타 지식] 옥수수에 관한 짧지식 45 mantra 16 1 일 전
11289 [호러 괴담] [살인자 이야기] 당시 15살이던 그녀의 몸무게는 22kg이었다. 9 그그그그 3 2 일 전
11288 [기타 지식] [음감1:부록] 나는 음치일까? 진단할 수 있는 4가지 사이트 7 Rockth 6 2 일 전
11287 [역사] 유대전쟁 - 신약과 관련된 마지막 역사 2 실용화성악 3 2 일 전
11286 [역사] 계시와 약속의 책 - 묵시문학에 관하여 11 실용화성악 2 2 일 전
11285 [역사] 이스라엘의 기원 - 출애굽과 가나안 정복에 관하여 2 실용화성악 3 2 일 전
11284 [역사] 이스라엘이 기원하기 직전 고대 근동 세계에 관하여 2 실용화성악 3 2 일 전
11283 [역사] 초기 이스라엘의 여호와 신앙에 관하여 14 실용화성악 2 2 일 전
11282 [기묘한 이야기] 나도써보는 군생활중 오싹오싹 경험 1 흑천마왕 2 2 일 전
11281 [유머] 나도 써보는 꿀 빨았던 군대 썰 7 부부붐단단 1 2 일 전
11280 [유머] 나도 써보는 07군번 아재의 군대에서 본 폐급이야기 3 오징어따콩 3 3 일 전
11279 [유머] (두서없음 주의) 내 맞후임의 9개월만의 후임이 황국신민이었... 5 꼬만도 3 3 일 전
11278 [유머] 07군번 독립수송부대 1호차 운전병 썰-2 5 애매한남자 4 3 일 전
11277 [역사] 14군번 5 82년산세로쉬 0 3 일 전
11276 [유머] 07군번 독립수송부대 1호차 운전병 썰 7 애매한남자 5 3 일 전
11275 [역사] 13군번이 겪은 군대 부조리 이야기 36 악마지망생 1 3 일 전
11274 [역사] dp보고 내가 당했던 군 부조리 9 댓츠노노 1 4 일 전
11273 [호러 괴담] [살인자 이야기] 한국인이 범인? 세타가야 일가족 살인사건 10 그그그그 4 4 일 전