연습문제 – ASCII Art of N

홀수 정수가 입력되면, 그 숫자가 지정하는 크기의 N을 출력한다. 만약 값이 1이라면 “N” 하나를 출력하지만, 3이라면, “N”이라는 글자로 N 모양의 아스키코드 아트를 출력한다.

N N
NNN
N N

이렇게 동작하는 프로그램을 작성하라. 단, 입력은 항상 유효하다고 가정한다.

접근

일단 문제에서는 입력이 항상 유효하다고 가정했지만, 항상 홀수가 되도록 변조해서 처리하겠다. N을 아스키아트로 출력하는데 필요한 정보들을 생각해보자. 입력된 홀수 정수값이 n 이라 가정하면

  1.  출력될 전체 아스키아트의 폭과 높이는 모두 n 이다.
  2. 맨 첫줄과 끝줄은 꺾이는 지점과 끝점을 표현하므로 양 끝에 N이 들어간다.
  3. 그외의 줄에는 2번째칸부터 순차적으로 N이 하나씩 더 붙는다. i 행( i = 0, 1, 2,…. n-1)에서의 가운데 N의 위치는 i +1 번째 칸이다. (여기서 칸은 1, 2, 3으로 센다.)

 

풀이 1

첫번째 풀이 방식은 순차적으로 한 줄씩 출력하는 것이다. 첫줄과 마지막 줄은 "N" + (n-2)개의 공백 + "N"으로 출력한다. 그리고 그 이후부터는 가운데 “N”의 위치를 잡는다. 1…n-2 번줄에 대해서는 따라서, “N” + (i-1)개 공백 + “N” + (n-1+i)개 공백 + “N”이 된다.

def solution1():
  n = int(input()) // 2 * 2 + 1
  print('N' + ' ' * (n-2) + 'N')
  for i in range(1, n-1):
    print('N' + ' ' * (i-1) + 'N' + ' ' * (n-2-i) + 'N')
  print('N' + ' ' * (n-2) + 'N')

코드가 정직하긴한데, 너무 정직하고 깔끔하지 못한 거 같다. 좀 개선해보자.

풀이 2

두 번째 풀이는 버퍼를 이용하는 것이다. 여기서 2차원 그리드에 대한 버퍼를 사용하기 때문에 주로 리스트의 리스트 즉 2차원 배열을 많이 사용하는데, 개인적으로 2차원 배열을 별로 좋아하지 않기 때문에 1차원 리스트로 해결하고자 한다.

  1. 버퍼의 크기는 n * n 이며, 초기값은 모두 공백문자로 채워진다.
  2. N의 왼쪽 세로선을 생각해보자. 세로선상의 칸들은 그리드의 폭(n)만큼 떨어져있다. 따라서 0부터 n씩 증가하며 이 곳의 칸을 ‘N’으로 대체한다.
  3. N의 오른쪽 세로선 역시, n-1을 초기값으로 하며 n씩 증가하는 인덱스로 참조된다.
  4. 대각선을 보면 n+1을 첫 위치로 하면서, 한줄에 한칸씩 오른쪽으로 밀리기 때문에 간격이 n+1이 된다.
  5. 버퍼상에 필요한 곳에 문자 N을 써 넣고 멀티라인 스트링으로 결합하면 끝
def process(n):
  buffer = [' '] * (n*n)
  buffer[0::n] = ['N'] * n
  buffer[n-1::n] = ['N'] * n
  buffer[n+1::n+1] = ['N'] * (n-1)
  return '\n'.join(''.join(buffer[i*n:i*n+n]) for i in range(n))

def solve():
  n = int(input()) // 2 * 2 + 1
  print(process(n))