Post

BeakJoon 4344. 평균은 넘겠지 - 평균 이상 학생 비율 계산

짧게 코드 작성하는 법 고민하자

문제 URL: https://www.acmicpc.net/problem/4836

😒문제


창영이는 요즘 춤을 배우고 있다. 창영이는 다음과 같은 규칙을 따라서 춤을 추어야 한다.

  1. dip은 jiggle을 춘 다음이나 다다음, 또는 twirl을 추기 전에 출 수 있다. 예를 들면 다음과 같다.
    • …jiggle dip…
    • …jiggle stomp dip…
    • …dip twirl…
  2. 모든 춤은 clap stomp clap으로 끝나야 한다.
  3. 만약 twirl을 췄다면, hop도 춰야한다.
  4. jiggle로 춤을 시작할 수 없다.
  5. 반드시 dip을 춰야 한다.

창영이가 춘 춤이 주어졌을 때, 위의 규칙을 지켰는지 아닌지를 알아내는 프로그램을 작성하시오.

👀제약조건


입력

입력은 여러개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스는 한 줄로 이루어져 있으며, 창영이가 춘 춤이 주어진다. 각 춤은 1000스텝을 넘지 않는다. 각 스텝 알파벳 소문자로 이루어져 있고, 100글자를 넘지 않는다.

출력

창영이의 춤이 규칙을 모두 지켰다면, “form ok: “를 출력하고 입력으로 주어진 춤을 출력한다.

창영이의 춤이 규칙을 1개만 어겼다면, “form error K: “를 출력하고 입력으로 주어진 춤을 출력한다. 여기서 K는 창영이가 어긴 규칙의 번호이다.

창영이의 춤이 규칙을 여러개 어겼다면, “form errors K(1), K(2), …, K(N-1) and K(N): “을 출력하고 입력으로 주어진 춤을 출력한다. K(i)는 창영이가 어긴 규칙의 번호이고, 오름차순이다.

창영이가 1번 규칙을 어겼다면, 입력으로 주어진 춤을 출력할 때, 규칙에 어긋난 dip을 대문자로 출력한다.

예제 입력 1

1
2
3
4
5
6
7
8
dip twirl hop jiggle hop hop clap stomp clap
dip hop jiggle hop hop clap stomp clap
dip twirl hop jiggle hop hop clap clap stomp
jiggle dip twirl hop jiggle hop hop clap stomp clap
jiggle dip
jiggle
dip twirl hop dip jiggle hop dip hop clap stomp clap

예제 출력 1

1
2
3
4
5
6
7
form ok: dip twirl hop jiggle hop hop clap stomp clap
form error 1: DIP hop jiggle hop hop clap stomp clap
form error 2: dip twirl hop jiggle hop hop clap clap stomp
form error 4: jiggle dip twirl hop jiggle hop hop clap stomp clap
form errors 2 and 4: jiggle dip
form errors 2, 4 and 5: jiggle
form error 1: dip twirl hop DIP jiggle hop dip hop clap stomp clap

🤩접근방법


구현 유형의 문제입니다.

5가지 함수를 만들었고, form 결과 출력물을 list에 담아 동적 결과가 만들어질 수 있도록 접근하였습니다.

아래 코드는 Rule1을 확인하는 코드의 일부분으로

바로 직전과, 전전의 인덱스가 음수가 되는 경우를 방지하기 위해 max를 사용하였습니다.

1
2
 #바로 직전이 jiggle 이거나 전전이 jiggle
            if data[max(0,i-1)] =='jiggle' or data[max(0,i-2)] == 'jiggle'

🤔풀이


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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# dip은 jiggle을 춘 다음이나 다다음, 또는 twirl을 추기 전에 출 수 있다.

def rule1(data):
    mistake = []
    for i in range(len(data)):
        if data[i] == 'dip':
            #바로 직전이 jiggle 이거나 전전이 jiggle
            if data[max(0,i-1)] =='jiggle' or data[max(0,i-2)] == 'jiggle' or data[min(len(data)-1, i+1)] == 'twirl':
                continue
            else:
                mistake.append(i)
    return mistake

# 모든 춤은 clap stomp clap으로 끝나야 한다.
def rule2(data):
    
    target = ["clap","stomp","clap"]
    if len(data) >= 3:
        for i in range(3):
            if target[i] != data[-3+i]:
                return False
        return True
    else:
        return False
    

# 만약 twirl을 췄다면, hop도 춰야한다.
def rule3(data):
    if 'twirl' in data:
        if 'hop' in data:
            return True
        return False 
    else:
        return True

# jiggle로 춤을 시작할 수 없다.
def rule4(data):
    if data[0] == 'jiggle':
        return False
    
    return True
        

# 반드시 dip을 춰야 한다.
def rule5(data):
    if 'dip' not in data:
        return False
    return True 

while True:
    try:
        origin = input()
        n = list(origin.split())
        rules = [False]*5
        
        result = rule1(n)
        if len(result) == 0:
            rules[0] = True
        if rule2(n):
            rules[1] = True
        if rule3(n):
            rules[2] = True
        if rule4(n):
            rules[3] = True
        if rule5(n):
            rules[4] = True
        if all(rules):
            print(f'form ok: {origin}')
        else:
            
            cnt = []

            for i in range(len(rules)):
                if not rules[i]:
                    cnt.append(i)
            
            for r in result:
                n[r] = 'DIP'
            origin = " ".join(n)

            if len(cnt) == 1:
                print(f'form error {cnt[0]+1}: {origin}')
            else:
                error_message = ['form errors ']

                for i in range(len(cnt)):
                    if i == 0:
                        pass
                    elif i == len(cnt) - 1:
                        error_message.append(" and ")
                    else:
                        error_message.append(", ")
                        
                    error_message.append(str(cnt[i]+1))
                error_message.append(": ")
                error_message.append(origin)
                print("".join(error_message))

    except EOFError:
        break

🧐


위 코드를 더 깔끔히 작성한다면?

1
2
3
4
5
6
7
8
9
10
def rule1(data):
    mistake = []
    for i in range(len(data)):
        if data[i] == 'dip':
            #바로 직전이 jiggle 이거나 전전이 jiggle
            if data[max(0,i-1)] =='jiggle' or data[max(0,i-2)] == 'jiggle' or data[min(len(data)-1, i+1)] == 'twirl':
                continue
            else:
                data[i] = 'DIP'

1번 조건을 확인하는 부분에서 mistakes 리스트를 지우고, data에서 dip -> DIP로 변경할 수 있습니다.

대신, dip가 DIP로 바뀌면서 5번 조건 반드시 dip을 춰야 한다에 영향을 줄 수 있기 때문에 1번 조건 확인은 가장 나중에 확인해야합니다.

1
2
3
4
5
6
7
8
9
10
11
# 모든 춤은 clap stomp clap으로 끝나야 한다.
def rule2(data):
    
    target = ["clap","stomp","clap"]
#    if len(data) >= 3:
#        for i in range(3):
#            if target[i] != data[-3+i]:
#                return False

		if (data[-3], data[-2], data[-1]) != ('cap', 'stom','clap')
					return False

2번 조건은 반복문으로 순회해도 비교가 가능하지만 튜플 형식으로도 비교할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
#if rule5(n):
#    rules[4] = True
#if rule1(n):
#    rules[0] = True
#if rule2(n):
#    rules[1] = True
#if rule3(n):
#    rules[2] = True
#if rule4(n):
#    rules[3] = True

errors = [str(i+1) for i in range(5) if rules[i]]

다섯가지 조건을 확인하여 만족하지 않는 조건의 번호를 에러문으로 출력하는 부분은 각 함수에서 자기 자신의 rules[idx]에 대해 true/false를 처리하고, 그 값을 리스트 컴프리션 형태로 가져와 사용하도록 변경 가능합니다.

1
2
3
4
5
6
7
8
9
10
if not errors:
	print(f'form ok: ', end='')
elif len(errors) == 1:
	print(f'form error {error[0]}: ', end='')
else:
	print(f'form erros {", ".join(errors[:-1])}} and errors[-1]}: ',  end='')

print(" ".join(n))
------------------------------------------------
error_message= ", ".join(map(str, errors[:-1])) + " and " + str(errors[-1])

print문 또는 리스트에 에러구문을 위와 같이 사용하여 결과값을 짧은 코드로 출력할 수 있습니다.

This post is licensed under CC BY 4.0 by the author.