[AI 코테 멘토링 스터디룸] 공부 기록1
## 에라토스테네스의 체 2960
```python
#에라토스테네스의 체 2960
N,K=map(int,input().split())
nums=list(range(2,N+1))
count=0
current_erase=-1
while K!=count:
P=nums[0]
current_erase=nums.pop(0)
count+=1
# print(current_erase, count, nums)
if count>=K:
break
for i,num in enumerate(nums):
if num%P==0:
current_erase=nums.pop(i)
count+=1
if count>=K:
break
# print(current_erase, count, nums)
print(current_erase)
```
먼저, 에라토스테네스의 체를 사용하여 K번째로 지워지는 수를 찾는 문제의 코드를 제출해주셨네요.
문제의 목표는 주어진 수 N까지의 모든 수를 에라토스테네스의 체로 거르면서 K번째로 지워진 수를 찾는 것입니다. 현재 코드는 기본적인 로직은 올바르게 구현되어 있지만, 리스트에서 요소를 삭제할 때 인덱스가 변경되는 문제 때문에 문제가 발생할 수 있습니다.
개선을 위해 몇 가지 조언을 드리겠습니다:
1. `nums.pop(i)`를 사용할 때 리스트에서 요소를 제거하면 뒤의 요소들의 인덱스가 당겨지기 때문에 반복문에서 일부 요소를 건너뛸 수 있습니다.
2. 위의 문제를 해결하기 위해 순회하는 동안 리스트를 수정하지 않는 다른 방법을 사용해야 합니다.
개선된 코드를 제안하겠습니다:
```python
N, K = map(int, input().split())
nums = list(range(2, N+1))
count = 0
current_erase = -1
while nums and count < K:
P = nums[0]
remove_list = []
for i, num in enumerate(nums):
if num % P == 0:
remove_list.append(i)
count += 1
if count == K:
current_erase = num
break
for index in reversed(remove_list):
nums.pop(index)
print(current_erase)
```
이렇게 변경하면 먼저 지워야 할 인덱스를 `remove_list`에 저장하고, 나중에 이 인덱스들을 기반으로 한 번에 지워버리는 방식을 사용합니다. `reversed(remove_list)`를 사용하는 이유는 리스트의 마지막 인덱스부터 삭제하기 위함입니다.
물론, 좀 더 효율적이고 깔끔하게 코드를 짤 수 있는 방법을 제안하겠습니다.
1. **Boolean List 활용**: 체로 걸러내는 동안 바로바로 해당 수가 지워졌는지 확인할 수 있도록 boolean 리스트를 사용할 수 있습니다. 이렇게 하면 굳이 리스트에서 값을 삭제할 필요가 없어집니다.
2. **외부 반복문 조건 수정**: `nums` 리스트가 비어있는지 확인하는 것은 필요 없습니다. 최대 N까지만 확인하면 됩니다.
코드를 개선하면 아래와 같습니다:
```python
N, K = map(int, input().split())
# N+1 크기의 boolean 리스트를 초기화합니다.
# True는 해당 위치의 수가 아직 지워지지 않았음을 의미합니다.
is_prime = [True] * (N+1)
count = 0
current_erase = -1
for i in range(2, N+1):
if is_prime[i]:
for j in range(i, N+1, i):
if is_prime[j]:
is_prime[j] = False
count += 1
if count == K:
current_erase = j
break
if count == K:
break
print(current_erase)
```
이 코드는 주어진 범위 내에서 모든 소수를 찾으면서 동시에 K번째로 지워지는 수도 찾습니다. `is_prime` 리스트를 사용하면 불필요한 요소 삭제 없이도 원하는 결과를 얻을 수 있습니다.
bfs 문제를 풀었어! 피드백 해줘!
```python
## 바이러스 2656
computer_count=int(input())
iter_count=int(input())
computer_connection=dict()
for i in range(iter_count):
fir,sec=map(int,input().split())
if fir not in computer_connection:
computer_connection[fir]=[]
if sec not in computer_connection:
computer_connection[sec]=[]
computer_connection[fir].append(sec)
computer_connection[sec].append(fir)
count=0
infected=[1]
current=0
while current<=len(infected)-1:
# print("log: ",infected[current],infected, computer_connection[infected[current]])
if infected[current] in computer_connection:
for i in computer_connection[infected[current]]:
if i not in infected:
infected.append(i)
current+=1
print(len(infected)-1)
```
BFS를 이용하여 컴퓨터 간의 네트워크 연결상태에서 바이러스가 전파되는 컴퓨터의 수를 구하는 문제를 푼 것으로 보입니다.
코드를 보면 전체적으로는 BFS 구조를 잘 잡아서 구현하셨습니다. 다만, 몇 가지를 개선하면 좀 더 효율적이거나 가독성이 좋은 코드를 작성할 수 있습니다.
1. **Queue 사용**: 현재 `infected` 리스트를 이용해서 큐 역할을 하게 만들었습니다. 이는 코드의 가독성을 저하시킵니다. 파이썬의 `collections` 모듈의 `deque`를 사용하면 큐를 명시적으로 표현할 수 있습니다.
2. **Dictionary 초기화 방식 개선**: `computer_connection`을 초기화할 때 `defaultdict`를 사용하면 코드를 좀 더 깔끔하게 만들 수 있습니다.
3. **불필요한 count 변수**: 코드 내에 `count` 변수는 사용되지 않고 있습니다. 이는 삭제해도 좋을 것 같습니다.
위의 피드백을 바탕으로 코드를 개선해보면 다음과 같습니다:
```python
from collections import defaultdict, deque
computer_count = int(input())
iter_count = int(input())
computer_connection = defaultdict(list)
for i in range(iter_count):
fir, sec = map(int, input().split())
computer_connection[fir].append(sec)
computer_connection[sec].append(fir)
visited = set([1])
queue = deque([1])
while queue:
current = queue.popleft()
for neighbor in computer_connection[current]:
if neighbor not in visited:
visited.add(neighbor)
queue.append(neighbor)
print(len(visited) - 1)
```
`defaultdict`를 사용하면 딕셔너리 키가 없을 때도 바로 추가할 수 있어 코드가 간결해집니다. 또한, `deque`를 사용하면 BFS를 좀 더 명시적으로 표현할 수 있습니다.
### 슈퍼 마리오 2851
```jsx
#슈퍼 마리오 2851
now_total=0
last_total=-99999
mushrooms=[]
is_printed=False
for i in range(10):
mushrooms.append(int(input()))
for mushroom in mushrooms:
now_total+=mushroom
if (now_total - 100)*(now_total - 100)>(last_total - 100)*(last_total - 100):
print(last_total)
is_printed=True
break
# elif (now_total - 100)*(now_total - 100)==(last_total - 100)*(last_total - 100):
# print(now_total)
# break
last_total=now_total
#now_total=0
# print("last_total")
if not is_printed:
print(last_total)
```
코드를 확인해 보았습니다. "슈퍼 마리오 2851" 문제를 풀기 위한 코드로 보입니다. 코드의 목적과 구조를 기반으로 몇 가지 조언 및 개선 사항을 제시해 보겠습니다.
1. **코드 주석 및 문서화**: 코드의 각 부분이 어떤 목적으로 작성되었는지 주석을 통해 설명해 주는 것이 좋습니다. 이를 통해 다른 사람이나 나중에 코드를 다시 보게 될 자신이 이해하기 쉬워집니다.
2. **변수명의 명확성**: 가능하면 변수명을 좀 더 명확하게 지어주는 것이 좋습니다. 예를 들어, `is_printed`보다는 `score_found`와 같은 이름을 사용하면 코드를 읽는 사람에게 더 명확한 의미 전달이 가능합니다.
3. **초기값 설정**: `last_total`의 초기값이 `99999`로 설정된 것은 불필요한 특정 값으로 보입니다. `0`으로 초기화하면 더욱 간결하게 표현할 수 있습니다.
4. **코드의 간결성**: 조건문의 표현 방식을 간결하게 하면 코드의 가독성을 높일 수 있습니다.
아래는 위의 조언을 반영하여 수정한 코드입니다:
```python
# 슈퍼 마리오 2851 문제 해결을 위한 코드
now_total = 0
last_total = 0
mushrooms = []
score_found = False
# 버섯의 점수를 입력받아 저장
for i in range(10):
mushrooms.append(int(input()))
# 가장 100에 가까운 총 점수 찾기
for mushroom in mushrooms:
now_total += mushroom
# 현재 총 점수와 이전 총 점수 중 100에 더 가까운 점수를 확인
if abs(now_total - 100) > abs(last_total - 100):
print(last_total)
score_found = True
break
last_total = now_total
# 100에 가장 가까운 총 점수가 아직 출력되지 않았다면 출력
if not score_found:
print(last_total)
```
이렇게 코드를 수정하면 좀 더 가독성이 좋고 이해하기 쉬운 코드가 됩니다.
score_found 이거 이름 바꾼 이유 알려줘 그리고 이렇게 flag(이게 맞는 단어인지는 모르겠어)를 쓰는 방식이 좋은지 나쁜지 모르겠어
네, 좋은 질문입니다!
1. **`score_found` 이름 변경 이유**:
- 원래의 `is_printed`는 해당 변수가 "출력되었는지"에 대한 여부를 나타내는 것처럼 보입니다. 그러나 코드의 주요 목적은 "100에 가장 가까운 점수를 찾는 것"이므로, 이를 반영하는 이름이 더 적절하다고 생각했습니다.
- `score_found`는 "적절한 점수(100에 가장 가까운 점수)를 찾았는지"에 대한 여부를 나타냅니다. 이렇게 이름을 변경하면 변수의 목적과 연관성을 더 명확하게 표현할 수 있습니다.
2. **Flag 사용에 대한 평가**:
- **장점**: Flag 변수는 코드의 특정 부분에서 어떤 조건 또는 상태가 만족되었는지를 추적할 때 유용합니다. 코드의 다른 부분에서 이 상태를 검사하면 로직의 흐름을 제어할 수 있습니다.
- **단점**: 과도하게 사용하면 코드가 복잡해지고 가독성이 떨어질 수 있습니다. 특히 여러 Flag 변수들이 서로 연관되어 동작할 때, 코드의 흐름을 파악하기 어려울 수 있습니다.
이러한 점을 고려하여, Flag 변수 사용은 필요한 경우에 제한적으로 사용하는 것이 좋습니다. 사용할 때는 변수명을 명확하게 지어 해당 Flag의 목적을 잘 설명하도록 해야 합니다.
위의 코드에서 `score_found`는 코드 흐름을 명확하게 제어하기 위해 사용되므로, 이 경우에는 적절하게 사용된 것으로 판단됩니다.
결론적으로, Flag 변수의 사용은 코드의 목적과 복잡성, 그리고 개발자의 선호에 따라 달라질 수 있습니다. Flag 사용 시에는 그 목적과 사용 방식을 명확하게 이해하고 있어야 합니다.
댓글
댓글 쓰기