기타/백준

6. 심화 1 (2)

zoome22 2023. 7. 14. 13:43

https://www.acmicpc.net/step/52

 

심화 1 단계

두세 문자가 한 글자로 묶일 수 있을 때 글자의 수를 세는 문제

www.acmicpc.net

 

5문제


백준 / 10988번

문제

알파벳 소문자로만 이루어진 단어가 주어진다. 이때, 이 단어가 팰린드롬인지 아닌지 확인하는 프로그램을 작성하시오.

팰린드롬이란 앞으로 읽을 때와 거꾸로 읽을 때 똑같은 단어를 말한다. 

level, noon은 팰린드롬이고, baekjoon, online, judge는 팰린드롬이 아니다.

 

입력

첫째 줄에 단어가 주어진다. 단어의 길이는 1보다 크거나 같고, 100보다 작거나 같으며, 알파벳 소문자로만 이루어져 있다.

 

출력

첫째 줄에 팰린드롬이면 1, 아니면 0을 출력한다.

 

풀이

-Python3

str = input()
flag = 1
for i in range(len(str)):
    if str[i] == str[len(str)-1-i] :
        continue
    else :
        flag = 0

print(flag)

앞에서 i번째 인덱스와 뒤에서 i번째 인덱스를 비교하여 같을 때는 flag가 true로 유지되게 하고, 그렇지 않다면 flag를 0으로 바꾸어서 출력하게 했다. string을 len() 함수로 길이를 뽑으면 최대 인덱스 넘버보다 1이 크기 때문에 인덱스를 셀 때 1을 빼주는 것만 주의하면 될 것 같다


백준 / 1157번 (★)

문제

알파벳 대소문자로 된 단어가 주어지면, 이 단어에서 가장 많이 사용된 알파벳이 무엇인지 알아내는 프로그램을 작성하시오. 단, 대문자와 소문자를 구분하지 않는다.

 

입력

첫째 줄에 알파벳 대소문자로 이루어진 단어가 주어진다. 주어지는 단어의 길이는 1,000,000을 넘지 않는다.

 

출력

첫째 줄에 이 단어에서 가장 많이 사용된 알파벳을 대문자로 출력한다. 단, 가장 많이 사용된 알파벳이 여러 개 존재하는 경우에는 ?를 출력한다.

 

풀이

-Python3

str = input().upper()
char = list(set(str)) #중복 제거 set()
countlist = []

for i in char :
    count = str.count(i)
    countlist.append(count)

if countlist.count(max(countlist)) > 1:
    print("?")
else :
    maxindex = countlist.index(max(countlist))
    print(char[maxindex])

진짜 오래 걸렸다.... 

원래 maxcount랑 maxindex 변수를 놓고 str.count(문자) 한 결과가 maxcount보다 크면 그 때의 count, index, char를 저장하는 식으로 하려고 했는데 for문 설정하는 게 어디서인가 계속 어긋나서 포기. 어찌저찌 구현까지는 성공했는데 동일한 count일때 에러문을 출력하는 게 막막해서 countlist로 선언할 수밖에 없는 것 같다. 하고 upper()로 대문자 변환하는 걸 처음 입력받을 때 안 하고 print 할 때만 해서 한번 틀렸다. 대소문자가 각각 들어오면 다른 문자로 인식하지 않게 처음부터 변환시켜서 저장해야 한다. 뭔가 이런 로직 잘 짜는 사람은 데이터베이스도 잘 다룰 것 같음

  • countlist를 따로 생성하여 count에 대한 값을 저장하고 추후 비교
  • countlist에 대해 max 값의 index를 찾고, 그 index를 각 char만 저장해놓은 리스트 char에서 접근한다. (크기가 같은 list로 선언했기 때문에 가능한 일)
  • 중복 제거 함수는 set()
  • 문자열을 대문자로 바꾸는 string 함수는 upper()

백준 / 2941번

문제

예전에는 운영체제에서 크로아티아 알파벳을 입력할 수가 없었다. 따라서, 다음과 같이 크로아티아 알파벳을 변경해서 입력했다.

č c=
ć c-
dz=
đ d-
lj lj
nj nj
š s=
ž z=

예를 들어, ljes=njak은 크로아티아 알파벳 6개(lj, e, š, nj, a, k)로 이루어져 있다. 단어가 주어졌을 때, 몇 개의 크로아티아 알파벳으로 이루어져 있는지 출력한다.

dž는 무조건 하나의 알파벳으로 쓰이고, d와 ž가 분리된 것으로 보지 않는다. lj와 nj도 마찬가지이다. 위 목록에 없는 알파벳은 한 글자씩 센다.

 

입력

첫째 줄에 최대 100글자의 단어가 주어진다. 알파벳 소문자와 '-', '='로만 이루어져 있다.

단어는 크로아티아 알파벳으로 이루어져 있다. 문제 설명의 표에 나와있는 알파벳은 변경된 형태로 입력된다.

 

출력

입력으로 주어진 단어가 몇 개의 크로아티아 알파벳으로 이루어져 있는지 출력한다.

 

풀이

-Python3

char = ['c=', 'c-', 'dz=', 'd-', 'lj','nj','s=','z=']
str = input()
for i in char:
    str = str.replace(i,'1')
print(len(str))

문제가 장황한 것에 비해 어렵지는 않다.

크로아티아 문자에 대응하는 문자 리스트를 따로 선언해두고, 이 안에서 for문을 돌면서 일치하는 문자를 한 글자로 바꿔버리면 된다. 일반 알파벳과 -, =가 조합되어 두 글자로 표현되는 크로아티아 문자를 한 글자로 바꿔서 길이를 세기만 하면 되기 때문이다.


백준 / 1316번

문제

그룹 단어란 단어에 존재하는 모든 문자에 대해서, 각 문자가 연속해서 나타나는 경우만을 말한다. 예를 들면, ccazzzzbb는 c, a, z, b가 모두 연속해서 나타나고, kin도 k, i, n이 연속해서 나타나기 때문에 그룹 단어이지만, aabbbccb는 b가 떨어져서 나타나기 때문에 그룹 단어가 아니다.

단어 N개를 입력으로 받아 그룹 단어의 개수를 출력하는 프로그램을 작성하시오.

 

입력

첫째 줄에 단어의 개수 N이 들어온다. N은 100보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에 단어가 들어온다. 단어는 알파벳 소문자로만 되어있고 중복되지 않으며, 길이는 최대 100이다.

 

출력

첫째 줄에 그룹 단어의 개수를 출력한다.

 

풀이

-Python3

N = int(input())
count = N #group단어의 count 저장

for _ in range(N) :
    str = input()
    for i in range(len(str)-1):
        if str[i] == str[i+1]:
            pass
        elif str[i] in str[i+1:]:
            count-=1
            break
print(count)

count를 추가하는 식으로 생각했을 때 되게 막막한 느낌이었는데 깎는 식으로 접근하니 금방 풀렸다.

count를 추가하는 게 너무 습관이라서 역으로 생각하는 것도 염두해두면 좋을 것 같다.

로직은 현재 글자와 뒷 글자가 같으면 for문을 이어가고, 만약 두 글자가 다를 시에는 그룹 단어가 아니라는 뜻으로 count를 차감한다. 여기서 주의할 것은 elif로 조건을 한 번 더 점검해야 한다는 것이다. 두 글자가 다르다고 해도, 뒷 글자가 존재하지 않을 수도 있다. 또는 다른 단어의 시작일 수도 있다. 그래서 현재 글자가 다음 글자부터 시작되는 나머지 string에 존재하는지 확인하는 조건이 필요하다. (str[i] in str[i+1:])


백준 / 25206번

문제

인하대학교 컴퓨터공학과를 졸업하기 위해서는, 전공평점이 3.3 이상이거나 졸업고사를 통과해야 한다. 그런데 아뿔싸, 치훈이는 깜빡하고 졸업고사를 응시하지 않았다는 사실을 깨달았다!

치훈이의 전공평점을 계산해주는 프로그램을 작성해보자.

전공평점은 전공과목별 (학점 × 과목평점)의 합을 학점의 총합으로 나눈 값이다.

인하대학교 컴퓨터공학과의 등급에 따른 과목평점은 다음 표와 같다.

A+ 4.5
A0 4.0
B+ 3.5
B0 3.0
C+ 2.5
C0 2.0
D+ 1.5
D0 1.0
F 0.0

P/F 과목의 경우 등급이 P또는 F로 표시되는데, 등급이 P인 과목은 계산에서 제외해야 한다.

과연 치훈이는 무사히 졸업할 수 있을까?

 

입력

20줄에 걸쳐 치훈이가 수강한 전공과목의 과목명, 학점, 등급이 공백으로 구분되어 주어진다.

 

출력

치훈이의 전공평점을 출력한다.

정답과의 절대오차 또는 상대오차가 10^−4 이하이면 정답으로 인정한다.

 

풀이

-Python3

출제자가 인하공인듯

rate_list = ['A+', 'A0', 'B+', 'B0', 'C+', 'C0', 'D+', 'D0', 'F']
grade_list = [4.5, 4.0, 3.5, 3.0, 2.5, 2.0, 1.5, 1.0, 0]

total = 0 #학점의 총합
result = 0 #학점x과목평점

for _ in range(20) :
    subject, point, rate = input().split() #띄어쓰기 구분으로 저장
    point = float(point) #string 상태의 point를 실수형으로 변환
    if rate != 'P' :
        total += point
        result += point * grade_list[rate_list.index(rate)]

print('%.6f' % (result / total))

생각보다 간단함

학점과 등급이 매칭될 수 있도록 미리 list로 선언을 해두면 간단해진다

과목명, 학점, 등급이 띄어쓰기로 들어오기 때문에 split()으로 나눠서 각 변수에 저장해둔 다음, 학점은 총학점 변수에 저장하고 (학점x과목 평점)도 따로 for문 밖에 변수를 선언해두고 더해주면 된다. 둘을 나누기만 하면 끝

 


심화에서는 크기가 같은 두 개의 리스트를 미리 선언해두고, 인덱스 넘버가 같아 매칭되는 점을 이용해서 두 데이터를 넘나드는 문제가 많이 나왔다.