야찌 게임은 다섯 개의 주사위를 써서 하는 게임으로, 13 라운드에 걸쳐서 주사위를 던지는 게임이다. 스코어 카드에는 13개의 카테고리가 있다. 각 라운드에서는 게임 참가자가 선택한 카테고리에 의해 점수를 딸 수 있는데, 이때 각 카테고리는 한 게임에 한 번만 쓸 수 있다. 13개의 카테고리에서는 다음과 같은 식으로 점수를 딴다.

 

  • 1 - 모든 1들의 합
  • 2 - 모든 2들의 합
  • 3 - 모든 3들의 합
  • 4 - 모든 4들의 합
  • 5 - 모든 5들의 합
  • 6 - 모든 6들의 합
  • 찬스 - 모든 숫자의 합
  • 같은 숫자 세 개 - 적어도 세 개가 같은 숫자일 때, 모든 숫자의 합
  • 같은 숫자 네 개 - 적어도 네 개가 같은 숫자일 때, 모든 숫자의 합
  • 같은 숫자 다섯 개 - 적어도 다섯 개가 같은 숫자일 때, 50점
  • 쇼트 스트레이트 - 네 개가 연속된 숫자일 때(1, 2, 3, 4 또는 2, 3, 4, 5 또는 3, 4, 5, 6), 25점
  • 롱 스트레이트 - 다섯 개가 연속된 숫자일 때(1, 2, 3, 4, 5 또는 2, 3, 4, 5, 6), 35점
  • 풀 하우스 - 세 개가 같은 숫자이고 나머지 두 개가 같은 숫자일 때(예를 들면 2, 2, 5, 5, 5), 40점

마지막 여섯 개의 카테고리는 조건이 만족되지 않으면 0점으로 처리한다.

 

이 게임의 총점은 13개의 카테고리 각각의 점수를 모두 더한 점수며 첫번째부터 여섯 번째까지의 카테고리 총합이 63점 이상이면 보너스 점수 35점이 추가된다.

 

여러 라운드가 주어졌을 때 가능한 최고 점수를 계산하라.

 

입력

각 줄에는 1이상 6 이하의 정수가 다섯 개 있으며 이는 각 라운드에 나온 주사위 다섯개의 숫자를 나타낸다. 매 게임마다 13줄이 입력되며 입력 데이터에 들어있는 게임 횟수에는 제한이 없다.

 

출력

한 줄에 15개의 숫자를 출력한다. 15개의 숫자는 각 카테고리별 점수(위에 나와 잇는 순서대로)와 보너스 점수(0 또는 35), 그리고 총점이다. 여러 방식으로 카테고리를 적용했을 때 같은 점수가 나오면 그 중 아무 결과나 출력해도 된다.

 

예제

아래처럼 입력에 대한 출력이 나온다.

 

해설

해가 지나도록 질질 끌었던 문제다. 룰 적용에 대한 모든 조합을 구하고, 각 조합에 대한 점수를 계산해서 최고 점수를 찾는 것이다. 다만 전체 조합의 수가 13! 이기 때문에 시간이 어마어마하게 걸린다. 이에 대한 해답으로 0점인 룰은 제외해서 조합의 수를 줄이니 어찌어찌 수 분만에 풀이가 가능했다. 

 

'같은 숫자 세 개'와 '같은 숫자 네 개' 룰의 점수 계산이 헷갈릴 수 있다. 조건이 맞을 때, 숫자 5개의 점수를 모두 더하는 것이다. 처음에는 3개, 4개만 더했더니 자꾸 답이 틀렸는데, 이 부분을 유의하면 좋을 것 같다.

# Quiz 0016, Yahtzee
# written by badsaram

import sys

class Yahtzee(object):
    def __init__(self):
        self.dice_try = []
        self.dice_try_score = []
        self.combination = [0] * 13
        self.combination_count = 0
        self.max_try_count = 13
        self.max_pattern_count = 13
        self.max_combination_count = 0
        self.max_score = 0
        self.max_score_combination = [0] * 13

    def input(self):
        for i in range(0, self.max_try_count):
            str = input()
            tokens = str.split(' ')

            if (len(tokens) > 5):
                print("wrong input number.")
                sys.exit(-1)

            int_tokens = []
            for token in tokens:
                if (int(token) > 6):
                    print("wrong input number.")
                    sys.exit(-1)
                    
                int_tokens.append(int(token))

            self.dice_try.append(int_tokens)

    def test_input1(self):
        for i in range(0, self.max_try_count):
            self.dice_try.append([1, 2, 3, 4, 5])

    def test_input2(self):
        self.dice_try.append([1, 1, 1, 1, 1])
        self.dice_try.append([6, 6, 6, 6, 6])
        self.dice_try.append([6, 6, 6, 1, 1])
        self.dice_try.append([1, 1, 1, 2, 2])
        self.dice_try.append([1, 1, 1, 2, 3])
        self.dice_try.append([1, 2, 3, 4, 5])
        self.dice_try.append([1, 2, 3, 4, 6])
        self.dice_try.append([6, 1, 2, 6, 6])
        self.dice_try.append([1, 4, 5, 5, 5])
        self.dice_try.append([5, 5, 5, 5, 6])
        self.dice_try.append([4, 4, 4, 5, 6])
        self.dice_try.append([3, 1, 3, 6, 3])
        self.dice_try.append([2, 2, 2, 4, 6])

    def calc(self):
        for i in range(0, len(self.dice_try)):
            self.calc_pattern(self.dice_try[i])

        # brutal force
        self.traverse(0)

        # fill empty item
        for i in range(0, len(self.max_score_combination)):
            if (self.max_score_combination[i] == 0):
                for j in range(1, self.max_pattern_count + 1):
                    if (j in self.max_score_combination):
                        pass
                    else:
                        self.max_score_combination[i] = j
                        break

        # print answer
        #print(self.max_score_combination)
        answer = [0] * 15
        for i in range(0, len(self.max_score_combination)):
            pattern = self.max_score_combination[i]
            score = self.dice_try_score[i][pattern]
            answer[pattern - 1] = score

        if (sum(answer[0:6]) >= 63):
            answer[13] = 35
    
        answer[14] = self.max_score

        print(answer)           

    def calc_pattern(self, dices):
        switch = {
            1 : self.calc_pattern_1(dices),
            2 : self.calc_pattern_2(dices),
            3 : self.calc_pattern_3(dices),
            4 : self.calc_pattern_4(dices),
            5 : self.calc_pattern_5(dices),
            6 : self.calc_pattern_6(dices),
            7 : self.calc_pattern_7(dices),
            8 : self.calc_pattern_8(dices),
            9 : self.calc_pattern_9(dices),
            10 : self.calc_pattern_10(dices),
            11 : self.calc_pattern_11(dices),
            12 : self.calc_pattern_12(dices),
            13 : self.calc_pattern_13(dices)
        }

        item = []
        item.append(dices)
        for i in range(1, 14):
            item.append(switch.get(i))

        self.dice_try_score.append(item)

    def calc_pattern_1(self, dices):
        return dices.count(1) * 1
    
    def calc_pattern_2(self, dices):
        return dices.count(2) * 2
    
    def calc_pattern_3(self, dices):
        return dices.count(3) * 3
    
    def calc_pattern_4(self, dices):
        return dices.count(4) * 4
    
    def calc_pattern_5(self, dices):
        return dices.count(5) * 5
    
    def calc_pattern_6(self, dices):
        return dices.count(6) * 6
    
    def calc_pattern_7(self, dices):
        return sum(dices)
    
    def calc_pattern_8(self, dices):
        for i in range(1, 7):
            if (dices.count(i) >= 3):
                return sum(dices)
            
        return 0
    
    def calc_pattern_9(self, dices):
        for i in range(1, 7):
            if (dices.count(i) >= 4):
                return sum(dices)

        return 0

    def calc_pattern_10(self, dices):
        sum = 0

        for i in range(1, 7):
            if (dices.count(i) >= 5):
                sum = 50
                break

        return sum
    
    def calc_pattern_11(self, dices):
        sum = 0

        if (1 in dices) and (2 in dices) and (3 in dices) and (4 in dices):
            sum = 25

        if (2 in dices) and (3 in dices) and (4 in dices) and (5 in dices):
            sum = 25

        if (3 in dices) and (4 in dices) and (5 in dices) and (6 in dices):
            sum = 25

        return sum
    
    def calc_pattern_12(self, dices):
        sum = 35

        if (1 in dices) and (2 in dices) and (3 in dices) and (4 in dices) and (5 in dices):
            sum = 35

        if (2 in dices) and (3 in dices) and (4 in dices) and (5 in dices) and (6 in dices):
            sum = 35

        return sum
    
    def calc_pattern_13(self, dices):
        sum = 0
        meet2 = False
        meet3 = False

        for i in range(1, 7):
            if (dices.count(i) == 2):
                meet2 = True

            elif (dices.count(i) == 3):
                meet3 = True
            
        if ((meet2 == True) and (meet3 == True)):
            sum = 40
        
        return sum
    
    def calc_combination(self, combination):
        total_score = 0
        pattern_1_6_score = 0

        for i in range (0, self.max_try_count):
            pattern = combination[i]
            if (pattern != 0):
                total_score = total_score + self.dice_try_score[i][pattern]
            if (pattern in range(1, 7)): # 1 
                pattern_1_6_score = pattern_1_6_score + self.dice_try_score[i][pattern]

        if (pattern_1_6_score >= 63):
            total_score = total_score + 35  # if score of pattern 1˜6 is greater than 63, bonus 35 is added 

        if (total_score > self.max_score):
            self.max_score = total_score
            self.max_score_combination[:] = combination

        return total_score
    
    def count_combination_length(self, combination):
        return len(list(filter(lambda x: x != 0, combination)))

    def traverse(self, depth):
        if (depth >= self.max_try_count): # depth >= 13
            return

        for i in range(1, self.max_try_count + 1):
            if (i in self.combination):
                continue

            if (self.dice_try_score[depth][i] == 0):
                continue

            self.combination[depth] = i

            if (depth == (self.max_try_count - 1)): # depth == 12
                total_score = self.calc_combination(self.combination)
                self.max_combination_count = self.max_try_count # 13

                self.combination_count = self.combination_count + 1
                #print("%10d | %s | %d" % (self.combination_count, self.combination, total_score))

            self.traverse(depth + 1)
            self.combination[depth] = 0

        combination_len = self.count_combination_length(self.combination)
        if (combination_len >= self.max_combination_count):
            total_score = self.calc_combination(self.combination)
            self.max_combination_count = combination_len

            self.combination_count = self.combination_count + 1
            #print("%10d | %s | %d" % (self.combination_count, self.combination, total_score))

if __name__ == '__main__':
    obj = Yahtzee()

    obj.input()
    #obj.test_input1()
    #obj.test_input2()
    obj.calc()

윈도우 파워쉘(PowerShell) 사용 중 스크립트 파일(.ps1)을 실행하면 UnauthorizedAccess 오류가 발생하면서 스크립트가 실행 안될 때가 있다. 평소에 쓰던 파이참(PyCharm) 대신 멋있게 콘솔창으로 파이썬(Python)으로 파이썬 가상 환경으로 만들려고 했을 때 접한 오류다.

 

activate.ps1을 실행하려고 했더니 위처럼 UnauthorizedAccess 오류가 발생한다. 

파워쉘에서 보안을 위해 비인가 스크립트의 실행을 막아놔서 그렇다. 그럼 이걸 풀어주면 되겠지?

아래처럼 해주면 해결 할 수 있다.

1. 파워쉘을 관리자 모드로 실행한다.

2. Set-ExecutionPolicy unrestricted

이제 다시 문제가 된 스크립트를 실행해보면, 잘 실행되는 것을 볼 수 있다.

인증 제한을 푼 것이니, 아무래도 보안에는 좀 더 안 좋아졌을 것이다. 하지만 일은 해야 하니 어쩔 수 없다.

 

현재 실행정책을 보려면 Get-ExecutionPolicy 명령으로 볼 수 있다. 필요할 때 활용하자.

'Windows' 카테고리의 다른 글

파워쉘(PowerShell) 익히기  (0) 2023.01.18
Visual Studio 2022 + QT 개발 환경 셋업  (2) 2022.08.10

ACM ICPC에 출전하고 싶다면 점수 계산법을 알아야 한다. 경시 대회에 참가한 팀의 순위는 우선 푼 문제의 개수가 많은 순으로, 그 다음으로는 시간 벌점(penalty time)이 적은 순으로 매겨진다. 이 둘을 모두 고려했는데도 동점 팀이 둘 이상이면 팀 멤버 수가 적은 쪽이 더 높은 순위를 차지할 수 있다. 

 

제출된 풀이 가운데 정답으로 판정받은 것이 하나라도 있으면 그 문제는 해결된 것으로 인정된다. 시간 벌점은 해당 문제에 대한 첫번째 정답이 제출될 때까지 걸린 시간으로 계산되며 정답이 나오기 전까지 제출된 오답이 있으면 한 개에 20분씩의 시간 벌점이 추가된다. 풀리지 않은 문제에 대해서는 시간 벌점이 전혀 적용되지 않는다.

 

입력

각 입력은 심사 큐의 스냅샷으로 구성되는데, 여기서는 1번부터 9번까지의 문제를 푸는 1번부터 100번까지의 경시 대회 참가 팀으로부터 입력된 내용이 들어있다. 각 줄은 세 개의 수와 경시 대회 문제 시간 L 형식의 글자 하나로 구성된다. L은 C, I, R, U 또는 E 라는 값을 가질 수 있는데 이 글자들은 각각 Correct(정답), Incorrect(오답), Clarification Request(확인 요청), Unjudged(미심사), Erroneous submission(제출 오류)을 의미한다. 마지막 세 개의 케이스는 점수에 영향을 미치치 않는다. 입력은 제출된 순서대로 입력된다.

 

출력

각 테스트 케이스에 대해 앞에서 설명한 순서에 의해 정렬된 점수표가 출력된다. 출력되는 각 줄에는 참가팀 번호, 그 팀이 푼 문제, 누적된 시간 벌점이 출력된다. 모든 경시 대회 참가 팀이 풀이를 제출하는 것은 아니므로 실제로 풀이를 제출한 팀의 결과만 표시한다. 그리고 두 개의 서로 다른 케이스에 대한 출력은 빈 줄로 구분한다.

 

예제


해설

문제를 묘하게 이해하기 힘들었다. "동점 팀이 둘 이상이면 팀 멤버 수가 적은 쪽이 더 큰 순위를 차지할 수 있다" 라는데 입력 어디에도 팀 멤버수가 정의되지 않았다. 이건 무시했다. 점수 집계를 파이썬의 딕셔너리를 사용하다보니, 딕셔너리의 정렬 방법에 대해서 공부가 필요했다. 다른 것은 평이하니 소스 코드를 보면 쉽게 이해가 될 것이다.

# Quiz 0015, Contest Score Board
# written by badsaram

import sys

class CScoreBoard(object):
    def __init__(self):
        self.history_board = []
        self.score_board = {}

    def input(self):
        ret = True

        while True:
            input_str = input()

            if (input_str == ""):
                ret = False
                break

            tokens = input_str.split(" ")

            try:
                team_id     = int(tokens[0])
                quiz_num    = int(tokens[1])
                proc_time   = int(tokens[2])
                result_type = tokens[3].strip().upper()

                if ((team_id <= 0) or (team_id > 100) or (quiz_num <= 0) or (quiz_num >= 10)):
                    ret = False
                    break

                self.history_board.append([team_id, quiz_num, proc_time, result_type])
            except:
                ret = False
                break

        return ret

    def test_input(self):
        self.history_board.append([1, 2, 10, 'I'])
        self.history_board.append([3, 1, 11, 'C'])
        self.history_board.append([1, 2, 19, 'R'])
        self.history_board.append([1, 2, 21, 'C'])
        self.history_board.append([1, 1, 25, 'C'])
        self.history_board.append([9, 1, 10, 'C'])
        self.history_board.append([9, 2, 30, 'C'])
        self.history_board.append([9, 3, 40, 'C'])
        self.history_board.append([4, 1, 10, 'C'])
        self.history_board.append([4, 2, 20, 'C'])

    def run(self):
        for history in self.history_board:
            if ((history[0] in self.score_board) == False):
                self.score_board[history[0]] = [ [], 0 ]

            if (history[3] == 'I'):
                self.score_board[history[0]][1] += 20
            elif (history[3] == 'C'):
                if ((history[1] in self.score_board[history[0]][0]) == False):
                    self.score_board[history[0]][0].append(history[1])

                self.score_board[history[0]][1] += history[2]
            else:
                pass

        d1 = sorted(self.score_board.items(), key = lambda x : (-len((x[1])[0]), (x[1])[1]))

        for item in d1:
            print("%d %d %d" % (item[0], len(item[1][0]), item[1][1]))

if __name__ == '__main__':
    obj = CScoreBoard()

    obj.input()
    #obj.test_input()
    obj.run()

헝가리 출신의 수학자 폴 에르되시(Paul Erdős, 1913-1996)는 20세기의 가장 유명한 수학자 가운데 하나로 꼽힌다. 에르되시와 함꼐 논문을 쓴 경험이 있는 수학자들도 존경을 받을 정도니 그의 명성을 짐작할 수 있을 것이다.

 

하지만 불행하게도 모든 사람들이 그와 함께 논문을 쓸 기회를 얻을 수 있는 것은 아니었기 때문에 에르되시와 함께 논문을 썼던 사람과 논문을 같이 쓰는 정도로 만족해야 한다. 이런 이유로 인해 에르되시 수라는 것이 생겼다. 에르되시와 함께 논문을 쓴 사람의 에르되시 수는 1이다. 에르되시와 직접 함께 논문을 쓰지 않았지만 에르되시 수가 1인 사람과 함께 논문을 쓴 적이 있는 사람의 에르되시 수는 2다.

 

주어진 논문과 논문 저자를 바탕으로 에르되시 수를 계산하는 프로그램을 만들어야 한다.

 

입력

입력의 첫번째 행에는 P와 N이라는 자연수 두 개가 입력된다. 그 다음 줄에는 논문 데이터베이스가 입력되며 각 논문마다 한 줄씩 저자에 대한 정보가 입력된다. 각 논문에 대한 정보는 다음과 같은 식으로 기술된다.

 

   Smith M.N., Martin, G., Erdos, P.: Newtonian forms of prime factors matrices

 

ő 같은 움라우트는 편의장 'o'로 표기한다. P개의 논문 정보 밑에는 각각 하나씩의 이름이 들어있는 N개의 행이 입력된다. 이름은 다음과 같은 형식으로 입력된다. 이름은 다음과 같은 형식으로 입력된다.

 

   Martin, G.

 

출력

입력된 모든 이름에 대해 이름과 에르되시 수를 출력한다. 저자의 이름은 입력된 순서대로 출력된다. 에르되시 수는 시나리오에 들어있는 논문 데이터베이스를 기반으로 계산한다. 데이터베이스에 있는 논문으로 볼 때 에르되시와 전혀 관계가 없는 저자들의 에르되시 수는 "infinity"로 출력한다.

 

예제


해설

논문 데이터베이스에서 저자들의 이름을 추출하는 것이 제일 어려웠다. 문자열 처리는 늘 골치가 아프다. 우선 에르되시와 1촌인 사람을 먼저 구한다. 그리고 2촌, 3촌 이런 식으로 구해가면 간단히 해결!

# Quiz 0014, Erdos Numbers
# written by badsaram

import sys

class ErdosNumbers(object):
    def __init__(self):
        self.num_thesis = 0
        self.num_author = 0
        self.num_query = 0
        self.thesis_list = []
        self.author_list = []
        self.query_list = []

    def input(self):
        ret = True

        str = input()
        tokens = str.split()

        try:
            self.num_thesis = int(tokens[0])
            self.num_author = int(tokens[1])
        except:
            ret = False

        for i in range(self.num_thesis):
            self.thesis_list.append(input())

        for i in range(self.num_author):
            self.query_list.append(input())

        return ret

    def test_input(self):
        self.num_thesis = 4
        self.num_query = 3

        self.thesis_list.append("Smith, M.N., Martin, G., Erdos, P.: Newtonian forms of prime factor matrix")
        self.thesis_list.append("Erdos, P., Reisig, W.: Stuttering in patri nets")
        self.thesis_list.append("Smith, M.N., Chen, X.: First oder derivates in structured programming")
        self.thesis_list.append("Jablonski, T., Hsueh, Z.: Selfstabilizing data structures")

        self.query_list.append("Smith, M.N.")
        self.query_list.append("Hsueh, Z.")
        self.query_list.append("Chen, X.")

    def run(self):
        for thesis_title in self.thesis_list:
            input_str = thesis_title.split(':')

            # separate authors from thesis title
            input_str = input_str[0].split(".,")
            for word in input_str:
                word = word.strip()
                if word[-1] != '.':
                    word += '.'

                try:
                    self.author_list.index([word, 0])
                except:
                    self.author_list.append([word, 0])

        # find tier-1
        for i in range(len(self.author_list)):
            for thesis in self.thesis_list:
                if (self.isTogether(self.author_list[i][0], "Erdos, P.") == True):
                    self.author_list[i][1] = 1

        # find tier-2, 3
        n = 1
        while True:
            if ((self.isCompleted() == True) or (n >= len(self.author_list))):
                break

            author_zero_indexes = self.getAuthorFilterIndex(0)
            author_n_indexes = self.getAuthorFilterIndex(n)

            for author_zero_index in author_zero_indexes:
                for author_n_index in author_n_indexes:
                    if (self.isTogether(self.author_list[author_zero_index][0],
                                        self.author_list[author_n_index][0]) == True):
                        self.author_list[author_zero_index][1] = n + 1

            n += 1

        for query in self.query_list:
            for i in range(len(self.author_list)):
                if (query == self.author_list[i][0]):
                    print(query + " ", end = "")
                    if (self.author_list[i][1] ==  0):
                        print("infinity")
                    else:
                        print(str(self.author_list[i][1]))


    def isCompleted(self):
        ret = True

        if (len(self.author_list) > 0):
            for author in self.author_list:
                if (author[1] == 0):
                    ret = False
                    break
        else:
            ret = False

        return ret

    def isTogether(self, author1, author2):
        ret = False

        for thesis in self.thesis_list:
            try:
                if ((thesis.index(author1) >= 0) and
                    (thesis.index(author2) >= 0)):
                    ret = True
                    break
            except:
                ret = False

        return ret

    def getAuthorFilterIndex(self, n):
        list = []

        for i in range(len(self.author_list)):
            if (self.author_list[i][1] == n):
                list.append(i)

        return list

if __name__ == '__main__':
    obj = ErdosNumbers()

    obj.input()
    #obj.test_input()
    obj.run()

 

빅 시티(Big)에는 카지노가 여러 개 있다. 그 중 한 카지노에는 딜러가 속임수를 씁니다. 그녀는 몇 가지 카드 섞는 법을 완벽하게 익혔는데, 그 카드 섞는 법을 사용하면 언제든지 카드를 마음대로 재배치할 수 있습니다. 간단한 예로 '밑장' 섞기를 들 수 있는데, 맨 아래 있는 카드를 꺼내서 맨 위로 올려놓는 방법이다. 그 딜러는 이런 다양한 섞기 방법을 조합해서 원하는 순서대로 카드를 쌓아 올릴 수 있습니다.

 

카지노의 보안 관리자가 그 딜러를 감시하기 위해 당신을 고용했습니다. 딜러가 섞은 모든 카드 순서가 주어지며 사용된 섞기 방법도 제공됩니다. 이런 정보가 주어졌을 때 몇번의 섞기 작업이 진행된 후의 카드 순서를 예측해야 합니다.

 

카드 한 벌은 52개의 카드로 구성되며 네 개의 무늬마다 13장의 카드가 있습니다. 카드의 값(숫자)은 2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, King, Ace 중 하나입니다. 그리고 무늬는 Clubs, Diamonds, Hearts, Spades 가운데 하나입니다. 각 카드는 <값> of <무늬>와 같은 식으로 값과 무늬를 써서 유일하게 식별할 수 있습니다. 예를 들면 "9 of Hearts", "King of Spades" 같은 식으로 표현할 수 있습니다. 관례에 따라 새 카드는 우선 무늬를 기준으로 알파벳 순으로, 그리고 위에 나와 있는 값 순서대로 정렬됩니다.

 

입력

입력은 딜러가 알고 있는 섞이 방법의 개수인 100이하의 정수 n으로 시작됩니다. 그 다음 줄에는 52개의 정수가 n세트 나오는데 각 세트에는 1에서 52까지의 모든 정수가 들어있습니다. 52개의 정수로 구성된 각 세트내에서 j 위치에 i가 있다는 것은 패에서 i번째 카드를 j번째 위치로 이동시킨다는 것을 의미합니다.

 

그 뒤에는 각각 1 이상 n 이하의 정수 k가 들어있는 행이 여러 개 뒤따릅니다. 입력된 정수 k는 딜러가 k번째 섞기 방법을 썼다는 것을 나타냅니다.

 

출력

딜러가 위에 기술되어 있는 대로 정렬된 새로운 패를 가지고 시작한다고 가정하고 섞기가 모두 끝난 후에 새로운 순서에 따라서 카드의 이름을 출력합니다. 두 개의 서로 다른 케이스에 대한 출력 결과는 빈 줄로 구분합니다.

 

예제
2
2 1 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 52 51
52 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 1
King of Spades
2 of Clubs
4 of Clubs
5 of Clubs
6 of Clubs
7 of Clubs
8 of Clubs
9 of Clubs
10 of Clubs
Jack of Clubs
Queen of Clubs
King of Clubs
Ace of Clubs
2 of Diamonds
3 of Diamonds
4 of Diamonds
5 of Diamonds
6 of Diamonds
7 of Diamonds
8 of Diamonds
9 of Diamonds
10 of Diamonds
Jack of Diamonds
Queen of Diamonds
King of Diamonds
Ace of Diamonds
2 of Hearts
3 of Hearts
4 of Hearts
5 of Hearts
6 of Hearts
7 of Hearts
8 of Hearts
9 of Hearts
10 of Hearts
Jack of Hearts
Queen of Hearts
King of Hearts
Ace of Hearts
2 of Spades
3 of Spades
4 of Spades
5 of Spades
6 of Spades
7 of Spades
8 of Spades
9 of Spades
10 of Spades
Jack of Spades
Queen of Spades
Ace of Spades
3 of Clubs

해설

문제가 무슨 말을 하는지 몰라서 고생을 했다. 한국말로 써 있는데 한국 말인 것인지 이해가 안됐다. 그러다 1부터 52까지 써 있는 것이 새 카드의 덱(deck)이고, 입력 받은 case의 52개의 숫자와의 Diff로 섞기 방법을 계산하면 의외로 쉬운 문제라는 것을 알게 됐다. 이렇게 Diff로 얻어진 카드의 이동 순서를 기록해두고, 새 카드의(deck)에 순차적으로 적용하면 됐던 평이한 문제였다. 

# Quiz 0013, Stack'em Up
# written by badsaram

import sys

class stackemup(object):
    def __init__(self):
        self.shuffle_list = []
        self.num_cases = 0

    def input(self, testflag):

        if (testflag == True):
            self.num_cases = 2
        else:
            str = input() # input number of test caess
            self.num_cases = int(str)

        for i in range(self.num_cases):
            if (testflag == True):
                if (i == 0):
                    str = "2 1 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 52 51"
                else:
                    str = "52 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 1"
            else:
                str = input()
        
            shf = shuffle()
            ret = shf.input_case(str)
            if (ret == True):
                self.shuffle_list.append(shf)
            else:
                return False

        return True

    def calc(self):
        ret = False

        org_str = "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52"
        dck = deck()
        ret = dck.input_deck(org_str)

        if (len(self.shuffle_list) != 0):
            tokens = org_str.split(' ')

            for shuffle_case in self.shuffle_list:
                dck.shuffle_apply(shuffle_case)

            dck.print_deck()

            ret = True
        else:
            ret = False

        return ret

class deck(object):
    def __init__(self):
        self.deck_org   = ""
        self.deck_calc  = []

    def input_deck(self, str):
        self.deck_org = str

        tokens = self.deck_org.split(' ')
        for i in range(len(tokens)):
            if (tokens[i] != ''):
                self.deck_calc.append(int(tokens[i]))

    def shuffle_apply(self, shf):
        shuffles = shf.get_shuffle()
        deck_copy = self.deck_calc.copy()

        for shuffle in shuffles:
            deck_copy[shuffle[0]] = self.deck_calc[shuffle[1]]

        self.deck_calc = deck_copy

    def print_deck(self):
        if (len(self.deck_calc) != 0):
            for i in range(len(self.deck_calc)):
                self.print_card(self.deck_calc[i])

    def print_card(self, card_num):
        mark = int((card_num - 1) / 13)
        card = int((card_num - 1) % 13)

        mark_string = [ "Clubs", "Diamonds", "Hearts", "Spades" ]
        card_string = [ "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King", "Ace"]

        print("%s of %s" % (card_string[card], mark_string[mark]))

class shuffle(object):
    def __init__(self):
        self.shuffle_org  = ""
        self.shuffle_calc = []

    def input_case(self, str):
        self.shuffle_org = str

        tokens = self.shuffle_org.split(' ')
        if (len(tokens) != 52):
            return False

        for i in range(len(tokens)):
            if ((tokens[i] != '') and (int(tokens[i]) != (i + 1))):
                self.shuffle_calc.append([i, int(tokens[i]) - 1])

        return True

    def print_case(self):
        if (self.shuffle_org != ""):
            tokens = self.shuffle_org.split(' ')

            for i in range(len(tokens)):
                if (tokens[i] != ''):
                    self.print_card(int(tokens[i]))

    def print_card(self, card_num):
        mark = int((card_num - 1) / 13)
        card = int((card_num - 1) % 13)

        mark_string = [ "Clubs", "Diamonds", "Hearts", "Spades" ]
        card_string = [ "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King", "Ace"]

        print("%s of %s" % (card_string[card], mark_string[mark]))

    def print_diff(self):
        if (len(self.shuffle_calc) != 0):
            for diff in self.shuffle_calc:
                print("%d %d" % (diff[0], diff[1]))

    def get_shuffle(self):
        return self.shuffle_calc

if __name__ == '__main__':
    obj = stackemup()

    obj.input(True)
    obj.calc()

윈도우 11을 사용하면서 문득 구닥다리 명령어 프롬프트(cmd.exe)를 바꾸고 싶어졌습니다.

명령어 프롬프트(cmd.exe)를 쓰는 경우는 주로 Git을 이용할 때였는데, 구닥다리 배치파일(.bat)로 뭔가를 하려니 하려고 하는 바를 맘껏하기 힘들었거든요. 그래서 Git Bash를 쓰곤 했는데, 아무래도 윈도우에서는 윈도우에 맞는 방법을 찾아야하지 않을까요?

▲ 애증의 명령어 프롬프트(cmd.exe)

 

보아하니 파워쉘(PowerShell)이라고 강화된 명령어 프롬프트가 있다고 합니다. 바로 설치 들어갑니다.

Microsoft Store를 실행한 후 powershell 로 검색하고 설치합니다. 

▲ 이것이 바로 명령어 프롬프트 改, PowerShell

 

실행한 모습은 기존의 명령어 프롬프트와 별차이는 없습니다. 까만바탕에 하얀 글씨, 프롬프트 깜빡깜빡.

엔지니어의 뽕을 자극하는 CLI 화면 되겠습니다.

▲ 파워쉘(PowerShell) 실행 화면. 기존 것과 별 차이는 없다.

 

문제는 몇가지 명령어를 쳐 본 뒤에 발견했습니다. 

예로 dir 같은 명령어는 실행됐지만  dir /w 같은 명령어를 치면 알아 먹지 못한다고 나옵니다.

 

기존 명령어 프롬프트(cmd.exe)에서 파워쉘(PowerShell)을 처음 접하는 사람들을 위해서, 자주 쓰는 명령어를 적어봅니다. 기존 명령어를 이미 알고 있는 분들을 대상으로 해서, 파워쉘(PowerShell) 오면서 바뀐 부분만 간단하게 설명합니다.

※ 사실 기반 명령어는 다 바뀌었는데, alias를 통해서 기존 명령어 프롬프트(cmd.exe)과 같이 쓸 수 있는 것입니다. 정공법은 alias를 활용해서, 자주 쓰는 명령을 등록해서 사용하는 겁니다.

No 파워쉘(PowerShell) 명령어 기능
1 dir 디렉토리 보기
2 ls
3 Get-ChildItem
4 dir | format-wide 디렉토리 넓게 보기 
5 dir -force | ? { $_.Attributes –band [IO.FileAttributes]::Hidden } 숨김 파일만 보기
6 pwd 현재 디렉토리 보기

 

위 표를 추가하면서 알게 된 것이 있습니다. 바로 기존 명령어 프롬프트를 이용하는 방법이죠.

cmd /r [실행하고 싶은 명령어]

예를 들어 dir /a 를 하고 싶은데, 도저히 위의 복잡한 명령어를 치기 싫다? 그렇다면..

cmd /r dir /a

라고 하면 되는 겁니다. 그럼 이만 총총.. 이미 이 글을 쓸 때의 초심을 잊은지 오래입니다.

 

(그럼 명령어 프롬프트를 쓰는 것과 뭐가 다르죠?)

+ Recent posts