이 페이지는 코딩도장 데이터의 읽기 전용 정적 보관본입니다.

나선형 배열의 거리

1부터 차례대로 다음과 같이 정렬했을 때, 숫자 N(1 <= N <= 109)을 입력받아서 1부터 N까지 가는 최단거리를 계산하는 프로그램을 작성하세요. (상, 하, 좌, 우로만 움직일 수 있고 대각선으로는 움직일 수 없다.)

17 16 15 14 13
18  5  4  3 12
19  6  1  2 11
20  7  8  9 10
21 22 23 24 ...

Input 예시

1
3
17
19
26
2550
2573

Output 예시

0
2
4
2
5
49
28

2019/11/07 17:56

AY

멍청해서 그런가 문제가 이제가 안되네요... ㅠㅠ - maluchi, 2020/02/07 12:40
배우는 입장이지만 한가지 방법은 1을 (0,0) 좌표로 할 때 3은 (1,1)이므로 최단거리는(|x|+|y|)로 표현되는 프로그램을 작성하라는 문제같습니다. - mr. gimp, 2020/03/22 16:37

19개의 풀이가 있습니다.

Python 3

나선형 배열은 다음과 같은 범주를 갖는다:

  • 0th: 1
  • 1th: 2 .. 9
  • 2th: 10 .. 25
  • 3th: 26 .. 49
  • ...
  • 즉, nth 범주의 최대값은 (2 * (n + 1) - 1) ** 2 (단, n >= 0) ... Eq.(1)

자연수 num이 주어질 때, Eq.(1)을 통해 num이 포함되는 범주 n을 구할 수 있다.

또한, nth 범주에 대해 각 변의 중앙값은 (e.g. 2th 범주에서는 11, 15, 19, 23)

  1. s1 = 4 * n ** 2 - 3 * n + 1
  2. s2 = s1 + 2 * n
  3. s3 = s2 + 2 * n
  4. s4 = s3 + 2 * n

이며,

num이 속하는 범주 nth에 대해 계산되는 s1, s2, s3, s4로 부터의 |num- s|의 최소값을 d라고 할 때,

최소 이동거리는 n + d이다.

def main():
    num = int(input())
    rst = get_min_distance(num)
    print(rst)


def get_nth(num: int):
    """num이 속하는 범주(nth) 계산"""
    nth = 0
    last_val = 1
    while num > last_val:
        nth += 1
        last_val = (2 * (nth + 1) - 1) ** 2

    return nth


def get_min_distance(num: int):
    """num으로 이동하는 최소 거리 계산"""
    nth = get_nth(num)
    if num == 1:
        return nth

    points = [4 * nth ** 2 - 3 * nth + 1]
    for i in range(3):
        points.append(points[-1] + nth * 2)
    min_distance = nth + min(abs(num - point) for point in points)

    return min_distance


if __name__ == '__main__':
    main()

2019/12/13 16:44

mohenjo

+1 그 설명해주신거 보면서 잘 공부하고 있는데 n th 범주 최댓값 설정할때 n >= 0 이나 (2 * n - 1)**2 로 식을 고쳐야되지 않을까 싶네요 - 바가지대머리, 2019/12/18 20:25
범위 표시에 오류가 있었네요. 감사합니다. - mohenjo, 2019/12/18 21:16

나선형 맵에서 1이 원짐일 때 특정 숫자의 좌표를 구하는 문제. n보다 작으면서 가장 큰 홀수 제곱근 m을 찾은 뒤, m^2과의 차이를 알면 좌표가 바로 나옵니다.

시간복잡도는 제곱근 m을 찾는데 필요한 O(log n). 공간복잡도는 O(1)

#include<stdio.h>
#include<algorithm>
using namespace std;
long long int n, m;
long long int minsqrt(long long int x) {
    long long int l = 1;
    long long int r = x+1;
    long long int mid;
    while (l < r) {
        mid = (l + r) / 2;
        if (mid <= x / mid) {
            if (mid * mid == x)return mid;
            else if (mid * mid < x)l = mid + 1;
            else r = mid;
        }
        else {
            r = mid;
        }
    }
    return l - 1;
}
int main() {
    int i, j, k, l;
    while (~scanf("%lld",&n)) {
        if (n == 1) {
            printf("0\n"); continue;
        }
        m = minsqrt(n-1);
        if (!(m & 1))m--;
        long long int mz = (m+1) / 2;
        long long int diff = n - m * m ;
        int type = 0;
        while (diff > mz*2) {
            diff -= mz*2;
            type++;
        }
        long long int x, y;
        if (type == 0)
        {
            x = mz;
            y = -mz + diff;
        }
        else if (type == 1) {
            x = mz - diff;
            y = mz;
        }
        else if (type == 2) {
            x = -mz;
            y = mz - diff;
        }
        else {
            x = -mz + diff;
            y = -mz;
        }
        printf("%lld\n", abs(x) + abs(y));
    }
}

input

1
3
17
19
26
2550
2573
1000000000
1000000000000000000
987654321987654321
2147483647
1048576

output

0
2
4
2
5
49
28
17493
999999999
987801760
41706
1023

2019/11/07 22:33

pichulia

스캐너를 이용해봤습니다. 출제자의 의도와 많이 다를 수도 있습니다.



package practice;

import java.util.Scanner;

public class What_Should_I_make {
    public static void main(String[] args) {

        //      1부터 차례대로 다음과 같이 정렬했을 때, 
        //      숫자 N(1 <= N <= 10^9)을 입력받아서 
        //      1부터 N까지 가는 최단거리를 계산하는 프로그램을 작성하세요. 
        //      (상, 하, 좌, 우로만 움직일 수 있고 대각선으로는 움직일 수 없다.)

        Scanner sc = new Scanner(System.in);

        int[][] arr;
        int size = 0;//크기
        int num = 1;//시작수
        int x = 0;//x축
        int y = 0;//y축
        System.out.print("홀수만 입력: ");
        size = sc.nextInt();
        arr = new int[size][size];//사용자가 지정한 사이즈

        x = size/2;
        y = size/2;
        //정중앙에서 시작



        int a = 1;//순서변수
        int sum = 1;//한줄로 숫자를 생성하기위한 변수

        arr[y][x] = num;
        //변의길이에 따른 나선배열 생성
        outer : while(num <= size*size) {


            for(int i = 0; i < sum; i++) {
                if(a == 1){ x += 1; num++; 
                if(num == size*size+1) {
                    break outer;
                }//규격외로 넘어가는 숫자생성 방지 
                arr[y][x] = num; }//오른쪽으로 생성
                if(a == 2){ y -= 1; num++; arr[y][x] = num; }//위로 생성
            }//for

            for(int i = 0; i < sum; i++) {
                if(a == 3){ x -= 1; num++; arr[y][x] = num; }//왼쪽으로생성
                if(a == 4){ y += 1; num++; arr[y][x] = num; }//아래로 생성
            }//for


            if( a == 4 ) {
                a = 1;
                sum++;
            }else if( a == 2){
                sum++;
                a++;
            }else if( a==3 || a==1 ){
                a++;
            }//진행순서 설정


        }//while

        //배열 출력 코드
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                System.out.print(arr[i][j]+"    ");
            }//inner
            System.out.println();
        }//output


        System.out.println("-------------------------------");



        int number = 0;
        System.out.println("5번 측정하세요");
        while(number != 5) {

            System.out.print("1에서 거리를 측정할 숫자 값: ");

            int n = sc.nextInt();
            int xLength;
            int yLength;

            for (int i = 0; i < arr.length; i++) {

                for (int j = 0; j < arr[i].length; j++) {   
                    if(n == arr[i][j]) {

                        if( i >= (size/2) ) {

                            yLength = i-(size/2);
                        }else{
                            yLength = (size/2)-i;
                        }//y값 거리측정

                        if( j >= (size/2) ) {
                            xLength = j-(size/2);
                        }else {
                            xLength = (size/2)-j;
                        }//x값 거리측정
                        System.out.println( xLength + yLength );
                    }//if

                }//inner

            }//outer
            number++;
        }//while



    }//main
}

출력결과

홀수만 입력: 7

37 36 35 34 33 32 31
38 17 16 15 14 13 30
39 18 5 4 3 12 29
40 19 6 1 2 11 28
41 20 7 8 9 10 27
42 21 22 23 24 25 26
43 44 45 46 47 48 49


5번 측정하세요

1에서 거리를 측정할 숫자 값: 25

4

1에서 거리를 측정할 숫자 값: 47

4

1에서 거리를 측정할 숫자 값: 49

6

1에서 거리를 측정할 숫자 값: 37

6

1에서 거리를 측정할 숫자 값: 44

5

2019/11/14 00:32

권태욱

+1 N=10^9일 때 잘 나오지 않을것 같습니다. 이 때 답이 나오려면 size값이 31623이 되어야하는데...돌려보진 않았지만 메모리가 힘들어할거 같습니다ㅠ - pichulia, 2019/11/17 12:59

Ruby

4변 중 가까운 변의 가운데 지점으로 거리 계산

distance = lambda do |given_num|
  side_length = (given_num ** 0.5).ceil.then { |s| s + ((s % 2) ^ 1) }
  radius, last_num = side_length / 2, side_length ** 2
  nearests = 4.times.map { |nth| last_num - ((nth * 2 + 1) * radius)}
  nearests.map { |vert| radius + (vert - given_num).abs }.min
end
distance_from_spiral_center = -> { puts gets("\n\n").split.map(&:to_i).map(&distance) }  

Test

test_numbers = [1, 3, 17, 19, 26, 2550, 2573]
expect(test_numbers.map(&distance)).to eq [0, 2, 4, 2, 5, 49, 28]
expect(distance[10**9]).to eq 17493
expect(distance[10**99]).to eq 40977302808488135725000812741163967580261426850331327105897628076954533744596746239

# for perfomance test
require 'benchmark'

expect( Benchmark.realtime { distance[10**9] } ).to be < 0.0001
expect( Benchmark.realtime { distance[10**100] } ).to be < 0.0001

Output

distance_from_spiral_center.call
1
3
17
19
26
2550
2573

0
2
4
2
5
49
28

2019/11/21 14:29

rk

import math

inp = int(input("INPUT : "))

x, y, result, nmax, dx, dy = 0, 0, 0, 0, 0, 1

DXDY_LIST,ADDRESS_IN_LIST  = [(0, 1), (-1, 0), (0, -1), (1, 0)], 0

## nmax 계산
while True :
    if math.sqrt(inp)%2 == 1 :
        result=(math.sqrt(inp)-1)
        break
    elif (2*nmax+1)*(2*nmax+1) > inp :
        break
    else :
        nmax += 1
x, y, result = nmax, -nmax+1, (2*(nmax-1)+1)*(2*(nmax-1)+1)+1

# 좌표 계산
while True :
    if nmax == 0 :
        print((math.sqrt(inp)-1))
        break
    if result == inp :
        print(abs(x)+abs(y))
        break
    else :
        x, y = x+dx, y+dy
        result += 1
        if abs(x) > nmax or abs(y) > nmax :
            x, y = x-dx, y-dy
            ADDRESS_IN_LIST = (ADDRESS_IN_LIST+1)
            dx = DXDY_LIST[ADDRESS_IN_LIST][0]
            dy = DXDY_LIST[ADDRESS_IN_LIST][1]
            x, y = x+dx, y+dy

먼저 입력된 수가 몇 번째 껍질에 들어있는지 계산하고, 그 다음부터는 수를 하나하나 늘려가며 좌표를 구하는 식으로 계산하였습니다.

결과


INPUT : 1000000000
17493

INPUT : 2550
49

INPUT : 26
5

입력된 수가 (2n+1)^2일 때의 처리가 매끄럽지 못 하는 등 미숙한 점이 많네요 ㅠㅠ

2019/11/26 17:54

GG

코딩 초보가 무식하게(방법적으로...) Python으로 짜봤습니다.

해당 숫자(number)를 포함하는 최소 크기의 정사각형 형태의 나선 배열을 가정해두고(한변의 길이가 size),

맨 왼쪽 하단 숫자 좌표를 (0,0)으로 두었을때

1의 위치 좌표 계산

나선의 최대 숫자에서 number까지의 거리 계산하여 맨 바깥쪽 껍질에서의 위치 좌표 계산

1과 number의 x좌표끼리의 차이와 y좌표끼리의 차이를 더하여 거리를 계산했습니다.

number의 좌표 구하는 부분이 영 마음에 안드네요.

import math

# 숫자 입력
number = int(input("Input Number : "))

# 해당 number를 포함하는 정사각 나선의 한변의 길이
size = math.ceil(math.sqrt(number))

# 정사각형 나선 최대 숫자에서 number까지의 거리
dist = size**2 - number

# number가 최대 숫자와 같은 변에 있는지 확인 및 좌표 계산을 위한 변수, edge > 0인 경우 변이 바뀜
edge = dist - (size - 1)

if size%2 == 0:
    # 나선의 한변의 길이가 짝수인 경우
    # (0,0) 기준 1의 위치 좌표
    [x1, y1] = [int(size/2 - 1), int(size/2)]

    # (0,0) 기준 number의 위치 좌표
    # 최대 숫자와 number가 같은 변에 있는지 확인
    if edge > 0:
        [x2, y2] = [size - 1, edge]
    else:
        [x2, y2] = [dist, 0]

else:
    # 나선의 한변의 길이가 홀수인 경우
    # (0,0) 기준 1의 위치 좌표
    [x1, y1] = [int(size/2), int(size/2)]

    # (0,0) 기준 number의 위치 좌표
    # 최대 숫자와 number가 같은 변에 있는지 확인
    if edge > 0:
        [x2, y2] = [0, edge]
    else:
        [x2, y2] = [-edge, size - 1]

# 1에서 부터 number의 거리
dist_from_one = abs(x1 - x2) + abs(y1 - y2)

print(dist_from_one)

2019/12/03 23:43

다비도

Javascript(ES6)...

  • 반복문으로 위치 추적
`1 부터 입력한 숫자 n 까지 반목문 생성, 반복문 안에서 처음 1 과의 상대적 위치를 나타내는 x, y 변수 계속 조정, 다음 칸이 경계를 벗어나면 방향 전환, Math.abs(x) + Math.abs(y) 가 1 에서 n 까지의 최단거리가 됨`;

function spiral_a(n) {

    let _n = Math.max(1, Math.min(1000000000, n));

    // x, y 는 1 과의 상대적 위치, dx, dy 는 x, y 가 진행할 방향, border 는 경계의 크기
    let [x, y, dx, dy, border] = [-1, 0, 1, 0, 0];

    // 반복문을 돌며 x, y 계속 추적
    for(let i = 1; i < _n + 1; i++) {
        [x, y] = [x + dx, y + dy];

        // x, y 의 위치가 오른쪽 아래 border 에 모두 닿으면 경계 확장
        if(x == border && y == border) { border++; }

        // x, y 의 다음 진행방향이 border 를 벗어나면 방향전환
        if(x + dx < -border || border < x + dx || y + dy < -border || border < y + dy) {
            [dx, dy] = [dy, -dx];
        }
    }

    console.log(`${Math.abs(x) + Math.abs(y)}`);
}

spiral_a(1);                // 0
spiral_a(3);                // 2
spiral_a(17);               // 4
spiral_a(19);               // 2
spiral_a(26);               // 5
spiral_a(2550);             // 49     
spiral_a(2573);             // 28
// spiral_a(1000000000);    // 17493    시간이 너무 오래 걸림
  • 규칙성을 찾아내어 계산
`Spiral 구조를 보면 오른쪽 아래 대각선 방향으로 숫자의 규칙성이 보임, 1, 9, 25, 49, 81, ... 이며 구체적으로는 아래와 같음

border                     0    1    2    3    4    5    6 ...
대각선 숫자 corner_n        1    9   25   49   81  121  169 ...
중심에서 거리 distance      0    2    4    6    8   10   12 ...

corner_n = (border * 2 + 1)**2, distance = border * 2 로 나타낼 수 있음

반복문을 돌며 주어진 숫자 n 을 바로 초과하는 corner_n 과 distance 를 구한 뒤, n 과 corner_n 차이에 대한 세부적인 조정으로 distance 재계산`;

function spiral_b(n) {

    let _n = Math.max(1, Math.min(1000000000, n));

    // 반복문으로 corner_n, distance 계산
    let [border, corner_n, distance] = [-1, 0, 0];
    do {
        border++;
        corner_n = (border * 2 + 1)**2;
    } while(corner_n < _n);
    distance = border * 2;

    // n 과 corner_n 차이 조정
    let sub = corner_n - _n;
    if(sub != 0) {
        sub %= (border * 2);
        if(sub > border) { sub = border * 2 - sub; }
        distance -= sub;
    }

    console.log(distance);
}

spiral_b(1);                // 0
spiral_b(3);                // 2
spiral_b(17);               // 4
spiral_b(19);               // 2
spiral_b(26);               // 5
spiral_b(2550);             // 49     
spiral_b(2573);             // 28
spiral_b(1000000000);       // 17493

2019/12/12 10:04

tedware

C언어로 해봤습니다. 초보라서..그냥 수열의 특징을 이용해 봤습니다.

1이 입력되었을 경우에는 그냥 0을 출력하도록 하고 2이상일 경우 1에서 부터 맨 마지막의 네 코너의 수를 구해서 코너까지 도달하는 거리 - 그 숫자에서 코너까지의 거리 를 계산했습니다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int getShortcut(int number);

int main() 
{
    int input, result;
    scanf("%d", &input);

    if (input < 2)      //1의 경우 계산을 하지 않고 0출력
    {
        printf("0");
    }
    else
    {
        printf("%d", getShortcut(input));
    }

    return 0;
}

int getShortcut(int number)
{
    int Nbox = 1;           //몇번째 나선인지 저장할 변수
    int EndOfLastBox = 0;   //비교에 사용할 이전 박스의 마지막 수
    int EndOfCuurentBox = 0;    //비교에 사용할 현재 박스의 마지막 수
    int footOnBorderCorner[5] = { 0, }; //이적박스의 마지막 수부터, 현재박스의 각 코너의 수를 저장할 배열
    int minusStep = 0;  //현재 수에서부터 각 코너까지의 거리를 저장할 변수
    int temp1 = 0, temp2 = 0;   //minusStep에 저장하기전 비교에 사용할 임시변수

    //몇번째 나선에 있는지 확인
    do
    {
        EndOfLastBox = (2 * (Nbox - 1) - 1)* (2 * (Nbox - 1) - 1);
        EndOfCuurentBox = (2 * Nbox - 1)* (2 * Nbox - 1);
        if (number > EndOfLastBox && number <= EndOfCuurentBox)
            break;
        Nbox++;
    } while (1);


    //각 나선에서 어느 변에 있는지 확인하여 코너로부터의 거리값을 구함.
    for (int i = 0; i < 5; i++)
    {
        footOnBorderCorner[i] = EndOfLastBox + ((Nbox-1)*2 * (i));

        if (i > 0)
        {
            if (number == footOnBorderCorner[i])   //만약 코너값 중에 일치하는 것이 있으면 minusStepㅇ  =0 
            {
                minusStep = 0;
            }
            else if (number > footOnBorderCorner[i - 1] && number < footOnBorderCorner[i])  //각 변에 속하면
            {
                temp1 = footOnBorderCorner[i] - number; // 큰수로부터의 거리
                temp2 = number - footOnBorderCorner[i - 1]; //작은수까지의 거리

                if (temp1 > temp2)  //작은쪽을 minusStep에 할당
                {
                    minusStep = temp2;
                }
                else
                {
                    minusStep = temp1;
                }

                break;
            }
        }
    }


    return ((Nbox-1)*2) - minusStep;    
}

2019/12/16 00:12

길정균

풀이에 있는 mohenjo이라는 아이디를 가진 분의 개념을 바탕으로 java언어를 가지고 만들었습니다.

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {

        Main main = new Main();

        int num;
        Scanner scan = new Scanner(System.in);
        num= scan.nextInt();//숫자입력

        int check = main.get_min_distance(num);
        System.out.println("입력한 숫자값: " + num);
        System.out.println("문제의 답: " + check);

    }

    public int get_nth(int num) {//num이 속하는 범주 계산.
        int nth=0;
        int last_val=1;

        while(num>last_val) {
            nth=nth+1;
            last_val =(int) Math.pow((2 * (nth+1) -1 ), 2);
        }
        return nth;
    }


    public int get_min_distance(int num){//num으로 이동하는 최소거리 계산
        int nth= get_nth(num);
        if(num==1) {
            return nth;
        }

        int points = 4*(int)Math.pow(nth, 2) - 3*nth + 1;
        int[] arr = new int[4];
        for(int i=0;i<4;i++) {
            arr[i]=points+i*2*nth;
        }

        int[] min_distance = new int[4];
        for(int i=0;i<4;i++) {
            min_distance[i]= nth + Math.abs(num-arr[i]);
        }

        //최소값구하기
        int min = min_distance[0];
        for(int i=0; i<min_distance.length;i++) {
            if(min>min_distance[i]) {
                min=min_distance[i];
            }
        }

        return min;
    }

}

올리는 건 처음이라 이게 맞는지 모르겠는데 확인해주세요.

2019/12/18 01:52

연보라

n = 0 
x = (random_number) #input 할 수

while True:
    if (2*n - 1)**2 < x <= (2*n + 1)**2:
        break
    else:
        n += 1


# n => n 번째 껍질에 존재한다는것을 알려준다.
# 껍질 => 2~9까지는 1번껍질, 10~25번까지는 2번껍질....
# 배열해보시면 n번껍질이 무엇인지 알수있을것입니다.

list1 = [i for i in range(2*n, n, -1)]
list2 = [j for j in range(n, 2*n)]
list3 = list1 + list2
list4 = list3*4

#젤 큰수로부터 몇번째 있는가에 따라 나눠지는 도달횟수, n껍질 기준
#ex) 25로부터 시작되는 2번껍질을 에 도달하는 최소횟수를 리스트(list4)로 풀면 [4,3,2,3,4,3,2,4,3,4,3,2,3,4,3,2,3] 이됩니다.
#4짝으로 반복이 되는데 사각형의 4개의 면을 의미합니다.

k = (2*n + 1)**2 - x # 위에 정한 리스트에 몇번째에 위치하는가를 나타내기위해 k를 썼습니다.

final_result = list4[k] #최종결과는 리스트를 인덱스한것으로 나타냈습니다.

print(final_result)

#함수로 나타내지 못한점 죄송합니다. 초보라서... 수정해주시면 감사하겠습니다.

처음으로 문제 풀고 올려봅니다. 확인해주시면 감사하겠습니다!

2019/12/20 17:47

Seong Gyu Kwon

def spiral(N):

    i = 1


    while True:

        if N <= (2*i -1) ** 2:
            break

        i += 1


    if i == 1: return 0

    temp = 2*i -1

    t_list = []

    for j in range(temp**2 - temp + 2,temp**2+1):
        t_list.append(j)

    while True:

        if N in t_list : break

        else:
            for k in range(len(t_list)):
                t_list[k] -= temp -1

    result = (i-1) + abs(t_list.index(N) - (i-2))

    return result

2020/01/03 16:45

임태욱

파이썬 3입니다

정사각형 모양의 껍질을 먼저 찾았습니다 (n 번째 껍질)

import math

N = int(input())

n = math.ceil((math.sqrt(N) + 1) / 2)

print('1부터 {}까지의 거리는 {}이다'.format(N, n - 1 + abs((N - (2 * n - 3) ** 2) % (2 * n - 2) - n + 1)))

2020/01/31 19:19

우재용

N=int(input("""1부터 N까지 가는 최단거리를 출력합니다.
N(1<=N<=10^9)을 입력하십시오:"""))
ON=N
N=int(N**(1/2))**2
border=int(N**(1/2))+1
onetoS=int(N**(1/2))-1
lst=[onetoS,onetoS+1]
n,a=onetoS+1,1
while len(lst)<2*border:
    if border%2==0:
        n=n-a
        lst.append(n)
        if n==int(border/2):
            a=-a
        elif n==border:
            a=-a
    else:
        n=n-a
        lst.append(n)
        if n==int(border/2):
            a=-a
        elif n==(border-1):
            a=-a
d=dict()
for k in range(N,N+len(lst)):
    d[k]=lst[k%N]
if ON<=3:
    d={1:0,2:1,3:2}
print(d[ON])

결과

1부터 N까지 가는 최단거리를 출력합니다.
N(1<=N<=10^9)을 입력하십시오:1000000000
17493

2020/02/09 18:06

박시원

import math

n=int(input())
def check_far(n):
    c=math.sqrt(n)
    n_2=math.ceil(c)
    if n_2%2==1:
        return (n_2-1)/2
    else: return n_2/2

def check(n,garo):
    start=(garo*2+1)**2
    gap=start-n
    if gap>=0 and gap<=garo*2:
        mid= garo
        return garo+abs(gap-mid)
    elif gap>garo*2 and gap<garo*4:
        mid= 3*garo
        return garo+ abs(gap-mid)
    elif gap>=garo*4 and gap<=garo*6:
        mid= 5*garo
        return garo+abs(gap-mid)

    else:
        mid=7*garo
        return garo + abs(gap-mid)



garo=check_far(n)
print(int(check(n,garo)))

2020/04/06 01:54

정민석

package helical_ordering;
import java.util.Scanner;
public class HelicalOrdering {

    public static void main(String[] args) {
        //1 <= N <= 9801
        Scanner in = new Scanner(System.in);
        int n=100, N=n*n;
        int i=50, j=50, k=1, p, q, input;
        int[][] board = new int[n][n];
        int direction=0; // 0 오른쪽, 1 위쪽, 2 왼쪽, 3 아래쪽

        do {
            System.out.print("Input:");
            input = in.nextInt();
            if(input==0) break;

            /*나선형 배열 만들기*/
            board[50][50]=1; //첫 스텝
            while(k<input){
                if(direction==0) { //오른쪽
                    board[i][++j]=++k;
                    if(board[i-1][j]==0)
                        direction=1;
                }
                else if(direction==1) { //위쪽
                    board[--i][j]=++k;
                    if(board[i][j-1]==0)
                        direction=2;
                }
                else if(direction==2) { //왼쪽
                    board[i][--j]=++k;
                    if(board[i+1][j]==0)
                        direction=3;
                }
                else if(direction==3) { //아래쪽
                    board[++i][j]=++k;
                    if(board[i][j+1]==0)
                        direction=0;
                }
                else System.out.println("It should not reach here.");
            }   

            int result=0;
            result+=(i>50)?i-50:50-i;
            result+=(j>50)?j-50:50-j;

            System.out.println("Output:"+result);       
        }while(input!=0);

        /*print*//*
        for(p=0; p<n; p++) {
            for(q=0; q<n; q++) {
                if(board[p][q]<1000)
                    System.out.print(" ");
                if (board[p][q]<100)
                    System.out.print(" ");
                if (board[p][q]<10)
                    System.out.print(" ");
                System.out.print(" "+board[p][q]);
            }
            System.out.println();
        }*/
    }
}
Input:1
Output:0
Input:3
Output:2
Input:17
Output:4
Input:19
Output:2
Input:26
Output:5
Input:2550
Output:49
Input:2573
Output:28
Input:0

2020/05/16 17:00

Katherine

from math import sqrt, floor


# 1의 위치가 원점 (0, 0)일 때 n의 좌표를 구한다.
def find_pos(n):
    m = (floor(sqrt(n-1)) + 1) // 2 # 몇 번째 나선인가? => 0, 1, 2, 3, ...
    l = m * 2                       # (한 변의 길이 - 1) => 0, 2, 4, 6, ...

    # 하변
    k = (l + 1) ** 2    # k는 각 변에서 가장 큰 수 => 1*1, 3*3, 5*5, 7*7, ... 에서 시작
    if k - l < n <= k:
        return m, m - (k - n)

    # 좌변
    k -= l
    if k - l < n <= k:
        return m - (k - n), -m

    # 상변
    k -= l
    if k - l < n <= k:
        return -m, -m + (k - n)

    # 우변
    k -= l
    return -m + (k - n), m


n = int(input())
x, y = find_pos(n)
print(abs(x) + abs(y))

2020/07/13 01:15

Noname

자바로 풀어봤습니다.

import java.util.Scanner;

public class test {
    public static void paintingArray(int[][] result, int m, int n) {
        for(int i=0; i<m; i++) {
            for(int j=0; j<n; j++) {
                System.out.printf("%3d", result[i][j]);
            }
            System.out.println();
        }
    }

    public static int[] findPosition(int[][] result, int Number) {
        int[] position = new int[2];

        for(int i=0; i<result.length; i++) {
            for(int j=0; j<result[0].length; j++) {
                if(result[i][j]==Number) {
                    position[0] = j;
                    position[1] = i;
                }
            }
        }

        return position;
    }

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);

        // 배열 사이즈 입력
        System.out.print("배열의 사이즈를 입력(m:row, n:column):");
        int m = scan.nextInt();
        int n = scan.nextInt();

        // 배열 초기화
        int result[][] = new int[m][n];

        // 배열 원소 압력
        int element = m*n, direction=0, row=0, column=0;

        while(element>0) {
            switch(direction) {
            case 0:
                for(int j=column; j<n-1-column; j++) {
                    result[row][j] = element;
                    element--;
                }
                direction++;
                break;
            case 1:
                for(int i=row; i<m-1-row; i++) {
                    result[i][n-1-column] = element;
                    element--;
                }
                direction++;
                break;
            case 2:
                for(int j=n-1-column; j>column; j--) {
                    result[m-1-row][j] = element;
                    element--;
                }
                direction++;
                break;
            case 3:
                for(int i=m-1-row; i>row; i--) {
                    result[i][column] = element;
                    element--;
                }
                direction=0;
                column++;
                row++;
                break;
            }
        }

        // 결과 출력
        paintingArray(result, m, n);    

        // position of zero
        int[] zeroPosition = findPosition(result, 1);

        // 자연수 N 입력
        System.out.print("\n최단거리를 계산하고 싶은 N을 입력:");
        int N = scan.nextInt();

        // position of N
        int[] NPosition = findPosition(result, N);

        //distance 계산
        int distance = 0;
        for(int i=0; i<2; i++) {
            distance += Math.abs(zeroPosition[i] - NPosition[i]);
        }
        System.out.printf("1부터 %d까지 가는 최단거리 : %d", N, distance);
    }
}

2022/06/13 22:02

유로

# 1    3    13    31 -  -  -  - 4n^2 - 2n + 1
#   2    10    19    -  -  -  - 2 + 8(n-1)
#     8     8


def shortestDistance(N):
    if N < 4:
        return N - 1

    i = 0
    S = 1
    while N >= S:
        i += 1
        S = 4 * i ** 2 - 2 * i + 1

    i -= 1
    S = 4 * i ** 2 - 2 * i + 1
    dx = [-1, 0, 1, 0]
    dy = [0, -1, 0, 1]
    x, y = i, i

    m = N - S
    cm = 2 * i
    idx = 0
    for j in range(1, m + 1):
        x += dx[idx]
        y += dy[idx]
        if idx < 2 and j % cm == 0:
            idx += 1
        elif j == 3 * cm + 1:
            idx += 1
        #print(x, ' ', y)

    return abs(x) + abs(y)


N = int(input('숫자 N을 입력하세요: '))
print(shortestDistance(N))

2023/07/24 18:43

insperChoi

using System;

namespace solution
{
    class Program
    {
        static void Main(string[] args)
        {
            int N = 17;

            Console.WriteLine("\n   {0}  :  {1}", 1, shortestDistance(1));
            Console.WriteLine("\n   {0}  :  {1}", 3, shortestDistance(3));
            Console.WriteLine("\n   {0}  :  {1}", N, shortestDistance(N));
            Console.WriteLine("\n   {0}  :  {1}", 19, shortestDistance(19));
            Console.WriteLine("\n   {0}  :  {1}", 26, shortestDistance(26));
            Console.WriteLine("\n   {0}  :  {1}", 2550, shortestDistance(2550));
            Console.WriteLine("\n   {0}  :  {1}", 2573, shortestDistance(2573));
        }

        private static int shortestDistance(int N)
        {
            if (N < 4)
                return N - 1;

            int nq = 1;
            while (N >= (2 * nq + 1) * (2 * nq + 1))
                nq++;

            int mN = 4 * nq * nq - 3*nq + 1;
            int minD = Math.Abs(N - mN);
            for (int i = 0; i < 4; i++)
            {
                minD = Math.Min(minD, Math.Abs(N - mN));
                mN += 2 * nq;
            }
            return nq + minD;
        }
    }
}

2023/07/24 21:23

insperChoi

목록으로