문제
그룹 단어란 단어에 존재하는 모든 문자에 대해서, 각 문자가 연속해서 나타나는 경우만을 말한다. 예를 들면, ccazzzzbb는 c, a, z, b가 모두 연속해서 나타나고, kin도 k, i, n이 연속해서 나타나기 때문에 그룹 단어이지만, aabbbccb는 b가 떨어져서 나타나기 때문에 그룹 단어가 아니다.
단어 N개를 입력으로 받아 그룹 단어의 개수를 출력하는 프로그램을 작성하시오.
입력
첫째 줄에 단어의 개수 N이 들어온다. N은 100보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에 단어가 들어온다. 단어는 알파벳 소문자로만 되어있고 중복되지 않으며, 길이는 최대 100이다.
출력
첫째 줄에 그룹 단어의 개수를 출력한다.
N = int(input())
lst = []
sum = 0
for i in range(N):
word = input()
lst.append(word)
for i in lst: # 입력한 단어들에 대하여
lst1 = []
for j in i: # 단어들의 알파벳에 대하여
indices = [i for i, c in enumerate(i) if c == j] # 해당 알파벳의 인덱스 모두를 리스트로 만들어 바인딩
if indices not in lst1: # 알파벳 당 인덱스 리스트는 하나만
lst1.append(indices) # 새로운 리스트에 알파벳 인덱스 리스트를 추가
cnt = 0
for k in lst1: # 각각의 알파벳 인덱스 리스트에 대하여
if len(i) > 1: # 알파벳이 하나 이상일 때
for l in range(len(k) - 1):
if k[l+1] - k[l] != 1: # 인덱스가 연속되지 않을 경우 (인덱스값의 차이가 1이 아닌 경우)
cnt += 1 # cnt값을 추가한다.
if cnt == 0: # cnt값이 하나라도 추가되지 않을 경우 (인덱스가 모두 연속할 경우))
sum += 1
print(sum)
먼저 단어들을 입력받은 후 , 그룹 단어인지를 판별하는 기준은 동일한 알파벳의 인덱스가 연속인지를 관찰하는 아이디어를 이용했다.
입력받은 단어들을 리스트 lst에 집어넣어 주었고, 각각의 단어들에 대하여 알파벳의 인덱스를 리스트 lst1에 집어넣어 주었다.
이 과정을 거치면 lst1에는 단어의 알파벳에 대한 인덱스가 들어있게 된다.
예를들어 apple, haha이라는 단어가 입력되면,
lst = ['apple', 'haha'] 가 되고,
lst1은 단어 'apple'에 대한 알파벳의 인덱스 리스트, 즉 [[0], [1, 2], [3], [4]]
마찬가지로 'haha'에 대한 알파벳의 인뎃르 리스트, 즉 [[0, 2], [1, 3]] 이 만들어진다.
그 다음의 for문에서는 알파벳의 인덱스가 연속되지 않은 경우에는 cnt 값을 추가해주어 가중치를 만들어주고, 가중치가 없으면 최종적으로 그룹 단어의 개수인 sum에 1을 더하여 주는 방식으로 작동하게 된다.
'apple'은 인덱스가 연속되므로 cnt = 0이다. 즉 sum = 1이 된다.
'haha'는 인덱스가 연속되지 않으므로 cnt = cnt + 1이 되므로, 여전히 sum = 1이다.
따라서 입력이
2
apple
haha
가 되었을 때, 최종 출력은 1이 된다.
단어들의 알파벳 인덱스 리스트를 만드는 과정에서, 인덱스와 그 인덱스에 해당하는 값을 동시에 리턴하는 과정이 필요했는데,
이 때 enumerate라는 함수를 사용하였다.
enumerate 함수
enumerate함수는 입력으로 받은 데이터와 인덱스 값을 포함하는 enumerate 객체를 리턴해준다.
예를 들어 lst = ['apple, 'banana', 'car'] 이라는 리스트가 있고, for문을 사용하여 enumerate객체를 출력해주게 되면,
lst = ['apple', 'banana', 'car']
for x in enumerate(lst):
print(x)
>>>(0, 'apple')
>>>(1, 'banana')
>>>(2, 'car')
이와 같이 출력되게 된다.
나는 입력된 단어 'apple'이라는 단어에서 각각의 알파벳에 대하여, for문을 작성하여 enumerate함수를 이용하였다.
'a'에 대하여 enumerate 객체 (0, 'a'), 'p'에 대하여 (1, 'p'), (2, 'p') ... 식으로 반환되는 객체를 이용하여 또 다른 리스트로 만들었고,
[0], [1, 2] ... 와 같은 알파벳의 인덱스 리스트를 반환할 수 있게 되었다.
이 과정에서 이용한 개념이 또 있는데, 한 줄 for문 개념이다.
한 줄 for문
indices = [i for i, c in enumerate(i) if c == j]
indices 라는 리스트는 enumerate(i)라는 enumerate 객체의 두 변수인 i와 c중 i만을 추가한 리스트이다. 이때 c는 j와 같아야 한다.
for문과 if문은 한 줄로 출력할 수 있으며, 동시에 같이 쓰는 방법도 잘 이용하면 편리하게 코드를 작성할 수 있다.
lst = [1, 2, 3, 4, 5]
다음과 같은 리스트가 있다고 가정할 때, for문을 이용하여 원소를 출력하려면..
1. 기존의 for문 작동방식을 이용
for i in lst:
print(i)
2. 하지만 다음과 같이 한줄로 작성할 수도 있다.
[i for i in lst]
for 전과 후를 띄어서 이해하면 편리하다.
1번 방법에서는 int형으로 한 행에 값 하나씩 출력되지만, 2번 방법에서는 리스트 안에 담겨서 출력되게 된다.
lst = [[1, 2, 3], [4, 5, 6]]
다음과 같은 2차원 리스트에서는 원소를 하나하나 출력하려면 이와 같은 방법을 사용해야 했지만,
for i in lst:
for j in i:
print(j)
아래와 같이 한줄로 작성할 수도 있다.
[j for i in lst for j in i]
if문의 경우도 마찬가지로 한 줄로 표현할 수 있는데,
v = 3
if v > 0:
print('양수')
elif v < 0:
print('음수')
else:
print('zero')
위와 같이 여러 줄에 걸쳐 있는 조건문을
print('양수' if v > 0 else '음수' if v < 0, else 'zero')
이렇게 한줄로 나타낼 수 있다.
for문과 if문을 동시에 출력하는 방법 또한 마찬가지로 가능하다.
lst = [1, 2, 3, 4, 5, 6]
for i in lst:
if i > 3:
print(i)
[i for i in lst if i > 3]
위 코드와 아래 코드는 동일한 구성이다.
'Study > 백준' 카테고리의 다른 글
| [백준/파이썬] 1193 분수찾기 : 계차수열의 일반항 구하기 (0) | 2023.03.01 |
|---|---|
| [백준/파이썬] 4673 셀프 넘버 : set, sort(), sorted() (0) | 2023.01.13 |
| [백준/파이썬] 4344 평균은 넘겠지 : f-string 사용법 (0) | 2023.01.13 |