코드 출현 2015 - 1일차

6951 단어 adventofcodepython
이것은 Python에서 Advent of Code부터 현재까지의 각 2015 (AoC) 문제를 해결하는 방법을 보여주는 일련의 게시물입니다. 아이디어는 코딩을 연습하고 개선 방법을 살펴보는 것입니다. 각 챌린지를 완료한 후 다른 사람들의 제출물을 살펴보고 퍼즐을 풀 수 있는 더 많은 Pythonic 방법이 있는지, 그리고 골퍼들이 어떤 작은 해결책을 내놓았을지 알아보겠습니다.

파이썬 코드



단순히 구문적으로 올바른 것과는 반대로 사용하려는 방식으로 언어를 사용하는 Python 작성 방법이 있습니다. 몇 년 동안 어떤 형태로든 Basic으로 코딩하면서 Python에 입문했기 때문에 많은 Python이 번역된 Basic처럼 읽을 수 있습니다. 예를 들어 몇 년 동안 손을 대본 후에도 여전히 반복자에 대해 배울 것이 많습니다. 언어에 대한 새로운 통찰력을 제공하는 Advent 퍼즐에 대한 다른 Python 솔루션을 찾는 것을 좋아합니다.

골프



아무리 Advent 퍼즐이 어려울 수 있지만 절대적으로 가장 짧은 코드를 작성하려는 코더의 하위 집합이 항상 있을 것입니다. 이것은 항상 가장 효율적인 코드는 아니며, 매우 불투명한 경향이 있어 유지 관리가 어렵기 때문에 프로덕션에서는 종종 쓸모가 없습니다. 그러나 20줄을 작성한 퍼즐을 해결하는 코드 한 줄을 우연히 발견하는 것은 기쁨이 될 수 있습니다.

스포일러?



상상할 수 있는 거의 모든 언어로 모든 AoC 퍼즐에 대해 Reddit에 solution megathreads이 있습니다. 그리고 제가 시작한 퍼즐은 거의 7년이 되었기 때문에 누군가를 위해 어떤 것도 망치고 있다고 생각하지 않습니다.

1일차



그런 다음 퍼즐을 계속 진행합니다. 각 퍼즐은 두 부분으로 나뉩니다. 파트 1을 해결하면 파트 2가 잠금 해제되고 각 파트를 해결하면 별을 받습니다. 대림절 말의 목표는 별 50개를 갖는 것입니다. 일반적으로 퍼즐의 두 부분에 대한 입력 역할을 하는 테스트 데이터 파일이 있습니다. 즉, 거의 모든 솔루션에서 코딩의 첫 번째 비트는 파일에서 퍼즐 데이터를 로드하는 것입니다.

파일은 종종 다음과 같이 로드할 수 있는 단일(매우 긴) 문자열입니다.

with open('input.txt') as f:
    data = f.read()


또는 파일에 여러 줄의 데이터가 포함되며 다음과 같이 목록에 로드하는 경향이 있습니다.

with open('input.txt') as f:
    data = [line for line in f]


1 부



퍼즐은 일반적으로 산타와 그의 엘프에 대한 이야기 ​​스타일로 작성됩니다. 다음은 Day 1의 장면 설정 방법입니다.



내 첫 번째 생각은 단순히 문자열( for char in data )을 반복하는 것이었지만 Python의 문자열 라이브러리가 다른 문자열 안에 있는 한 문자열의 인스턴스를 계산할 수 있다는 것을 기억했습니다.

floor = data.count('(') - data.count(')')


그리고 그것이 공평하게 단순한 퍼즐로 청구되었던 파트 1의 끝이었습니다! 더 Pythonic 접근 방식에 대한 다른 솔루션을 살펴보았을 때 주요 대안은 문자열의 replace() 함수를 사용하여 '('를 '+1'로, ')'를 '-1'로 바꾸고 eval()를 실행하는 것이었습니다. 결과 문자열:

eval(data.replace('(', '+1').data(')', '-1'))


2 부



두 번째 부분은 거의 같은 작업을 수행하지만 지하실에 도달하면 중지해야 합니다.



내 생각에 이것은 캐릭터를 반복하고 지하실에 도달하면 루프를 종료하는 것을 의미했습니다.

floor = 0
pos = 0
for char in data:
    pos += 1
    if char == '(':
        floor += 1
    else:
        floor -= 1
    if floor == -1:
        break
print(str(pos))


이것은 확실히 효과가 있었고 얼마나 개선될 수 있는지 너무 걱정하지 않을 만큼 충분히 빠르게(<4ms) 실행되었습니다...

하지만 골프 용어로 보면 Reddit user에서 이것이 눈에 띄었습니다.

list(itertools.accumulate([1 if b == '(' else -1 for _
   x in data])).index(-1) + 1


이전에 accumulate() function을 본 적이 없지만 여기에서 수행하는 작업은 전체 문자열을 살펴보고 이전 목록을 살펴볼 때 새 목록에 층 번호를 저장한 다음 인덱스( +1) 처음으로 -1을 쳤습니다. 그것은 깔끔한 하나의 라이너이지만 긴 지침 세트의 처음 몇 단계에서 지하실에 도달하면 약간 낭비가 될 수 있습니다 ...

좋은 웹페이지 즐겨찾기