Spiral Array 문제를 보고 비슷한 문제를 만들어봤습니다.
http://codingdojang.com/scode/266
자연수 N을 입력받아서 다음과 같은 NxN 매트릭스를 출력하는 프로그램을 작성하라
<입력예1>
자연수 N을 입력하시오(0<N) : 3
<출력예1>
1 3 4
2 5 8
6 7 9
<입력예2>
자연수 N을 입력하시오(0<N) : 5
<출력예2>
1 3 4 10 11
2 5 9 12 19
6 8 13 18 20
7 14 17 21 24
15 16 22 23 25
19개의 풀이가 있습니다.
Brainfuck 실행 url
>>>,>-[<->-----]<+++[>+>+>+>+<<<<-]>->->>[<[>>+>+<<<-]>>>[<<<+>>>-]<<-]<<<<<+[[<[<+>>>>[<+>-]>[<+>-]<<[>>+<<-]<<-]<[>+<-]>>>>[<+>>>[>+>>+<<<-]>[<+>-]<<<-]>[<+>>>>>+<<<<-]>[<+>-]>>>[[>>+<<-]+>>-]<<[<<]>[>[>>]>+<<<[<<]<+>>-]->[>>]<<[-<<]<[>>+<<-]<[>+<-]<[>+<-]<[>+<-]<<[<+>>>>[<+>-]>[<+>-]<<[>>+<<-]<<-]<[>+<-]>>>>[<]<[>>>>[<->>+<-]<+[>]>[<<+<-<<+>>>>]>[<+<+>>-]<<-<<]<-]+<[>-<-]>[<+>-]+>>[<]<[>>->+<<]>>-<<<->>[<+>-]>[<+>-]<<[>>+<<-]>>>>>[<+>>+<-]>[<+>-]<<[<<<<<+>>>>>[-]]<<<<<]<[-]>>>+>>[>>>>[>>]>+>+<<<<[<<]<<-]>>>>[>>]>[>[<<+<+>>>-]<<[>>+<<-]<[<[<<]++++++++++>>[-<+<-[<+<<]<[+[->+<]<+<<]>>>>>>]<<[-]<<<++++++++++>[-<-[<+<<]<[+[->+<]<+<<]>>>>>]<[-]<<[<++++++[->++++++++<]>.>>+<+<[-]]>[>[-<->]++++++[-<++++++++>]<.[-]]>>++++++[->++++++++<]>.[-]>>[-]>[-]++++[<++++++++>-]<.[-]>>>[>>]<-]>++++++++++.[-]>-]
Haskell
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE FlexibleContexts #-}
import Data.Array
import Data.List
import Data.Tuple
import Data.Function
import Control.Applicative
import Control.Monad
import Control.Monad.Except
import Control.Monad.RWS.Lazy
import Control.Monad.Identity
-- 유틸리티 함수
type V2 = (Int, Int)
vecAdd (a,b) (c,d) = (a+c,b+d)
groupOn f = groupBy ((==) `on` f)
horizontal = groupOn fst . range
through genRay f ar = genRay (bounds ar) >>= f (ar!)
-- DSL 정의
type Path = ExceptT () (RWS (V2, V2) [V2] V2)
runPath m bnd@(i,_) = pure $ snd $ execRWS (runExceptT $ m') bnd i
where m' = (get >>= tell . pure) >> m
jump :: (V2 -> V2) -> Path ()
jump f = do
guard =<< (inRange <$> ask <*> gets f)
modify f
get >>= tell . pure
step = jump . vecAdd
run = many . step
-- 코어 로직
zigzag = runPath $ many $ do
step (1, 0) <|> step (0, 1)
run (-1, 1)
step (0, 1) <|> step (1, 0)
run (1, -1)
fillZigzag = (//) <*> through zigzag (const $ flip zip [1..])
-- I/O
render = through horizontal $ \f ->
(=<<) ((show . f) <> const " ") <> const "\n"
arr n = listArray ((1,1),(n,n)) $ repeat 0
parse = read
main = putStr . render . fillZigzag . arr . parse =<< getLine
nxn 배열의 좌표들을 특정 기준으로 정렬한 뒤 숫자를 배정하면 됩니다.
n = int(input())
C = sorted(((x, y) for x in range(n) for y in range(n)),
key=lambda z:(z[0]+z[1], z[1] if (z[0]+z[1])%2 else z[0]))
L = [[0] * n for _ in range(n)]
for i, (x, y) in enumerate(C, 1): L[x][y] = i
for line in L: print(*line)
C++
#include<iostream>
#include<vector>
using namespace std;
int main() {
int N, tmp;
cout << "자연수 N을 입력하시오(0<N) : ";
cin >> tmp;
cout << endl;
if (tmp < 1) { return 0; }//범위 외 값 받으면 프로그램 종료
N = tmp;
vector<vector<int>> arr;
arr.assign(N, vector<int>(N, 0));//N*N 벡터 0으로 초기화
int dx = -1, dy = 1;//내려가는 방향(↙), dx=1, dy=-1이면 올라가는 방향(↗)
int x = 0, y = 0;
int max_num = N * N;
for (int cnt = 1; cnt <= max_num; cnt++) {
arr[y][x] = cnt;
if(dx==-1 && (x==0 || y==N-1)){//내려가는 방향이고 x==0이거나 y==N-1이면(내려가는 방향에서 방향전환)
dy =(y!=N-1 && x==0)?1:0;//x가 0인 경우 y방향으로 한칸 내린다(단 y==N-1이면 예외)
dx = (y == N - 1) ? 1 : 0;//y가 N-1인 경우 x방향(오른쪽)으로 한칸 이동(x==N-1&&y=N-1인 경우는 루프 마지막이므로 예외처리 안해도 됨)
x += dx;
y += dy;
dx = 1;//방향전환(올라가는 방향으로 전환)
dy = -1;
}
else if (dx == 1 && (y == 0 || x == N - 1)) {//올라가는 방향이고 y==0이거나 x==N-1이면(올라가는 방향에서 방향전환)
dx = (x != N - 1 && y == 0) ? 1 : 0;//y==0인 경우 x방향(오른쪽)으로 한칸 이동(단 x==N-1이면 예외)
dy = (x == N - 1) ? 1 : 0;//x가 N-1인 경우 y방향으로 한칸 내린다(x==N-1&&y=N-1인 경우는 루프 마지막이므로 예외처리 안해도 됨)
x += dx;
y += dy;
dx = -1;//방향전환(내려가는 방향으로 전환)
dy = 1;
}
else {
x += dx;
y += dy;
}
}
//arr 출력
for (vector<int> v : arr) {
for (int x : v) {
cout << x << " ";
}
cout << endl;
}
return 0;
}
Ruby
사선으로 배치한 뒤 각 컬럼에 해당하는 값을 hash에서 획득/출력
def zigzag(n = gets.to_i)
nums, widths = [*1..n**2], 1.upto(n) + (n-1).downto(1)
grid = [*1..n].product([*1..n])
vals = widths.sum([]) { |w| w.odd? ? nums.shift(w).reverse : nums.shift(w) }
zigzag = grid.sort_by { |row, col| [row + col, -row] }.zip(vals).to_h
grid.map(&zigzag).each_slice(n) { |row| puts row.sum('') { |col| "%3d" % col } }
end
Test
# stdout test data
case_1 = <<-eos
1
eos
case_2 = <<-eos
1 3
2 4
eos
case_5 = <<-eos
1 3 4 10 11
2 5 9 12 19
6 8 13 18 20
7 14 17 21 24
15 16 22 23 25
eos
case_9 = <<-eos
1 3 4 10 11 21 22 36 37
2 5 9 12 20 23 35 38 53
6 8 13 19 24 34 39 52 54
7 14 18 25 33 40 51 55 66
15 17 26 32 41 50 56 65 67
16 27 31 42 49 57 64 68 75
28 30 43 48 58 63 69 74 76
29 44 47 59 62 70 73 77 80
45 46 60 61 71 72 78 79 81
eos
# stdin/out test
$stdin = StringIO.new('1\n')
expect { zigzag }.to output(case_1).to_stdout
$stdin = StringIO.new('2\n')
expect { zigzag }.to output(case_2).to_stdout
$stdin = StringIO.new('5\n')
expect { zigzag }.to output(case_5).to_stdout
$stdin = StringIO.new('9\n')
expect { zigzag }.to output(case_9).to_stdout
import numpy as np
from itertools import cycle
# 다음 위치(generator): 대각선 한 줄씩 오른쪽으로 진행
def pos_gen(in_range):
x, y = (0, 0)
for dx, dy in cycle(((1, -1), (-1, 1))): # ↙, ↗ 반전
# 배열 범위 벗어난 부분은 스킵
while not in_range(x, y):
x, y = x + dx, y + dy
while in_range(x, y):
yield (x, y)
x, y = x + dx, y + dy
y += 1
N = int(input('N='))
arr = np.zeros((N, N), np.int32)
pos = pos_gen(lambda x, y: 0 <= x < N and 0 <= y < N)
for i in range(N * N):
arr[next(pos)] = i + 1
print(arr)
파이썬 3.4.3
def print2arr(arr):
for i in range(number):
for j in range(number):
print('%3d'%arr[i][j],end='')
print('')
number=int(input('자연수를 입력하시오: '))
N=number*number
arr=[[-1 for i in range(number)] for j in range(number)]
X=0
Y=0
dx=1
dy=-1
for n in range(1,N+1):
arr[X][Y]=n
X+=dx
Y+=dy
if X==-1:
X-=dx;Y-=dy
Y+=1
dx=1
dy=-1
elif Y==-1:
X-=dx;Y-=dy
X+=1
dx=-1
dy=1
if X==number :
X-=1
Y+=1
if arr[X][Y] !=-1:
Y+=1
dx=-1
dy=1
elif Y==number:
Y-=1
X+=1
if arr[X][Y] !=-1:
X+=1
dx=1
dy=-1
print2arr(arr)
진행할 때 시작하는 지점을 잡아주고 배열의 끝을 만날때까지 진행하도록 만들었습니다.
#include<iostream>
using namespace std;
int main()
{
int** arr;
int N;
cin >> N;
//2차원 배열 동적 할당
arr = new int*[N];
for (int i = 0; i < N; i++)
{
arr[i] = new int[N];
}
int num = 0;
int row = 0;
int column = 0;
for (int i = 0; i < N * 2; i++)
{
//처음 위치 초기화
if (i < N)
{
if (i % 2 == 0)
{
row = i;
column = 0;
}
else
{
row = 0;
column = i;
}
}
else
{
if (N % 2 == 1)
{
if (i % 2 == 1)
{
row = i - N;
column = N - 1;
}
else
{
row = N - 1;
column = i - N;
}
}
else
{
if (i % 2 == 0)
{
row = N - 1;
column = i - N + 1;
}
else
{
row = i - N + 1;
column = N - 1;
}
}
}
//범위를 벗어 날 때까지 진행
while (1)
{
if (i % 2 == 0)//오른쪽위
{
arr[column++][row--] = ++num;
if (row == -1 || column == N)
break;
}
else//왼쪽아래
{
arr[column--][row++] = ++num;
if (row >= N|| column <= -1)
break;
}
}
}
//출력
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
cout << arr[i][j] << " ";
}
cout << endl;
}
}
function zzMat(n){
var res = [];
for(let i=0; i<n; i++)
res.push(Array(n));
for(let i=0,l=2*n-1,c=1; i<l; i++){
for(let j=0; j<=i; j++){
let a, b;
i&1 ? (a=i-j,b=j) : (a=j,b=i-j);
if(a >= n || b >= n || a < 0 || b < 0) continue;
res[a][b] = c++;
}
}
console.log(res);
}
zzMat(5)
[ [ 1, 3, 4, 10, 11 ],
[ 2, 5, 9, 12, 19 ],
[ 6, 8, 13, 18, 20 ],
[ 7, 14, 17, 21, 24 ],
[ 15, 16, 22, 23, 25 ] ]
부족한 실력이지만 용기내서 올려봅니다
#include "stdafx.h"
#include<iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int N, tmp;
int x, y, sum;
int** arr;
x = y = 0;
cin >> N;//input
arr = new int*[N];
cout << endl;
for (int i = 0; i < N; i++)
{
arr[i] = new int[N];
}
for (int i = 1; i < N*N + 1; i++)
{
sum = x + y;
arr[x][y] = i;
if (sum % 2 == 0)
{
if (x + 1 == N)
{
y++;
}
else
{
if (y >= 1)
y--;
x++;
}
}
else
{
if (y + 1 == N)
{
x++;
}
else
{
if (x >= 1)
x--;
y++;
}
}
}
for (int i = 0; i < N; i++)//output
{
for (int j = 0; j < N; j++)
{
cout << arr[i][j] << " ";
}
cout << endl;
}
cin >> tmp;
return 0;
}
#include <iostream>
using namespace std;
int main(void)
{
int num;
int a;
int *arr;
cout << "자연수 n을 입력하시오(0<N): ";
cin >> num;
a = num *num;
arr = new int[a];
for (int i = 0; i < a; i++)
{
arr[i] = i + 1;
}
for (int i = 0; i < a; i++)
{
if (i % num == 0)
cout << endl;
cout << arr[i] << " ";
}
}
Python 3.7
n = int(input('자연수 N을 입력하시오(0<N) : '))
mx = [[0]*n for i in range(n)]
x, y = 0, 0
a = 0 # 0=↙, 1=↗
mx[x][y] = 1
for i in list(range(2,n**2+1)):
if y == 0 and a == 0:
if x < n-1: x += 1
else: y += 1
a = 1
elif x == 0 and a == 1:
if y < n-1: y += 1
else: x += 1
a = 0
elif y == n-1 and a == 1:
x += 1; a = 0
elif x == n-1 and a == 0:
y += 1; a = 1
elif a == 0:
x += 1; y += -1
elif a == 1:
x += -1; y += 1
mx[x][y] = i
print('\n'.join([' '.join(list(map(str,i))) for i in mx]))
자연수 N을 입력하시오(0<N) : 5
1 3 4 10 11
2 5 9 12 19
6 8 13 18 20
7 14 17 21 24
15 16 22 23 25
package d234_Zigzag_Array;
import java.util.Scanner;
public class ZigzagArray {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Input two numbers, for the height and width of array:");
int Y=sc.nextInt(); // Y: 높이 입력(행)
int X=sc.nextInt(); // X: 넓이 입력(열)
int i=0, j=-1, n=1, direct=0; // 숫자넣기 1부터 시작
//i:행, j:열, n:숫자 넣기, direct:방향 ~ 1:왼쪽 아래 방향, 0:오른쪽 위 방향
int[][] array = new int[Y][X];
while(n<=Y*X) {
if(direct==1) { //방향:1은 왼쪽 아래 방향
if(i==Y-1) { //맨 아랫줄에 닿을 경우 방향 변경
j++;
direct=0;
array[i][j]=n++;
}
else if(j==0) { //맨 왼쪽 줄에 닿을 경우 방향 변경
i++;
direct=0;
array[i][j]=n++;
}
else { //방향:1은 왼쪽 아래 방향
i++;
j--;
array[i][j]=n++;
}
}
else if(direct==0) { //방향:0은 오른쪽 위 방향
if(j==X-1) { //맨 오른쪽 줄에 닿을 경우 방향 변경
i++;
direct=1;
array[i][j]=n++;
}
else if(i==0) { //맨 윗줄에 닿을 경우 방향 변경
j++;
direct=1;
array[i][j]=n++;
}
else { //방향:0은 오른쪽 위 방향
j++;
i--;
array[i][j]=n++;
}
}
}
for(i=0; i<Y; i++) { //출력
for(j=0; j<X; j++) { //최대자리수가 세자릿수일 때 최적화 출력
if(array[i][j]<10) System.out.print(" ");
else if(array[i][j]<100) System.out.print(" ");
System.out.print(array[i][j]+" ");
}
System.out.println(" ");
}
}
}
자바입니다. 메인함수에서 ZigzagArray zza=new ZigzagArray(); zza.printArray();로 실행시키면 됩니다.
public class ZigzagArray {
private int n=0;
public ZigzagArray() {
Scanner scan=new Scanner(System.in);
System.out.print("자연수 N을 입력하시오");
n=scan.nextInt();
}
public void printArray() {
int[][] arr=new int[n][n];
arr[0][0]=1;
int dx=1;
int dy=0;
boolean direct=false; //true 왼쪽아래, false 오른쪽 위
for(int i=2;i<=n*n;i++) {
if(direct) {
//왼쪽아래로 향하는 방향
//x값이 -가 되거나 y값이n보다 커질겨우
arr[dx][dy]=i;
if(dy-1<0 || dx+1>=n) {
direct=false;
dx++;
if(dx>=n) {
dx=n-1;
dy++;
}
}else {
dy--;
dx++;
}
}else {
//오른쪽 위로 향하는 방향
//y값이 -가 되거나 x값이 n보다 커지면 왼쪽아래
arr[dx][dy]=i;
if( dx-1<0 || dy+1>=n ) {
direct=true;
dy++;
if(dy>=n) {
dy=n-1;
dx++;
}
}else {
dy++;
dx--;
}
}
}
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) {
System.out.print(arr[i][j]+"\t");
}
System.out.println();
}
}
}
inp = int(input("INPUT : "))
def ZZarray(N) :
map_, x, y, dx, dy, numb = [['#' for i in range(N)] for z in range(N)], 0, 0, -1, 1, 1
dx_dy, trans = [(1, -1), (-1, 1)], [(1, 0), (0, 1)] # dx, dy
while numb <= (N**2) :
while numb <= (N**2) : #내부 루프에서 dx, dy만큼 옮겨가며 숫자를 갱신하고, 리스트 범위의 끝을 만나면 다음 루프로 넘어간다.
map_[y][x] = numb
if ((dx, dy) == (1,-1) and y == 0 and x != len(map_[0])-1) or ((dx, dy) == (-1, 1) and y == len(map_)-1) : ##trans가 x 증가인 경우 : dx_dy == (1,-1), y == 0 or dx_dy == (-1, 1), y == len(map)-1
x += 1
dx, dy = dx_dy[(dx_dy.index((dx, dy))+1)%2][0], dx_dy[(dx_dy.index((dx, dy))+1)%2][1]
numb += 1
elif ((dx, dy) == (-1,1) and x == 0) or ((dx, dy) == (1, -1) and x == len(map_[0])-1) : ## trans가 y 증가인 경우 : dx_dy == (-1,1), x == 0 or dx_dy == (1, -1), x == len(map[0])-1
y += 1
dx, dy = dx_dy[(dx_dy.index((dx, dy))+1)%2][0], dx_dy[(dx_dy.index((dx, dy))+1)%2][1]
numb += 1
else :
x, y = x + dx, y + dy
numb += 1
for i in map_ :
print(" ".join(list(map(lambda x : (str(x).rjust(len(str(N**2)))), i)))) # 결과 출력
ZZarray(inp)
결과
INPUT : 6
1 3 4 10 11 21
2 5 9 12 20 22
6 8 13 19 23 30
7 14 18 24 29 31
15 17 25 28 32 35
16 26 27 33 34 36
N=int(input("자연수 N을 입력하십시오: "))
elst=[[" "]*N for i in range(N)]
clst=[[x,y] for x in range(N) for y in range(N)]
lst=sorted(clst,key=lambda idx:(idx[0]+idx[1], idx[1] if (idx[0]+idx[1])%2 else idx[0]))
#sorting key 설명: clst안의 [x,y]에서 x(=idx[0])와 y(=idx[1])를 더한 값을 기준으로 오름차순 정렬하는데, 그 값이 2로 나누어 떨어지지 않으면 idx[1], 즉 y가 작은 순서에서부터 오름차순으로 정렬하고 그렇지 않으면 idx[0], 즉 x가 작은 순서로부터 오름차순 정렬함.(ex)N=3일 때, 좌표값의 합 기준으로 오름차순 정렬은 0,1,2,3,4이다. 그러나, 조건에 의해 합이 1일 땐 좌표가 [0,1],[1,0]이 있는데 합이 2로 나누어 떨어지지 않아 idx[1]을 기준으로 정렬하기 때문에 [1,0], [0,1]순이 된다. 나머지 과정은 생략함.)
for i, (x, y) in enumerate(lst,1):
elst[x][y]=i
for lst in elst:
for num in lst:
print("%3d"%num, end="")
print()
원래 좌표를 차근차근 더해가면서 숫자를 넣으려고 했는데 생각해보니 좌표의 리스트를 특정 조건에 의해 소팅한 후 그 순서대로 숫자를 지정해줘도 될 것 같아 이 방법으로 풀어봤습니다.
#파이썬
#문제는 풀었는데 소스가 좀 길어져 버렸습니다 ㅠ
def show_m(x):
for i in range (0,n):
for j in range (0,n):
print("%4d" %m[i][j],end='')
print()
n=int(input('n?'))
m=[]
for i in range (0,n):
temp=[]
for j in range (0,n):
temp.append(0)
m.append(temp)
x,y,num=0,0,1
m[y][x]=num
while(1):
if y != n-1:
y+=1
num+=1
m[y][x]=num
elif y==n-1:
x+=1
num+=1
m[y][x]=num
while (x!=n-1 and y!=0):
y-=1
x+=1
num+=1
m[y][x]=num
if y==0 and x!=n-1:
x+=1
num+=1
m[y][x]=num
elif x==n-1:
y+=1
num+=1
m[y][x]=num
while (x!=0 and y!=n-1):
y+=1
x-=1
num+=1
m[y][x]=num
if x==n-1 and y==n-1:
show_m(m)
break
n = int(input())
n_list, loc_list = [], []
for a in range(n):
n_list.append([])
for b in range(n):
n_list[-1].append([])
loc_list.append([a, b])
m_loc_sum = 2*(n-1)+1
loc_sum = 0
n = 1
while loc_sum < m_loc_sum:
temp = []
for loc in loc_list:
if loc[0] + loc[1] == loc_sum:
temp.append(loc)
for write in temp:
n_list[write[0]][write[1]] = n
n += 1
loc_sum += 1
for a in n_list:
print(a)
import random
d = int(input("자연수 N을 입력하시오(0<N) : "))
a = d*d
b = []
while a:
b.append(a)
a -= 1
for i in range(1,d+1):
for j in range(1,d+1):
c = random.choice(b)
b.remove(c)
print(c,end=' ')
print()
n = int(input('n을 입력하세요: '))
map = [[0 for _ in range(n)] for _ in range(n)]
su = 1
for i in range(2*n - 1):
if i % 2 == 1:
if i < n:
a, b = i, 0
else:
a, b = n-1, i-n+1
while a >= 0 and b < n:
map[a][b] = su
a, b, su = a-1, b+1, su+1
else:
if i < n:
a, b = 0, i
else:
a, b = i - n + 1, n - 1
while b >= 0 and a < n:
map[a][b] = su
a, b, su = a + 1, b - 1, su + 1
for r in range(n):
for c in range(n):
print(' {0:3}'.format(map[r][c]), end="")
print()