正の整数nが与えられたとき、次のようなn * n
の二次元配列を生成する関数を作成してください。
- 一番左上の値は 1 です。
- 左下方向に行くに従って値が1ずつ増えていきます。
- これ以上左下方向に行けなくなったら、右上の次の位置に戻ります。
例えば、n = 4が与えられたとき、
1 2 4 7 3 5 8 11 6 9 12 14 10 13 15 16
を生成します。
プログラム言語は何でも構いません。命令型でも関数型でも大丈夫です。
解決後追記:
より良い回答を頂いた後に何なんですが、念のため昨日質問をする前に私が書いたコードを載せておきます。
Java
1 public static int[][] makeArray(int n) { 2 int[][] array = new int[n][n]; 3 4 int num = 1; 5 int istart = 0, jstart = 0; 6 int i = 0, j = 0; 7 8 while (true) { 9 array[i][j] = num; 10 num++; 11 12 // リセットの場合 13 if (i == jstart && j == istart) { 14 // 終了の場合 15 if (i == n - 1 && j == n - 1) 16 break; 17 18 if (istart != n - 1) { 19 istart++; 20 } else { 21 jstart++; 22 } 23 i = istart; 24 j = jstart; 25 continue; 26 } 27 // 続ける場合 28 i--; 29 j++; 30 } 31 return array; 32 }
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答7件
0
Javascript
1function hoge ( n ) { 2 var ary = []; 3 var i; 4 5 for ( i = 0; i < n; i ++ ) { 6 ary[ i ] = []; 7 } 8 9 fuga( ary, 0, 0, 1, n ); 10 moga( ary, n - 1, n - 1, n * n, n ); 11 12 function fuga( ary, i, j, x, n ) { 13 if ( j == n ) return; 14 15 ary[ i ][ j ] = x; 16 17 if ( j == 0 ) { 18 fuga( ary, j, i + 1, x + 1, n ); 19 } else { 20 fuga( ary, i + 1, j - 1, x + 1, n ); 21 } 22 } 23 24 function moga( ary, i, j, x, n ) { 25 if ( i == n - 1 && j == 0 ) return; 26 27 ary[ i ][ j ] = x; 28 29 if ( j == n - 1 ) { 30 moga( ary, j, i - 1, x - 1, n ) 31 } else { 32 moga( ary, i - 1, j + 1, x - 1, n ); 33 } 34 } 35 36 return ary; 37} 38 39console.log( hoge( 4 ) );
あまりきれいなプログラムじゃありませんが
Javascript
1function hoge ( n ) { 2 var ary = []; 3 var i; 4 5 for ( i = 0; i < n; i ++ ) { 6 ary[ i ] = []; 7 } 8 9 moga( ary, 0, 0, 1, 1, n ); 10 11 function fuga( ary, i, j, x, y, n ) { 12 if ( y < 0 || j < 0 ) return; 13 14 if ( i < n && j < n ) { 15 ary[ i ][ j ] = x; 16 } 17 if ( i == 0 ) { 18 fuga( ary, i + 1, j - 1, x + 1, 0, n ); 19 x += y; 20 if ( j < n - 2 ) { 21 y++; 22 } else if ( j > n - 2 ) { 23 y--; 24 } 25 fuga( ary, i, j + 1, x, y, n ); 26 } else { 27 fuga( ary, i + 1, j - 1, x + 1, y, n ); 28 } 29 } 30 31 return ary; 32} 33 34console.log( hoge( 4 ) );
Javascript
1function hoge( n ) { 2 var ary = []; 3 var i, j, k, x = 1; 4 5 for ( i = 0; i < n; i ++ ) ary[ i ] = []; 6 7 for ( k = 0; k <= ( n - 1 ) * 2; k ++ ) 8 for ( i = 0, j = k; j >= 0; i ++, j -- ) 9 if ( i < n && j < n ) 10 ary[ i ][ j ] = x ++; 11 12 return ary; 13} 14console.log( hoge( 4 ) );
最短で4行、これ以上無理
投稿2015/11/22 18:59
編集2015/11/23 04:39総合スコア34
0
こんなところでしょうか。
C++
1#include <cstdio> 2#include <iostream> 3#include <algorithm> 4#include <vector> 5 6std::vector<std::vector<int>> generate(int n) 7{ 8 std::vector<std::vector<int>> data(n); 9 std::fill(data.begin(), data.end(), std::vector<int>(n)); 10 11 // ◤の部分 12 int a = 1; 13 for(int i = 0; i < n; i++) 14 { 15 for(int j = 0; j <= i; j++) 16 { 17 data[j][i - j] = a++; 18 } 19 } 20 // ◢の部分 21 a = n * n; 22 for(int i = 0; i < n - 1; i++) 23 { 24 for(int j = 0; j <= i; j++) 25 { 26 data[(n - 1) - j][(n - 1) - (i - j)] = a--; 27 } 28 } 29 return data; 30} 31 32int main() 33{ 34 for(;;) 35 { 36 int n; 37 std::cout << "n (0=exit) ? "; 38 std::cin >> n; 39 if(n == 0) 40 break; 41 42 auto data = generate(n); 43 for(int i = 0; i < n; i++) 44 { 45 for(int j = 0; j < n; j++) 46 { 47 printf(" %4d", data[i][j]); 48 } 49 std::cout << std::endl; 50 } 51 std::cout << std::endl; 52 } 53 return 0; 54}
平行四辺形にすることに気づいたらコードが単純化できました。
投稿2015/11/22 21:10
編集2015/11/23 00:48総合スコア5944
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

0
yuux01 さんの解を ruby でかいてみました。
斜め線でスキャンをしていき、正方形領域にひっかかったときだけ
配列に値を設定していきます。
(x < n && y < n が正方形の内部か? の判定になります。
この判定部分を変更すると、三角形や円の形で切り取ることができるようになります。)
ruby
1def gen_square(n) 2 ary = Array.new(n).map! { Array.new(n, 0) } 3 seq = 1 4 (0..n * 2 - 1).each do |scan_line| 5 (0..scan_line).each do |y| 6 x = scan_line - y 7 if x < n && y < n 8 ary[y][x] = seq 9 seq += 1 10 end 11 end 12 end 13 ary 14end 15 16def show_square(ary) 17 return if ary.size == 0 18 keta = Math.log10(ary.size * ary.size).floor + 2 19 fmt = "%#{keta}d" 20 ary.each do |line| 21 s = '' 22 line.each do |item| 23 s += format(fmt, item) 24 end 25 puts s 26 end 27end 28 29[0, 1, 2, 3, 4, 10].each do |d| 30 ary = gen_square(d) 31 show_square(ary) 32 puts 33end
実行例
1 1 2 3 4 1 2 4 3 5 7 6 8 9 1 2 4 7 3 5 8 11 6 9 12 14 10 13 15 16 1 2 4 7 11 16 22 29 37 46 3 5 8 12 17 23 30 38 47 56 6 9 13 18 24 31 39 48 57 65 10 14 19 25 32 40 49 58 66 73 15 20 26 33 41 50 59 67 74 80 21 27 34 42 51 60 68 75 81 86 28 35 43 52 61 69 76 82 87 91 36 44 53 62 70 77 83 88 92 95 45 54 63 71 78 84 89 93 96 98 55 64 72 79 85 90 94 97 99 100
投稿2015/11/23 07:36
総合スコア22328
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
ベストアンサー
ary[y][x] の値を求める関数を func(x, y, n) としてくくりだして、
2 次元配列に値を設定するようにしました。
ary[0][x] (四角の上辺の値)は (x * x + x) / 2 + 1 で計算できること、
ary[n-1][n-1-x] (四角の下辺の値)は n * n - (y * y + y) / 2 で計算できること、
を使って、 それ以外の ary[y][x] の値を計算しています。
四角の上辺の値 1, 2, 4, 7, 11, ... の数列は
隣同士の差が 1, 2, 3, 4, ... となっています。
ruby
1def sub(x) 2 (x * x + x) / 2 3end 4 5def func(x, y, n) 6 if x + y < n 7 sub(x + y) + 1 + y 8 else 9 n * n - sub(2 * n - 1 - x - y) + n - x 10 end 11end 12 13def gen_square(n) 14 ary = Array.new(n).map! { Array.new(n, 0) } 15 (0..n - 1).each do |y| 16 (0..n - 1).each do |x| 17 ary[y][x] = func(x, y, n) 18 end 19 end 20 ary 21end 22 23def show_square(ary) 24 return if ary.size == 0 25 keta = Math.log10(ary.size * ary.size).floor + 2 26 fmt = "%#{keta}d" 27 ary.each do |line| 28 s = '' 29 line.each do |item| 30 s += format(fmt, item) 31 end 32 puts s 33 end 34end 35 36[0, 1, 2, 3, 10].each do |d| 37 ary = gen_square(d) 38 show_square(ary) 39 puts 40end
実行結果
1 1 2 3 4 1 2 4 3 5 7 6 8 9 1 2 4 7 11 16 22 29 37 46 3 5 8 12 17 23 30 38 47 56 6 9 13 18 24 31 39 48 57 65 10 14 19 25 32 40 49 58 66 73 15 20 26 33 41 50 59 67 74 80 21 27 34 42 51 60 68 75 81 86 28 35 43 52 61 69 76 82 87 91 36 44 53 62 70 77 83 88 92 95 45 54 63 71 78 84 89 93 96 98 55 64 72 79 85 90 94 97 99 100
追記:
v -> Ux,y) を求める方法は次のようになります。
ruby
1def pos(v, n) 2 if v <= (n * n + 1) / 2 3 pos_0(v, n) 4 else 5 x, y = pos_0(n * n + 1 - v, n) 6 [n - 1 - x, n - 1 - y] 7 end 8end 9 10def pos_0(v, n) 11 z = 1 # 四角の上辺の数列の初期値 12 d = 1 # 四角の上辺の数列の次の項との差分 13 tx = 0 # 四角の上辺の位置 14 if v <= (n * n + 1) / 2 15 while z <= v 16 z += d 17 d += 1 18 tx += 1 19 end 20 z -= (d - 1) 21 x = tx - (v - z) - 1 22 y = v - z 23 [x, y] 24 else 25 fail "Bad argument v:#{v}, n:#{n}" 26 end 27end 28 29def gen_square(n) 30 ary = Array.new(n).map! { Array.new(n, 0) } 31 (1..n * n).each do |v| 32 x, y = pos(v, n) 33 ary[y][x] = v 34 end 35 ary 36end
投稿2015/11/23 03:35
編集2015/11/23 07:34総合スコア22328
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

0
2重ループ1つでなんとかなりました。
yは各行の先頭の値です。
横へ移動した時の増分をコントロールして各要素に入れる数値xを生成しています。
左上△エリアと右下△エリアで増分の計算式が変わっています。
C++
1#include <iostream> 2#include <iomanip> 3#include <vector> 4#include <cstdlib> 5#include <climits> 6 7typedef std::vector<std::vector<int> > Array2D; 8 9Array2D createArray(size_t n) 10{ 11 Array2D wArray2D(n, std::vector<int>(n)); 12 13 int y=1; 14 for (int j=0; j < n; ++j) { 15 int x=y; 16 for (int i=0; i < n; ++i) { 17 wArray2D[i][j]=x; 18 if (i < (n-j-1)) 19 x += (j+i+1); 20 else 21 x += (n-j-1 + n-i-1); 22 } 23 y += (j+2); 24 } 25 26 return wArray2D; 27} 28 29int main(int argc, char* argv[]) 30{ 31 if (argc < 2) 32return 1; 33 34 size_t n=strtoul(argv[1], 0, 10); 35 if ((n == 0) || (n == ULONG_MAX)) 36return 1; 37 38 Array2D wArray2D = createArray(n); 39 for (int j=0; j < n; ++j) { 40 for (int i=0; i < n; ++i) { 41 std::cout << std::setw(4) << wArray2D[i][j]; 42 } 43 std::cout << "\n"; 44 } 45 46 return 0; 47}
2重配列をコピーで返却しているので、本当はstd::move()を使って返却した方がよいです。
std::move()はC++11以上でないと使えないので、ここでは見送りました。。
【閑話休題】
しかし、こんなに短いプログラムでも、C++11の恩恵が3箇所もありました。(nullptr, テンプレート・パラメータの閉じ括弧>>, std::move)
C++11って偉大です。
投稿2015/11/23 01:22
編集2015/11/23 04:35総合スコア23274
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
質問文の手順をそのままコードにしてみました。
ruby
1# See https://teratail.com/questions/20823 2def gen_square(n) 3 ary = Array.new(n).map! { Array.new(n, 0) } 4 seq = 1 5 (0..n - 1).each do |x| 6 (0..x).each do |i| 7 ary[i][x - i] = seq 8 seq += 1 9 end 10 end 11 12 (1..n - 1).each do |y| 13 (0..n - 1 - y).each do |i| 14 ary[y + i][n - 1 - i] = seq 15 seq += 1 16 end 17 end 18 ary 19end 20 21def show_square(ary) 22 return if ary.size == 0 23 keta = Math.log10(ary.size * ary.size).floor + 2 24 fmt = "%#{keta}d" 25 ary.each do |line| 26 s = '' 27 line.each do |item| 28 s += format(fmt, item) 29 end 30 puts s 31 end 32end 33 34[0, 1, 2, 3, 10].each do |d| 35 ary = gen_square(d) 36 show_square(ary) 37 puts 38end
実行例:
$ ruby 1.rb 1 1 2 3 4 1 2 4 3 5 7 6 8 9 1 2 4 7 11 16 22 29 37 46 3 5 8 12 17 23 30 38 47 56 6 9 13 18 24 31 39 48 57 65 10 14 19 25 32 40 49 58 66 73 15 20 26 33 41 50 59 67 74 80 21 27 34 42 51 60 68 75 81 86 28 35 43 52 61 69 76 82 87 91 36 44 53 62 70 77 83 88 92 95 45 54 63 71 78 84 89 93 96 98 55 64 72 79 85 90 94 97 99 100
ary[i]j] を計算で求めることができれば、単純なコードにできます。
( 九九の表なら ary[y][x] = (y+1) * (x+1) を単純に代入していくだけですむように)
□の左上と右下の三角形にわければ、計算式が書ける気がするんですが...
投稿2015/11/23 00:01
総合スコア22328
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
少しコードが汚い気もするのですが,こんな感じでどうでしょう?
左上から始めて添え字を左下方向に動かしていきます.(x -= 1,y += 1)
x が左端を超える場合やyが下の端を超える場合(x == 0 or y+1 == size)は
正しい位置に移動するように添え字を代入します.
左上半分を埋めている時は,単純にx = y+1,y = 0で十分です.
右下半分に差し掛かった時は,直前のyとxの位置に合わせてyの位置を工夫する必要があります.
python
1#!/usr/bin/python 2import numpy as np 3size = int(input()) 4array = np.zeros([size, size]) 5 6x = 0 7y = 0 8for i in range(size*size): 9 array[y][x] = i+1 10 if x == 0 or y+1 == size: 11 tx = x 12 x = y+1 if (y+1 < size) else size-1 13 y = 0 if (y+1 < size and tx == 0) else (y+1)+(tx+1)-size 14 else: 15 x -= 1 16 y += 1 17 18print array
配列の添え字が0から始まる言語と1から始まる言語とでは書き方が若干変わると思いますが,
1から始まる言語では適宜xとyを変更してください.
投稿2015/11/22 18:26
総合スコア751
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/11/23 04:52
2015/11/23 06:56
2015/11/23 07:49 編集
2015/11/23 15:26