파일에서 한 글자씩 스캔하는 방법

네이버 지식인에서 줏어든 문제 중에 이런게 있었다. 한글과 영문, 기호가 섞여 있는 내용으로 된 매우 큰 텍스트 파일이 있는데, 여기서 세 글자씩 가져와서 처리하고 싶다는 것이다.

이런 경우라면 텍스트 파일을 통째로 읽어들여서 큰 문자열로 로드한 후 앞에서부터 세글자씩 subscript해서 사용하면 된다. 그런데 문제는 이 파일이 매우 크다는 것이다. 그래서 이진 파일로 조금씩 읽어서 어떻게 한글/영문 관계 없이 세 글자씩 묶어서 처리할 수 있을까? 해당 텍스트 파일의 인코딩이 UTF8이라는 전제에서 접근해보자.

파일에서 한 글자씩 스캔하는 방법 더보기

오일러 프로젝트 82

(참고: 이 문제는 81번 문제의 좀 더 어려운 버전입니다)

아래와 같은 5×5 행렬이 있습니다. 맨 왼쪽 열의 아무곳에서나 출발하여 위/아래/오른쪽으로만 움직이면서 맨 오른쪽 열까지 갈 때, 빨갛게 표시된 경로의 합이 994로 가장 작습니다.

31kB 짜리 파일 matrix.txt에는 80×80 행렬의 정보가 들어있습니다. 위와 같은 방법으로 이 행렬의 맨 왼쪽 열에서 출발하여 오른쪽 열까지 갈 때, 경로 합의 최소값은 얼마입니까?

오일러 프로젝트 82 더보기

C로 작성된 함수를 파이썬에서 사용하기

표준 파이썬 해석기는 C로 만들어져 있다. 그리고 C에는 동적 라이브러리를 링크하여 사용할 수 있는 기능이 마련되어 있다. 따라서 표준 파이썬 해석기를 만드는 사람들도 실행시간에 C로 만들어진 동적 라이브러리를 링크하여 사용할 수 있을 것이라는 생각을 당연히 했을 것이고, 그 결과 ctypes 라는 라이브러리가 탑재되어 있다. 

C로 작성된 함수를 파이썬에서 사용하기 더보기

파이썬의 숫자판별함수

파이썬에서 주어진 문자열이 숫자로 되어 있는지를 검사하는데에는 흔히 문자열의 메소드인 isdigit()을 사용한다. 그런데 파이썬의 문자열 타입을 조사해보면 같은 기능을 하는 거 같은 메소드가 무려 3종 세트로 알차게 구성되어 있는 것을 알 수 있다. 바로 isdigit(), isnumeric(), isdecimal() 이다. 그렇다면 이 세 가지 함수는 왜 각각 존재하는 것일까?

급한 사람을 위한 빠른 결론 – int 타입으로 안전하게 변환하고 싶다면 isdigit() 대신에 isdecimal()을 사용하여 검사하라

이 세 종류의 메소드는 문자값 중에서 ‘숫자’를 찾는데 사용된다. 우리 말에서 ‘숫자’라는 개념은 사실 모호한데 (응? 이게 왜 모호하다는 거지?) 우리는 일상생활에서 흔히 0, 1, 2, 3, .. , 9의 10개의 숫자를 사용하고 있다. 즉 우리는 10개의 ‘숫자’만을 갖고 있는 셈이다. 그런데 사실은 이게 좀 간단한 문제가 아닌거라는게 문제다.

흔히 사용하는 isdigit() 메소드를 보자. 말 그대로 문자열에 사용된 글자들이 ‘digit’인지를 확인하는 것이다. 아 그러니까 우리는 ‘이게 숫자로 된 문자열이네’라는 것을 알 수 있을 거라 추측한다. 그리고 digit, numeric, decimal은 다같이 ‘숫자’로 번역되기 때문에 이 사이의 차이가 뭔지를 정확하게 모르게 된다.

다시 이번에는 decimal 을 보자. 이것이 우리가 흔히 생각하는 ‘숫자’와 같은 개념이다. 즉 '0123456789'의 구성으로 이루어진 10개의 글자. 말 그대로 int 타입으로 즉시 변환이 가능한 리터럴을 구성하는 문자를 말한다.

아니 그렇다면 digit은 뭐길래? 특수 기호 중에서 어깨위에 제곱이나 세제곱을 표시하는 문자가 있다. digit은 이렇게 ‘숫자처럼 생긴’ 모든 글자를 다 숫자로 치는 것이다. 다음 예를 보면 digit과 decimal의 차이를 알 수 있을 것이다.

x = '3²'
x.isdigit()
# True
x.isdecimal()
# False
int(x)
# ERROR!!!!

위 예에서 볼 수 있는  에서 두 번째 ² 는 특수문자이며, 우리가 흔히 키보드로 입력하는 2와는 다른 코드 값이다. 이는 decimal 값을 표기하는데 사용하는 문자는 아니지만, 사람이 읽었을 때 숫자로 인지하기 때문에 isdecimal()에서는 False가 리턴되고, isdigit()에서는 True가 리턴된다.

따라서 만약 어떤 텍스트가 int 값으로 변환이 가능한지를 검사하고자 한다면 isdigit()을 사용해서는 안되며, isdecimal()을 써야 할 것이다.

그럼 isnumeric()은 어떤 것일까?

numeric 하다는 것은 보다 넓은 의미인데, isdigit()은 단일 글자가 ‘숫자’ 모양으로 생겼으면 True를 리턴한다고 했다. isnumeric()은 숫자값 표현에 해당하는 텍스트까지 인정해준다. 예를 들어 “½” 이런 특수문자도 isnumeric()에서는 True로 판정된다.