Create TOC

2013년 8월 30일

Python/Spiral Array

원문

문제는 다음과 같습니다:

6 6

  0   1   2   3   4   5
 19  20  21  22  23   6
 18  31  32  33  24   7
 17  30  35  34  25   8
 16  29  28  27  26   9
 15  14  13  12  11  10

위처럼 6 6이라는 입력을 주면 6 X 6 매트릭스에 나선형 회전을 한 값을 출력해야 합니다.

풀이

#!/usr/bin/python
# -*- coding: utf-8 -*-

def fill_round(matrix, num, mx, my, base_x, base_y):
    ix = base_x
    iy = base_y

    # LR 진행
    for n in range(0, mx):
        matrix[iy][ix] = num
        num = num + 1
        ix = ix + 1
    ix = ix - 1
    mx = mx - 1

    # UD 진행
    iy = iy + 1
    for n in range(1, my):
        matrix[iy][ix] = num
        num = num + 1
        iy = iy + 1
    iy = iy - 1
    my = my - 1

    if my < 1:
        return

    # RL 진행
    ix = ix - 1
    for n in range(mx - 1, -1, -1):
        matrix[iy][ix] = num
        num = num + 1
        ix = ix - 1
    ix = ix + 1
    mx = mx - 1

    if mx < 1:
        return

    # DU 진행
    iy = iy - 1
    for n in range(my - 1, 0, -1):
        matrix[iy][ix] = num
        num = num + 1
        iy = iy - 1
    return num

def solution(x, y):
    if x < 0 or y < 0:
        return [[]]
    matrix = [[-1 for i in range(0, x)] for j in range(0, y)]

    num = 0
    w = x
    h = y
    i = 0
    while True:
        num = fill_round(matrix, num, w, h, i, i)
        i = i + 1
        w = w - 2
        h = h - 2
        if w <= 0 or h <= 0:
            break
    return matrix

matrix = solution(6, 6)
print '\n'.join([' '.join(['%3u' % n for n in m]) for m in matrix])

print ''

matrix = solution(9, 7)
print '\n'.join([' '.join(['%3d' % n for n in m]) for m in matrix])

결과

  0   1   2   3   4   5
 19  20  21  22  23   6
 18  31  32  33  24   7
 17  30  35  34  25   8
 16  29  28  27  26   9
 15  14  13  12  11  10

  0   1   2   3   4   5   6   7   8
 27  28  29  30  31  32  33  34   9
 26  47  48  49  50  51  52  35  10
 25  46  59  60  61  62  53  36  11
 24  45  58  57  56  55  54  37  12
 23  44  43  42  41  40  39  38  13
 22  21  20  19  18  17  16  15  14

Python/LCD Display

원문

한 친구가 방금 새 컴퓨터를 샀다. 그 친구가 지금까지 샀던 가장 강력한 컴퓨터는 공학용 전자 계산기였다. 그런데 그 친구는 새 컴퓨터의 모니터보다 공학용 계산기에 있는 LCD 디스플레이가 더 좋다며 크게 실망하고 말았다. 그 친구를 만족시킬 수 있도록 숫자를 LCD 디스플레이 방식으로 출력하는 프로그램을 만들어보자.

입력

입력 파일은 여러 줄로 구성되며 표시될 각각의 숫자마다 한 줄씩 입력된다. 각 줄에는 s와 n이라는 두개의 정수가 들어있으며 n은 출력될 숫자( 0<= n <= 99,999,999 ), s는 숫자를 표시하는 크기( 1<= s < 10 )를 의미한다. 0 이 두 개 입력된 줄이 있으면 입력이 종료되며 그 줄은 처리되지 않는다.

출력

입력 파일에서 지정한 숫자를 수평 방향은 '-' 기호를, 수직 방향은 '|'를 이용해서 LCD 디스플레이 형태로 출력한다. 각 숫자는 정확하게 s+2개의 열, 2s+3개의 행으로 구성된다. 마지막 숫자를 포함한 모든 숫자를 이루는 공백을 스페이스로 채워야 한다. 두 개의 숫자 사이에는 정확하게 한 열의 공백이 있어야 한다.

풀이

#!/usr/bin/python
# -*- coding: utf-8 -*-

q = {
    '1': {
        0: lambda c: [c, 0, 0],
        1: lambda c: [0, (c - 1), 1],
        2: lambda c: [c, 0, 0],
        3: lambda c: [0, (c - 1), 1],
        4: lambda c: [c, 0, 0],
    },
    '2': {
        0: lambda c: [1, (c - 2), 1],
        1: lambda c: [0, (c - 1), 1],
        2: lambda c: [1, (c - 2), 1],
        3: lambda c: [1, (c - 1), 0],
        4: lambda c: [1, (c - 2), 1],
    },
    '3': {
        0: lambda c: [1, (c - 2), 1],
        1: lambda c: [0, (c - 1), 1],
        2: lambda c: [1, (c - 2), 1],
        3: lambda c: [0, (c - 1), 1],
        4: lambda c: [1, (c - 2), 1],
    },
    '4': {
        0: lambda c: [c, 0, 0],
        1: lambda c: [1, (c - 2), 1],
        2: lambda c: [1, (c - 2), 1],
        3: lambda c: [0, (c - 1), 1],
        4: lambda c: [c, 0, 0],
    },
    '5': {
        0: lambda c: [1, (c - 2), 1],
        1: lambda c: [1, (c - 1), 0],
        2: lambda c: [1, (c - 2), 1],
        3: lambda c: [0, (c - 1), 1],
        4: lambda c: [1, (c - 2), 1],
    },
    '6': {
        0: lambda c: [1, (c - 2), 1],
        1: lambda c: [1, (c - 1), 0],
        2: lambda c: [1, (c - 2), 1],
        3: lambda c: [1, (c - 2), 1],
        4: lambda c: [1, (c - 2), 1],
    },
    '7': {
        0: lambda c: [1, (c - 2), 1],
        1: lambda c: [0, (c - 1), 1],
        2: lambda c: [c, 0, 0],
        3: lambda c: [0, (c - 1), 1],
        4: lambda c: [c, 0, 0],
    },
    '8': {
        0: lambda c: [1, (c - 2), 1],
        1: lambda c: [1, (c - 2), 1],
        2: lambda c: [1, (c - 2), 1],
        3: lambda c: [1, (c - 2), 1],
        4: lambda c: [1, (c - 2), 1],
    },
    '9': {
        0: lambda c: [1, (c - 2), 1],
        1: lambda c: [1, (c - 2), 1],
        2: lambda c: [1, (c - 2), 1],
        3: lambda c: [0, (c - 1), 1],
        4: lambda c: [1, (c - 2), 1],
    },
    '0': {
        0: lambda c: [1, (c - 2), 1],
        1: lambda c: [1, (c - 2), 1],
        2: lambda c: [c, 0, 0],
        3: lambda c: [1, (c - 2), 1],
        4: lambda c: [1, (c - 2), 1],
    },
}

def print_x(s, nums):
    if s <= 0:
        return
    c = s + 2
    r = s * 2 + 3

    print ''.join([' ' * q[n][0](c)[0] + '-' * q[n][0](c)[1] + ' ' * q[n][0](c)[2] + ' ' for n in nums])
    print '\n'.join([''.join(['|' * q[n][1](c)[0] + ' ' * q[n][1](c)[1] + '|' * q[n][1](c)[2] + ' ' for n in nums]) for i in xrange(0, r / 2 - 1)])
    print ''.join([' ' * q[n][2](c)[0] + '-' * q[n][2](c)[1] + ' ' * q[n][2](c)[2] + ' ' for n in nums])
    print '\n'.join([''.join(['|' * q[n][3](c)[0] + ' ' * q[n][3](c)[1] + '|' * q[n][3](c)[2] + ' ' for n in nums]) for i in xrange(0, r / 2 - 1)])
    print ''.join([' ' * q[n][4](c)[0] + '-' * q[n][4](c)[1] + ' ' * q[n][4](c)[2] + ' ' for n in nums])

print_x(2, '1234567890')
print ''
print_x(4, '1234567890')

실행 결과는 아래와 같다.

      --   --        --   --   --   --   --   --
   |    |    | |  | |    |       | |  | |  | |  |
   |    |    | |  | |    |       | |  | |  | |  |
      --   --   --   --   --        --   --
   | |       |    |    | |  |    | |  |    | |  |
   | |       |    |    | |  |    | |  |    | |  |
      --   --        --   --        --   --   --

        ----   ----          ----   ----   ----   ----   ----   ----
     |      |      | |    | |      |           | |    | |    | |    |
     |      |      | |    | |      |           | |    | |    | |    |
     |      |      | |    | |      |           | |    | |    | |    |
     |      |      | |    | |      |           | |    | |    | |    |
        ----   ----   ----   ----   ----          ----   ----
     | |           |      |      | |    |      | |    |      | |    |
     | |           |      |      | |    |      | |    |      | |    |
     | |           |      |      | |    |      | |    |      | |    |
     | |           |      |      | |    |      | |    |      | |    |
        ----   ----          ----   ----          ----   ----   ----

2013년 8월 14일

Debian/ssh 접속시 Google Authenticator 적용

Debian Sid에서 ssh 접속시 Google Authenticator를 적용하는 방법을 기술한다.

설치

$ sudo apt-get install libpam-google-authenticator

키 생성

$ google-authenticator

아래와 같은 질문에 y으로 대답하면 화면에 바코드가 출력된다.

Do you want authentication tokens to be time-based (y/n) y

바코드를 iPhone의 Google Authenticator 앱으로 찍어서 등록한다.

그 뒤에 질문들에는 y으로 대답한다.

Do you want me to update your "/사용자명/.google_authenticator" file (y/n) y

Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks (y/n) y

By default, tokens are good for 30 seconds and in order to compensate for
possible time-skew between the client and the server, we allow an extra
token before and after the current time. If you experience problems with poor
time synchronization, you can increase the window from its default
size of 1:30min to about 4min. Do you want to do so (y/n) y

If the computer that you are logging into isn't hardened against brute-force
login attempts, you can enable rate-limiting for the authentication module.
By default, this limits attackers to no more than 3 login attempts every 30s.
Do you want to enable rate-limiting (y/n) y

ssh 설정

/etc/pam.d/sshd 파일에 아래 내용을 추가한다.

auth       required     pam_google_authenticator.so

/etc/ssh/sshd_config 파일의 ChallengeResponseAuthentication 값을 yes로 수정한다.

ChallengeResponseAuthentication yes

ssh 를 재시작한다.

$ sudo /etc/init.d/sshd restart