파이썬으로 수학문제 풀기- 프로젝트 오일러(project euler, 22번부터)

프로젝트 오일러 22번 - 알파벳-숫자변환

알파벳을 숫자로 변환해서, 특정 연산을 하는 문제입니다.

약 5천개의 영문이름이 있고, 모든 알파벳을 A=1,B=2,,, 의 숫자로 치환해서, 합계를 계산한 다음, 각 이름의 index값을 합계와 곱해서, 누적한 값을 계산하는게 문제입니다.

예를 들어, 리스트의 첫번째이름은 MARY 이고, 이를 숫자로 변환하면, M=13,A=1,R=18 ,Y=25 이고, 합은 13+1+18+25=57이고, 인덱스는 5000개중에 1번이기 때문에, 57*1=57입니다. (실제 계산은 알파벳순으로 정렬을 해야해서, 인덱스값이 달라집니다.)

어렵진 않은데, 텍스트를 잘 처리하는게 관건이군요.

 

파일 불러오기
filename = 'q022_data.txt'
with open(filename) as file_object:
    contents = file_object.read()
print(contents)
"MARY","PATRICIA","LINDA","BARBARA","ELIZABETH","JENNIFER","MARIA","SUSAN","MARGARET","DOROTHY","LISA","NANCY","KAREN","BETTY","HELEN","SANDRA","DONNA","CAROL","RUTH","SHARON","MICHELLE","LAURA","SARAH","KIMBERLY","DEBORAH","JESSICA","SHIRLEY","CYNTHIA","ANGELA","MELISSA","BRENDA","AMY","ANNA","REBECCA","VIRGINIA","KATHLEEN","PAMELA","MARTHA","DEBRA","AMANDA","STEPHANIE",,,,,,,,,,,,,,

텍스트 안의 따옴표(")가 같이 포함된 상태이고, 하나의 긴 문자열입니다. 숫자로 치환작업을 할려면, 따옴표는 제거하고 컴마(,)를 기준으로 split을 하는게 좋을거 같습니다.

 

텍스트 처리
contents=contents.replace('"','')  #따옴표를 공백으로 치환
print(contents.isupper()) # 모두 대문자인지 확인
names=contents.split(',')     #콤마를 기준으로 (,)split
print(names)
True
['MARY', 'PATRICIA', 'LINDA', 'BARBARA', 'ELIZABETH', 'JENNIFER', 'MARIA', 'SUSAN', 'MARGARET', 'DOROTHY', 'LISA', 'NANCY', 'KAREN', 'BETTY', 'HELEN', 'SANDRA', 'DONNA', 'CAROL', 'RUTH', 'SHARON', 'MICHELLE', 'LAURA', 'SARAH', 'KIMBERLY', 'DEBORAH', 'JESSICA', 'SHIRLEY', 'CYNTHIA', 'ANGELA', 'MELISSA', 'BRENDA', 'AMY', 'ANNA', 'REBECCA', 'VIRGINIA', 'KATHLEEN', 'PAMELA', 'MARTHA',,,,,,,,,,

 따옴표는 공백으로 치환을 해주었고, 컴마를 기준으로 split을 했습니다. split을 하고 나면, 데이터형은 List형으로 전환됩니다. 그리고 아스키코드를 사용해서 숫자로 바꿀건데, 이름에 소문자가 섞여 있는지를 확인하기 위해서, contents.isupper() 명령을 실행해서 True가 나오는지 확인해주었습니다.

여기까지를 축약해서 표현하면 아래와 같습니다.

with open('q022_data.txt') as file:
    names = file.read().replace('"','').split(',')

 

리스트 정렬
names.sort()     #list 정렬
for idx,val in enumerate(names):
    print(idx+1,val)
1 AARON
2 ABBEY
3 ABBIE
4 ABBY
5 ABDUL
,,,,,,,,,,,, 
5159 ZORA
5160 ZORAIDA
5161 ZULA
5162 ZULEMA
5163 ZULMA

알파벳순으로 정렬해주고, for문으로 루프를 만들어 주었습니다. for문안에 enumerate()를 사용하게 되면, iter 나 sequence형(str,list,tuple등) 데이타 타입에 index를 자동으로 생성해줍니다. 위 코드에서는 idx변수에 index가 할당되고, val변수에 각 names의 값들이 할당됩니다.

 

숫자로 변환(아스키코드 이용)
for idx,val in enumerate(names):
    print(idx+1,val,end=' ')
    for i in val:
        print(ord(i)-64,end=',')  #아스키코드를 이용하여 숫자로 변환
    print()
1 AARON 1,1,18,15,14,
2 ABBEY 1,2,2,5,25,
3 ABBIE 1,2,2,9,5,
4 ABBY 1,2,2,25,
,,,,,,,
5160 ZORAIDA 26,15,18,1,9,4,1,
5161 ZULA 26,21,12,1,
5162 ZULEMA 26,21,12,5,13,1,
5163 ZULMA 26,21,12,13,1,

 ord(i) 명령이 아스키 코드값을 반환 해주는 명령입니다. 대문자 A가 65번이기 때문에, 64를 빼주면, 1부터 시작하는 연속된 값을 얻을수 있습니다.

 

합계 계산
grand_total =0
for idx,val in enumerate(names):
    print(idx+1,val,end=' ')
    total=0
    for i in val:
        print(ord(i)-64,end=',')
        total=total+ord(i)-64
    print("total:",total,end=',')
    grand_total+=total*(idx+1)  #누적
    print(grand_total)
1 AARON 1,1,18,15,14,total: 49,49
2 ABBEY 1,2,2,5,25,total: 35,119
3 ABBIE 1,2,2,9,5,total: 19,176
4 ABBY 1,2,2,25,total: 30,296
5 ABDUL 1,2,4,21,12,total: 40,496
,,,,,,,,,,,
5160 ZORAIDA 26,15,18,1,9,4,1,total: 74,870109087
5161 ZULA 26,21,12,1,total: 60,870418747
5162 ZULEMA 26,21,12,5,13,1,total: 78,870821383
5163 ZULMA 26,21,12,13,1,total: 73,871198282

 

댓글

댓글 본문
작성자
비밀번호
버전 관리
nomadlife
현재 버전
선택 버전
graphittie 자세히 보기