2012-09-29 3 views
2

2의 제곱을 계산하지만 10의 제곱을 사전으로 저장하는 코드를 작성하려고합니다 (예 : 2^9).이미 존재하지 않는 사전에 항목 추가하기

{0:2, 1:1, 2:5} 

5 * 10^2 + 1 * 10^1 + 2 * 10^0으로 저장됩니다.

그래서 현재 내가

def foo(): 
    result={0:2} 
    for i in range(2,10): 
     for p in result.keys(): 
      result[p]*=2 
     for p in result.keys(): 
      if result[p]/10 != 0: 
       result.setdefault(p+1,result[p]/10) 
       result[p] = result[p] % 10 

같은이 문제는 그것은 result[p+1]에 있던 어떤 덮어

result.setdefault(p+1,result[p]/10) 

입니다. 나는 사전을 검사하고 필요하다면 새로운 키를 "초기화"하는 것이 가능하다는 것을 알고 있지만, 그것을 수행하는 더 우아한 방법이 있습니까? 결과를 충분히 길게 초기화 할 수는 있지만, 얼마나 오래 "충분히 길다"는 것을 반드시 알 필요는 없으므로 비행 중에도 확장하는 것이 더 나을 것 같습니다.

는 기본적으로 나는

for p in result.keys(): 
    if result[p]/10 != 0: 
     if result[p+1] exists: 
      result[p+1]+=result[p]/10 
     else: 
      create result[p+1] and set its value to result[p]/10 

의 라인을 따라 뭔가 어떤 도움이 많이 감사합니다 싶습니다!

+0

게시 된 코드는 'result [p] 'result [p + 1] '이 아닙니다. – Amber

+0

빠른 질문 : 왜 [2, 1, 5]리스트 대신에'{0 : 2, 1 : 1, 2 : 5}'를 사용하고 있습니까? 어느 쪽이든,'x [0] == 2','x [1] == 1','x [2] == 5'. – abarnert

+0

@Amber : 죄송합니다. 내 목표는 {0:16}을 {0 : 6, 1 : 1}로 설정했기 때문에 둘 다 변경해야한다는 것을 이해합니다. – acs

답변

2

파이썬 3. 파이썬 2 result[p] == 0result[p] < 10한다면, 당신은 메인 루프를 통해 때마다 무슨 일을하는지 것은 : 이중 각 숫자가, 그 다음 자리에 여분의 수만을 가지고 다니십시오. 문제는 가장 높은 자릿수의 경우 다음 자릿수가 존재하지 않는다는 것입니다.

그래서 여기에 해결책이 있습니다. 2 이외의 다른 전원에서는 작동하지 않지만 해결책은 아래에 나와 있습니다.

def foo(): 
    result={0:2} 
    for i in range(2,10): 
     for p in result.keys(): 
      result[p]*=2 
     for p in result.keys()[:]: 
      if result[p]/10 != 0: 
       result[p+1] = result.get(p+1, 0) + result[p]/10 
       result[p] = result[p] % 10 

원래 코드와 두 가지 주요 변경 사항이 있습니다.

첫 번째로 result.keys()의 끝에 [:]을 추가하여 현재 키가 아닌 루프 앞에 사전의 키 집합을 반복합니다. 그 이유는 마지막 숫자가 5보다 크면 사전에 새 키를 추가 할 것이므로 반복하는 동안 키를 사용하지 않아도된다는 것입니다. (왜? 몇 가지 이유가 있지만 사전은 임의적 인 순서이며, 키를 추가 할 때마다 전체 주문이 변경 될 수 있습니다. 나중에도 중요합니다.)

두 번째로 원래 질문 : r_p을 저장할 것인지 또는 기존 값에 r_p을 추가 할 것인지를 결정하기 위해 if p+1 in result을 확인하지 않아도됩니까?

카운트를 처리 할 때 collection.Counter을 사용합니다. 이는 dict과 같으며 정수 만 저장하며 누락 된 키의 값은 0입니다.그렇지 않은 경우 일반적으로 collection.defaultdict을 사용합니다. 누락 된 모든 키가 갖는 기본값을 지정할 수 있다는 점을 제외하면 dict과 같습니다. Counter 또는 defaultdict을 사용하면 필요한 것은 result[p+1] += result[p]/10입니다.

그러나 나는 다른 대안을 사용했습니다 : 에 get 메서드를 사용 했으므로 기본값을 지정할 수 있습니다. 이유는 나중에 설명 하겠지만 일반적으로 get에 도달하면 defaultdict 또는 Counter을 대신 입력해야합니다.

그래서, 지금은 실행, 작업, 2의 거듭 제곱을위한 그러나 그것은 두 가지 이유로, 다른 힘에 대해 작동하지 않습니다 수 있습니다 :

첫째, 우리는이 임의의 순서로 수행하고 있습니다. 2의 거듭 제곱의 경우, 가장 많이 휴대 할 수있는 것은 1이며, 1이 다음 자리가 올라갈 지 여부에 영향을 미칠 수있는 방법은 없습니다. (8은 나르지 않으며 8 + 1도 없을 것이며, 이제는 9를 얻는 방법이 있습니다.) 그러나 다른 어떤 힘을 위해서, 그것은 사실이 아닙니다.

dict으로 시작하여 적은 수의 작은 키 (실제로는 작은 키를 추가 할 경우) (CPython 2.7 및 3.2 이상)가 발생하므로 간단한 테스트에서이를 알지 못합니다. 해시 값은 있지만 작은 정수는 자신을 해시 된 순서대로 정렬하고 아무 것도 삭제하지 않으면 dict은 순서대로 반복 (인쇄)됩니다. 그러나 일반적으로 주문은 예측할 수 없으며 사용자가 신뢰할 수 없습니다.

이 문제의 해결책은 키가 추가 된 순서대로 반복하는 collections.OrderedDict을 사용하는 것입니다. 그래서 defaultdict 또는 Counter을 사용하지 않으려는 것입니다. OrderedDict으로 전환해야하는 경우 유일한 옵션은 get입니다.

두 번째로, 지수가 10을 초과하면 100을 수행해야 할 수도 있습니다. 즉, 10을 지니고 있다는 의미이므로 다음 자릿수가 0이더라도 그 자리가 계속 이어집니다. 즉, 미리 키를 복사하십시오. 예를 들어, 우리가 75의 힘을 발휘한다고 가정 해 보겠습니다. {0:5, 1:7}으로 시작하십시오. 각 자릿수를 75로 곱하면 {0:375, 1:525}가됩니다. 이제 37 : {0:5, 1:562}을 휴대하십시오. 이제 56 : {0:5, 1:2, 2:56}을 휴대하십시오. [0, 1]은 원래 키의 복사본을 반복하기 때문에 5를 수행 할 기회가 없습니다.

이 문제를 해결하기 위해 최선을 다합니다.

그러나 기존의 장소를 수정하는 대신 새 사전을 만드는 것이 좋습니다. 그런 다음 이러한 모든 문제를 해결할 수 있습니다. (일반적으로 상태를 변경하는 대신 순수한 함수를 사용하면 많은 문제가 발생하지만 추가 복사 비용이 발생합니다.)

def double(d): 
    result = Counter() 
    for p in d: 
     result[p] += d[p] % 10 
     result[p+1] += d[p]/10 
    return result 

digits={0:2} 
for i in range(2,10): 
    for p in digits: 
     digits[p]*=2 
    digits = double(digits) 
+0

정교한 답변을 해주셔서 너무 감사드립니다! 여기에는 많은 개념들이 있습니다 ... – acs

1

당신은 in 구문을 사용하여 키의 존재 여부를 확인할 수 있습니다

또한
from collections import Counter 

result = Counter() 

for p in result.keys()[:]: 
    r_p = result[p]/10 

    if r_p != 0: 
     result[p + 1] += r_p 

, 당신의 상태는 다음과 같습니다 자동이 수행 Counter를 사용할 수 있습니다,

for p in result.keys()[:]: 
    r_p = result[p]/10 

    if r_p != 0: 
     if p + 1 in result: 
      result[p + 1] += r_p 
     else: 
      result[p + 1] = r_p 

또는 좀 이상하다. result[p]/10 == 0

+0

+1에 대한 '카운터'.하지만 첫 번째 버전은'if :'/'else :'루프 대신에'result [p + 1] = result.get (p + 1, 0) + r_p'처럼 훨씬 더 간단합니다. – abarnert

+0

@abarnert : 감사합니다. 나는'.get()'을 더 자주 사용하기 시작해야한다. – Blender

+0

글쎄,'get'에 도달하는 시간의 절반은'Counter','defaultdict','try :'/'d [key] ...'/'except :'가 어쨌든 더 나은 대답이라는 것을 깨닫게됩니다 ... – abarnert

관련 문제