일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 백준
- dacon
- Baekjoon
- 더현대서울 맛집
- 프로그래머스 파이썬
- ubuntu
- 우분투
- PYTHON
- github
- leetcode
- 편스토랑 우승상품
- 편스토랑
- SW Expert Academy
- programmers
- 자연어처리
- gs25
- Real or Not? NLP with Disaster Tweets
- hackerrank
- Docker
- 프로그래머스
- 맥북
- Kaggle
- AI 경진대회
- 금융문자분석경진대회
- ChatGPT
- 코로나19
- Git
- 데이콘
- 파이썬
- 캐치카페
- Today
- Total
솜씨좋은장씨
[BaekJoon] 3107번 : IPv6 (Python) (feat. ChatGPT) 본문
코딩 1일 1문제! 오늘의 문제는 백준의 IPv6 입니다.
👨🏻💻 문제 풀이 - SOMJANG - 1회차
입력받은 IPv6 문자열을 : 로 split 한 다음
"" 일 경우
-> 0으로만 이루어져 있는 그룹이 있을 경우 그 중 한 개 이상 연속된 그룹을 하나 골라 콜론 2개(::) 로 변경한 경우 이므로
-> "0000" 을 문자열을 split 한 리스트의 길이를 8에서 빼고 + 1 한 값 만큼 full_address 리스트에 넣어줍니다.
이때 :: 을 ":" 으로 split 하면 "" 가 2개 생기므로 첫번째 "" 을 처리했다면
두번째 ""은 별도의 처리를 하지않고 넘어가도록 하였습니다.
👨🏻💻 코드 ( Solution ) - SOMJANG - 1회차
def IPv6(ipv6_address):
ipv6_address = ipv6_address.split(":")
continue_check = False
full_address = []
for address in ipv6_address:
if address == "" and not continue_check:
full_address += ['0000' for _ in range(8 - len(ipv6_address) + 1)]
continue_check = True
else:
full_address.append(address.zfill(4))
return ":".join(full_address)
if __name__ == "__main__":
ipv6_address = input()
print(IPv6(ipv6_address=ipv6_address))
👨🏻💻 문제 풀이 - SOMJANG - 2회차
이렇게 풀고나니!
음 뭔가 python3 기본 모듈 중에 IPv6 를 처리하는게 있지않을까? 싶어 찾아보니
역시나! 존재했습니다.
https://docs.python.org/3/library/ipaddress.html#module-ipaddress
이 모듈을 사용하여서도 문제를 풀어보았습니다.
import ipaddress
def IPv6(ipv6_address):
return ipaddress.IPv6Address(ipv6_address).exploded
if __name__ == "__main__":
ipv6_address = input()
print(IPv6(ipv6_address=ipv6_address))
아주아주 간단하게! 문제를 풀 수 있었습니다.
👨🏻💻 문제 풀이 - ChatGPT - 실패!
이렇게 쉬운 풀이도 있겠다! ChatGPT 가 이정도 문제는 아주아주아주아주아주아주 쉽게 풀겠지? 라는 기대를 품고
문제를 풀어달라고 요청해보았습니다.
하지만....!
결국 문제를 푸는 것은 실패했습니다.
모든 풀이가 ::1 에 대해서 틀린 답을 만들거나 ValueError 같은 에러가 발생하는 코드를 만들어주었습니다.
다음은 ChatGPT 와의 대화 입니다.
💻 ChatGPT
아래는 주어진 IPv6 주소를 파싱하여 32자리의 16진수로 변환하여 출력하는 파이썬 코드입니다.
s = input()
# 콜론을 기준으로 문자열을 분리하여 리스트에 저장합니다.
groups = s.split(':')
# 만약 ::가 있다면, ::를 제거하고 그 자리에 0을 추가합니다.
if '' in groups:
idx = groups.index('')
groups = groups[:idx] + ['0'] * (9 - len(groups)) + groups[idx+1:]
else:
groups = ['0'] * (8 - len(groups)) + groups
# 각 그룹을 4자리 16진수로 변환합니다.
groups = [int(g, 16) for g in groups]
# 16진수를 0으로 채워진 4자리 문자열로 변환합니다.
groups = [format(g, '04x') for g in groups]
# 변환된 문자열을 콜론으로 이어붙여서 출력합니다.
print(':'.join(groups))
예를 들어, 입력으로 주어진 "25:09:1985:aa:091:4846:374:bb"라는 IPv6 주소를 파싱하여 32자리의 16진수로 변환하면 "0025:0009:1985:00aa:0091:4846:0374:00bb"가 출력됩니다.
🧑🏻💻 SOMJANG
ValueError 가 발생해
---------------------------------------------------------------------------
ValueError Traceback (most recent call last) Input In [19], in <cell line: 14>()
11 groups = ['0'] * (8 - len(groups)) + groups
13 # 각 그룹을 4자리 16진수로 변환합니다.
---> 14 groups = [int(g, 16) for g in groups]
16 # 16진수를 0으로 채워진 4자리 문자열로 변환합니다.
17 groups = [format(g, '04x') for g in groups]
Input In [19], in <listcomp>(.0)
11 groups = ['0'] * (8 - len(groups)) + groups
13 # 각 그룹을 4자리 16진수로 변환합니다.
---> 14 groups = [int(g, 16) for g in groups]
16 # 16진수를 0으로 채워진 4자리 문자열로 변환합니다.
17 groups = [format(g, '04x') for g in groups] ValueError: invalid literal for int() with base 16: ''
💻 ChatGPT
입력 예시에 "::"가 포함될 수 있기 때문에, 위 코드에서는 그룹들의 끝에 빈 문자열 ''이 추가되는 경우가 발생하여 int() 함수로 16진수로 변환할 때 ValueError가 발생합니다. 이 경우에 대비하여 groups 리스트에서 빈 문자열을 제거해주면 문제를 해결할 수 있습니다. 이를 적용한 수정된 코드는 다음과 같습니다.
ip = input().split(':')
groups = []
for g in ip:
if g:
groups.append(g)
else:
# '::'인 경우를 처리합니다.
groups += ['0'] * (8 - len(groups))
# 각 그룹을 4자리 16진수로 변환합니다.
groups = [int(g, 16) for g in groups]
# 16진수를 0으로 채워진 4자리 문자열로 변환합니다.
groups = [format(g, '04x') for g in groups]
# 그룹들을 ':'로 이어서 출력합니다.
print(':'.join(groups))
위 코드를 실행하면 정상적으로 결과가 출력됩니다.
🧑🏻💻 SOMJANG
::1 일때 0000:0000:0000:0000:0000:0000:0000:0001 이 되어야하는데 0000:0000:0000:0000:0000:0000:0000:0000:0001 가 됨
💻 ChatGPT
올바른 지적입니다. 이 코드에서는 '::'를 하나의 그룹으로 간주하여 9개 그룹으로 나누게 되어, 0이 7개인 그룹과 0이 1개인 그룹이 추가되어 10개 그룹이 생기게 됩니다. 이를 수정하여 '::'를 하나의 그룹으로 취급하도록 코드를 변경해야 합니다. 아래는 수정된 코드입니다.
# IPv6 주소를 입력받습니다.
ipv6 = input()
# 콜론을 기준으로 그룹을 분리합니다.
groups = ipv6.split(':')
# 각 그룹이 축약된 경우 0을 채워서 4자리로 만듭니다.
for i in range(len(groups)):
if len(groups[i]) < 4:
groups[i] = '0' * (4 - len(groups[i])) + groups[i]
# 축약되지 않은 그룹의 개수를 세어서 ::를 포함한 그룹의 개수를 구합니다.
num_full_groups = sum([len(g) == 4 for g in groups])
num_groups = num_full_groups + (2 if '' in groups else 0)
# ::가 없는 경우 그룹 수를 맞추기 위해 0 그룹을 추가합니다.
if '' not in groups:
groups += ['0000'] * (8 - len(groups))
# ::가 있는 경우 그룹 수를 맞추기 위해 0 그룹을 추가합니다.
elif num_groups < 8:
groups.remove('')
groups += ['0000'] * (8 - num_groups + 1)
# 각 그룹을 4자리 16진수로 변환합니다.
groups = [int(g, 16) for g in groups]
# 16진수를 0으로 채워진 4자리 문자열로 변환합니다.
groups = [format(g, '04x') for g in groups]
# 그룹을 콜론으로 연결하여 IPv6 주소를 완성합니다.
ipv6_full = ':'.join(groups)
# 결과를 출력합니다.
print(ipv6_full)
이 코드에서는 '::'을 하나의 그룹으로 간주하여 8개 그룹으로 나누게 되어, 0이 6개인 그룹과 0이 1개인 그룹이 추가되어 9개 그룹이 생기게 됩니다. 따라서 '::1'의 경우 8개 그룹 중 뒤에서 두 번째 그룹에 1이 들어가게 되어, 결과는 0000:0000:0000:0000:0000:0000:0000:0001이 되어야 합니다.
🧑🏻💻 SOMJANG
틀렸어 ::1 일 경우 0000:0000:0001:0000:0000:0000:0000:0000 가 아니라 0000:0000:0000:0000:0000:0000:0000:0001 이되어야해
💻 ChatGPT
네, 맞습니다. 제가 실수를 해서 잘못된 출력을 하고 있었습니다. 다음과 같이 수정하시면 됩니다.
address = input().split(':')
# 주소를 8개 그룹으로 나눕니다.
groups = []
for i in range(len(address)):
if address[i] == '':
# ::가 나온 경우 남은 그룹 수만큼 0으로 채웁니다.
groups += ['0'] * (8 - len(address) + 1)
else:
# 4자리 16진수로 변환합니다.
groups.append(format(int(address[i], 16), '04x'))
# 0으로 채워진 4자리 그룹을 먼저 찾아서 ::로 변경합니다.
zeros = [i for i in range(len(groups)) if groups[i] == '0000']
if zeros:
max_zero_len = max((len(list(v)) for _, v in itertools.groupby(zeros)))
if max_zero_len > 1:
zeros_group = [sum((list(v) + [None])[:max_zero_len]) // 2]
groups = groups[:zeros_group[0]] + ['0'] * (8 - max_zero_len + 1) + groups[zeros_group[-1] + 1:]
else:
groups = ['0'] * (8 - len(groups) + 1) + groups
# 16진수를 0으로 채워진 4자리 문자열로 변환합니다.
groups = [g.rjust(4, '0') for g in groups]
# 그룹을 콜론으로 연결합니다.
result = ':'.join(groups)
print(result)
출력 결과는 다음과 같습니다.
입력:
::1
출력:
0000:0000:0000:0000:0000:0000:0000:0001
여기까지 대화를 해보았는데 결국 위 코드도 ::1 에 대해서
0000:0000:0000:0000:0000:0000:0000:0000:0000:0000:0000:0000:0001
위 결과를 return 하는 것을 보고 내가 문제를 풀라고 해서 잘 풀지 못하는 것일까? 라는 생각이 들어서
이번에는 그냥 Python3 를 활용하여 IPv6 변환 코드를 구현해달라고 해보았습니다.
🧑🏻💻 SOMJANG
그냥 위에 문제 설명과 상관없이 축약된 IPv6 를 축약되지 않은 풀 IPv6로 변환하는 파이썬 코드를 알려줄 수 있을까
라고 해보았습니다.
💻 ChatGPT
네, 당연히 알려드릴 수 있습니다! 축약된 IPv6를 축약되지 않은 IPv6 주소로 변환하는 코드는 다음과 같이 작성할 수 있습니다.
def expand_ipv6_address(addr):
groups = addr.split(':')
# 각 그룹을 4자리 16진수로 맞춰준다.
groups = [group.rjust(4, '0') for group in groups]
# ::을 만나면 0으로 채워진 그룹을 삽입한다.
if '' in groups:
index = groups.index('')
groups[index:index+1] = ['0000'] * (9 - len(groups))
# 각 그룹을 결합하여 완성된 IPv6 주소를 반환한다.
return ':'.join(groups)
# 예시
print(expand_ipv6_address('2001:db8:85a3::8a2e:370:7334')) # 2001:0db8:85a3:0000:0000:8a2e:0370:7334
위 코드는 다음과 같은 단계로 동작합니다.
- 입력받은 주소를 그룹으로 나누어 리스트로 저장합니다.
- 각 그룹을 4자리 16진수로 맞춰줍니다.
- ::을 만나면 0으로 채워진 그룹을 삽입하여 그룹의 수를 8개로 맞춥니다.
- 각 그룹을 결합하여 완성된 IPv6 주소를 반환합니다.
이렇게 작성하면, 주어진 IPv6 주소가 축약된 경우에도 정확하게 풀 IPv6 주소로 변환됩니다.
🧑🏻💻 SOMJANG
틀렸어
💻 ChatGPT
죄송합니다. 다시 확인해 보았습니다. 위 코드에는 두 가지 문제가 있었습니다.
- 마지막 그룹이 생략되지 않은 경우 그룹 갯수가 총 8개가 되도록 0을 추가해주어야 합니다.
- 생략된 그룹이 여러개일 경우 :: 표기법을 사용할 때 생략된 그룹의 갯수를 구하고, 그 수만큼 0을 추가해주어야 합니다.
아래는 수정된 코드입니다.
ipv6 = input().split(':')
if len(ipv6) == 8: # 생략되지 않은 경우
print(':'.join([i.zfill(4) for i in ipv6]))
else: # 생략된 그룹이 있는 경우
null_group_count = ipv6.count('')
ipv6 = [i if i != '' else '0000' for i in ipv6]
ipv6_length = len(ipv6)
null_group = '0000:'
full_ipv6 = ':'.join(ipv6)
full_ipv6 = full_ipv6.replace('::', ':' + null_group * (7 - ipv6_length + null_group_count))
full_ipv6 = full_ipv6.rstrip(':')
print(full_ipv6)
이 코드는 다음과 같이 작동합니다.
- 입력받은 IPv6 주소를 ':'를 기준으로 나눕니다.
- 그룹의 갯수가 8개인 경우 각 그룹을 4자리로 채워주고 ':'로 이어서 출력합니다.
- 그룹의 갯수가 8개가 아닌 경우 생략된 그룹의 갯수를 구하고, 각 그룹이 4자리가 되도록 0을 채워줍니다.
- IPv6 주소를 다시 ':'로 이어붙인 뒤 '::'가 나오는 부분을 찾아서 생략된 그룹의 수에 따라 0을 채워줍니다.
- ':'로 끝나는 부분은 0을 추가하지 않아야 하므로, 끝의 ':'를 제거합니다.
- 최종적으로 변환된 IPv6 주소를 출력합니다.
계속 틀렸다고 알려주어도 계속 틀린 답변만 알려주어 여기서 그만 두었습니다.
( 위 코드는 ::1 -> 0000:0000:1 )
가장 쉽게 풀 줄 알았는데 만우절이어서 그런지 계속 거짓말만 하고 제대로 풀지 못하여 의아했던 문제였습니다.
읽어주셔서 감사합니다.
🍪 만우절이어서 거짓말 하는거야? - 네!
하지만 이것도 실패!
실패 실패 대실패!
'Programming > 코딩 1일 1문제' 카테고리의 다른 글
[BaekJoon] 27889번 : 특별한 학교 이름 (Python) (0) | 2023.04.04 |
---|---|
[Programmers] 2차원으로 만들기 (Python) (feat.ChatGPT) (0) | 2023.04.02 |
[BaekJoon] 10425번 : 피보나치 인버스 (Python) (feat. ChatGPT) (0) | 2023.03.30 |
[leetCode] 796. Rotate String (Python) (feat.ChatGPT) (0) | 2023.03.28 |
[leetCode] 2490. Circular Sentence (Python) (feat.ChatGPT) (0) | 2023.03.27 |