質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
多次元配列

1次元配列内にさらに配列を格納している配列を、多次元配列と呼びます。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Q&A

解決済

2回答

3269閲覧

渦を巻く二次元配列を作成したい

toshiyan

総合スコア74

多次元配列

1次元配列内にさらに配列を格納している配列を、多次元配列と呼びます。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

0グッド

0クリップ

投稿2020/05/23 00:30

bash

1$ ./a.out 26 3[[ 1, 2, 3, 4, 5, 6 ] 4 [ 20, 21, 22, 23, 24, 7 ] 5 [ 19, 32, 33, 34, 25, 8 ] 6 [ 18, 31, 36, 35, 26, 9 ] 7 [ 17, 30, 29, 28, 27, 10 ] 8 [ 16, 15, 14, 13, 12, 11 ]]

上記のような二次元配列を作りたいのですが、皆様がどのように実装するかが知りたいです。ちなみに私は以下のように実装しました。もっと楽に書けるのではと思い質問いたしました。よければ回答お願いします。言語は何でも構いません。

あと、以下の実装で気になる点(do whileが微妙など)や、もっとこうすればいいのではといったご指摘もあれば嬉しいです。

cpp

1#include <bits/stdc++.h> 2using namespace std; 3 4int dx[] = {1, 0, -1, 0}; 5int dy[] = {0, 1, 0, -1}; 6 7int ans[1000][1000]; 8 9int main() { 10 int n; 11 cin >> n; 12 int now = 1; 13 int nx = 0, ny = 0; // 現在位置 14 int dir = 0; // 現在進もうとする方向 15 while (now <= n * n) { 16 ans[nx][ny] = now; 17 now += 1; 18 do { 19 int wx = nx + dx[dir]; 20 int wy = ny + dy[dir]; 21 // 次に進もうとする方向が範囲外なら方向を変える 22 if (wx < 0 || wx >= n || wy < 0 || wy >= n) { 23 dir = (dir + 1) % 4; 24 break; 25 } 26 // 次に進もうとする方向が既に数を代入済みなら方向を変える 27 if (ans[wx][wy] != 0) { 28 dir = (dir + 1) % 4; 29 } 30 } while (0); 31 // 次に進む 32 nx += dx[dir]; 33 ny += dy[dir]; 34 } 35 // この時点でxが縦方向、yが横方向になっているので転置させる 36 for (int i = 0; i < n; i++) { 37 for (int j = 0; j < i; j++) { 38 swap(ans[i][j], ans[j][i]); 39 } 40 } 41 // 作成が完了した二次元配列の内容を出力する 42 for (int i = 0; i < n; i++) { 43 for (int j = 0; j < n; j++) { 44 cout << ans[i][j] << (j == n - 1 ? '\n' : ' '); 45 } 46 } 47 return 0; 48}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

やってることは一緒ですが.

C++

1const int N = 6; 2int ans[N][N] = { 0 }; 3 4void Work( int &x, int &y, int dx, int dy, int k, int val ) 5{ 6 for( int i=0; i<k; ++i ) 7 { 8 x += dx; 9 y += dy; 10 ans[y][x] = val + i; 11 } 12} 13 14int main() 15{ 16 int x = -1; 17 int y = 0; 18 int dx = 1; 19 int dy = 0; 20 21 Work( x,y, dx, dy, N, 1 ); 22 23 int k = N - 1; 24 int val = N + 1; 25 while( k>0 ) 26 { 27 for( int i=0; i<2; ++i ) 28 { 29 std::swap( dx, dy ); 30 dx = -dx; 31 Work( x,y, dx, dy, k, val ); 32 val += k; 33 } 34 --k; 35 } 36 37 //表示 38 for( int i = 0; i < N; i++ ) 39 { 40 for( int j = 0; j < N; j++ )std::cout << ans[i][j] << ' '; 41 std::cout << std::endl; 42 } 43 return 0; 44}

投稿2020/05/23 06:41

fana

総合スコア11652

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

元のプログラムをベースに短かくしてみました。

c++

1 2int main() { 3 int n; 4 cin >> n; 5 int now = 1; 6 int cx = 0, cy = 0; // 現在位置 7 int dir = 0; // 現在進もうとする方向 8 while (now <= n * n) { 9 ans[cy][cx] = now++; 10 // 次に進もうとする方向が範囲外もしくは渦巻の数字を入力済なら方向を変える 11 int nx = cx + dx[dir], ny = cy + dy[dir]; 12 if (nx < 0 || nx >= n || ny < 0 || ny >= n || ans[ny][nx] != 0) { 13 dir = (dir + 1) % 4; 14 } 15 // 次に進む 16 cx += dx[dir]; 17 cy += dy[dir]; 18 } 19 // 作成が完了した二次元配列の内容を出力する 20 for (int i = 0; i < n; i++) { 21 for (int j = 0; j < n; j++) { 22 cout << ans[i][j] << (j == n - 1 ? '\n' : ' '); 23 } 24 } 25 return 0; 26}

pythonだと、以下のような書き方を見たことがあります。
ざっくりとした動作は以下の通りです。
0. 渦巻を格納する配列mを用意する
0. どのx, y座標を対象にするかの配列posを用意する
0. posを大根のかつらむきのようにクルクル回しながら順番に座標を取り出す
0. mに値を代入する
0. 3に戻って繰り返し

python

1n = int(input()) 2v = iter(range(1, n**2+1)) # 1からn^2までを順に生成する 3pos = m = [[[x, y] for y in range(n)] for x in range(n)] 4while pos: 5 for x, y in pos[0]: 6 m[x][y] = next(v) 7 pos = list(zip(*pos[1:]))[::-1] # 一番上の行を取り除いて、左回転 8print(*m, sep='\n')

投稿2020/05/23 05:20

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問