부울 식을 작성하는 더 간결하거나 비열한 방법이 있습니까?
a + b == c or a + c == b or b + c == a
나는 생각해 냈다
a + b + c in (2*a, 2*b, 2*c)
그러나 그것은 조금 이상합니다.
부울 식을 작성하는 더 간결하거나 비열한 방법이 있습니까?
a + b == c or a + c == b or b + c == a
나는 생각해 냈다
a + b + c in (2*a, 2*b, 2*c)
그러나 그것은 조금 이상합니다.
답변:
파이썬의 선을 보면 내 것을 강조합니다.
Tim Peters의 Python Zen
못생긴 것보다 아름답습니다.
암시적인 것보다 명시적인 것이 좋습니다.
단순보다 복잡합니다.
복잡한 것이 복잡한 것보다 낫습니다.
평평한 것이 중첩보다 낫습니다.
스파 스가 밀도보다 낫습니다.
가독성이 중요합니다.
특별한 경우는 규칙을 어길만큼 특별하지 않습니다.
실용성은 순도를 능가하지만.
오류가 자동으로 전달되지 않아야합니다.
명시 적으로 침묵하지 않는 한.
모호함에 직면하여 추측하려는 유혹을 거부하십시오.
그것을하는 명백한 방법이 있어야합니다.
네덜란드 인이 아니라면 처음에는 그 방법이 명확하지 않을 수 있습니다.
지금보다 결코 낫습니다.
결코 결코 낫지 않지만바로 지금
구현이 설명하기 어렵다면 나쁜 생각입니다.
구현이 설명하기 쉬운 경우 좋은 생각 일 수 있습니다.
네임 스페이스는 훌륭한 아이디어 중 하나입니다. 더 많은 것을 해보자!
가장 Pythonic 솔루션은 가장 명확하고 간단하며 설명하기 쉬운 솔루션입니다.
a + b == c or a + c == b or b + c == a
더 좋은 점은이 코드를 이해하기 위해 Python을 알 필요조차 없습니다! 그것은이다 그 쉬운. 이것은 예약없이 최상의 솔루션입니다. 다른 것은 지적 자위 행위입니다.
더구나, 이것은 제안 된 것 중 단 하나 뿐인 것이기 때문에 이것이 가장 성능이 좋은 솔루션 일 것입니다. 인 경우 a + b == c
단일 추가 및 비교 만 수행됩니다.
의 세 가지 평등을 해결 :
a in (b+c, b-c, c-b)
파이썬에는 시퀀스의 모든 요소를 처리 하는 any
함수가 or
있습니다. 여기에서는 문장을 3 요소 튜플로 변환했습니다.
any((a + b == c, a + c == b, b + c == a))
참고 or
개별 조건을 계산하는 것은 비싼 경우가 더 좋을 수도 원래의 구조를 유지하기 때문에, 단락이다.
any()
및 all()
단락도.
any
도 실행 되기 전에 존재 합니다.
any
그리고 주어진 반복성 all
을 검사 하는 과정을 "단락" ; 그러나 iterable이 제너레이터가 아닌 시퀀스 인 경우 함수 호출이 발생하기 전에 이미 완전히 평가되었습니다 .
any
, 단일 들여 쓰기 ):
에서 if
수학이 포함될 때 가독성을 위해 많은 도움이 문)
당신이 양수만을 다루고 있다는 것을 안다면, 이것은 효과가 있으며 매우 깨끗합니다.
a, b, c = sorted((a, b, c))
if a + b == c:
do_stuff()
내가 말했듯이, 이것은 양수에만 적용됩니다. 그러나 그들이 긍정적이 될 것임을 안다면 이것은 코드에서 직접 함수가 아닌 매우 읽기 쉬운 솔루션 IMO입니다.
이 작업을 수행하면 약간의 반복 계산이 수행 될 수 있습니다. 그러나 성과를 목표로 지정하지 않았습니다.
from itertools import permutations
if any(x + y == z for x, y, z in permutations((a, b, c), 3)):
do_stuff()
또는 permutations()
반복 계산이 없거나 없을 가능성 :
if any(x + y == z for x, y, z in [(a, b, c), (a, c, b), (b, c, a)]:
do_stuff()
아마도 이것이나 다른 솔루션을 함수에 넣을 것입니다. 그런 다음 코드에서 함수를 깨끗하게 호출 할 수 있습니다.
개인적으로 코드에서 더 많은 유연성이 필요하지 않으면 질문에 첫 번째 방법을 사용합니다. 간단하고 효율적입니다. 여전히 함수에 넣을 수 있습니다.
def two_add_to_third(a, b, c):
return a + b == c or a + c == b or b + c == a
if two_add_to_third(a, b, c):
do_stuff()
그것은 꽤 파이썬 적이며, 아마도 가장 효율적인 방법 일 것입니다 (추가 함수 호출은 제외). 실제로 문제를 일으키지 않는 한 어쨌든 성능에 대해 너무 걱정하지 않아도됩니다.
세 개의 변수 만 사용하는 경우 초기 방법 :
a + b == c or a + c == b or b + c == a
이미 매우 pythonic입니다.
더 많은 변수를 사용할 계획이라면 다음과 같은 추론 방법을 사용하십시오.
a + b + c in (2*a, 2*b, 2*c)
매우 영리하지만 이유를 생각할 수 있습니다. 왜 이것이 작동합니까?
간단한 산술을 통해 우리는 다음을 볼 수 있습니다.
a + b = c
c = c
a + b + c == c + c == 2*c
a + b + c == 2*c
그리고 이것은 그 예는 동일합니다 의미, a, b 또는 c에 대해 true를 유지해야한다 2*a
, 2*b
또는를 2*c
. 이것은 여러 변수에 해당됩니다.
따라서 이것을 빠르게 작성하는 좋은 방법은 단순히 변수 목록을 가지고 두 배의 값 목록과 합계를 확인하는 것입니다.
values = [a,b,c,d,e,...]
any(sum(values) in [2*x for x in values])
이런 식으로 방정식에 변수를 더 추가하려면 'n'방정식을 쓰지 말고 'n'새로운 변수로 값 목록을 편집하면됩니다.
a=-1
, b=-1
, c=-2
, 다음 a+b=c
,하지만 a+b+c = -4
하고 2*max(a,b,c)
있다-2
abs()
호출로 후추를 뿌린 후에 는 OP의 스 니펫보다 Pythonic입니다 (실제로 읽기가 쉽지 않습니다).
any(sum(values) == 2*x for x in values)
것입니다.
다음 코드를 사용하여 각 요소를 다른 요소의 합계와 반복적으로 비교할 수 있습니다.이 요소는 해당 요소를 제외하고 전체 목록의 합계에서 계산됩니다.
l = [a,b,c]
any(sum(l)-e == e for e in l)
[]
이 두 번째 줄에서 브래킷 을 제거하면 , 이것도 원래처럼 단락됩니다 or
...
any(a + b + c == 2*x for x in [a, b, c])
OP의 제안에 매우 가깝습니다
시도하고 단순화하지 마십시오. 대신 함수로 수행중인 작업의 이름을 지정하십시오 .
def any_two_sum_to_third(a, b, c):
return a + b == c or a + c == b or b + c == a
if any_two_sum_to_third(foo, bar, baz):
...
조건을 "영리한"것으로 바꾸면 더 짧아 질 수 있지만 더 읽기 쉽지는 않습니다. 그러나이 세 가지 조건을 한눈에 확인하는 이유 를 아는 것은 까다로워서 읽기 쉽지 않은 방법으로 남겨 두십시오 . 이것은 당신이 확인하는 것을 절대적으로 명확하게 만듭니다.
성능과 관련하여이 접근 방식은 함수 호출의 오버 헤드를 추가하지만 반드시 해결해야하는 병목 현상을 발견하지 않으면 성능에 대한 가독성을 희생하지 않습니다. 일부 영리한 구현은 일부 상황에서 일부 함수 호출을 최적화하고 인라인 할 수 있으므로 항상 측정하십시오.
파이썬 3 :
(a+b+c)/2 in (a,b,c)
(a+b+c+d)/2 in (a,b,c,d)
...
여러 변수로 확장됩니다.
arr = [a,b,c,d,...]
sum(arr)/2 in arr
그러나 일반적으로 세 개 이상의 변수가 없으면 원래 버전을 더 읽기 쉽다는 데 동의합니다.
[x for x in range(pow(2,30)) if x != ((x * 2)/ pow(2,1))]
(a+b-c)*(a+c-b)*(b+c-a) == 0
두 항의 합이 세 번째 항과 같으면 요인 중 하나가 0이되어 전체 제품이 0이됩니다.
(a+b<>c) && (a+c<>b) && (b+c<>a) == false
어때요?
a == b + c or abs(a) == abs(b - c)
변수가 부호없는 경우에는 작동하지 않습니다.
코드 최적화 관점에서 (적어도 x86 플랫폼에서는) 이것이 가장 효율적인 솔루션 인 것 같습니다.
최신 컴파일러는 abs () 함수 호출을 인라인하고 CDQ, XOR 및 SUB 명령어 의 영리한 시퀀스를 사용하여 부호 테스트 및 후속 조건부 분기를 피 합니다 . 따라서 위의 높은 수준의 코드는 대기 시간이 짧고 처리량이 많은 ALU 명령어와 두 개의 조건부만으로 표현됩니다.
fabs()
사용할 수 있다고 생각 float
합니다.).
Alex Varga가 제공 한 "a in (b + c, bc, cb)"솔루션은 작고 수학적으로 아름답지만 다음 개발자가 코드의 목적을 즉시 이해하지 못하기 때문에 실제로 그런 식으로 코드를 작성하지는 않습니다. .
마크 랜섬의 솔루션
any((a + b == c, a + c == b, b + c == a))
보다 명확하지만 간결하지는 않습니다.
a + b == c or a + c == b or b + c == a
다른 사람이보아야 할 코드를 작성할 때, 또는 내가 작성할 때 생각했던 것을 잊었을 때 오랜 시간을보아야 할 코드를 작성할 때 너무 짧거나 영리한 것이 좋은 것보다 더 해가되는 경향이 있습니다. 코드를 읽을 수 있어야합니다. 간결함은 훌륭하지만 간결하지는 않지만 다음 프로그래머가 이해할 수 없습니다.
요청은 더 간결하거나 더 많은 pythonic에 대한 것입니다-나는 더 컴팩트하게 손을 시험해 보았습니다.
주어진
import functools, itertools
f = functools.partial(itertools.permutations, r = 3)
def g(x,y,z):
return x + y == z
원본보다 2 자 적습니다.
any(g(*args) for args in f((a,b,c)))
테스트 :
assert any(g(*args) for args in f((a,b,c))) == (a + b == c or a + c == b or b + c == a)
또한 다음과 같이 주어진다 :
h = functools.partial(itertools.starmap, g)
이것은 동등하다
any(h(f((a,b,c))))
g()
이것이 작동하도록 정의해야 할 작은 기능도 있습니다. 모든 것을 감안할 때, 나는 그것이 훨씬 크다고 말할 것입니다.
가장 파이썬적인 답변 으로 보이는 것을 제시하고 싶습니다 .
def one_number_is_the_sum_of_the_others(a, b, c):
return any((a == b + c, b == a + c, c == a + b))
일반적으로 최적화되지 않은 경우 :
def one_number_is_the_sum_of_the_others(numbers):
for idx in range(len(numbers)):
remaining_numbers = numbers[:]
sum_candidate = remaining_numbers.pop(idx)
if sum_candidate == sum(remaining_numbers):
return True
return False
파이썬의 선에 관해서는 강조된 문장이 다른 답변보다 더 많이 따르는 것으로 생각합니다.
Tim Peters의 Python Zen
못생긴 것보다 아름답습니다.
암시적인 것보다 명시적인 것이 좋습니다.
단순보다 복잡합니다.
복잡한 것이 복잡한 것보다 낫습니다.
평평한 것이 중첩보다 낫습니다.
스파 스가 밀도보다 낫습니다.
가독성이 중요합니다.
특별한 경우는 규칙을 어길만큼 특별하지 않습니다.
실용성은 순도를 능가하지만.
오류가 자동으로 전달되지 않아야합니다.
명시 적으로 침묵하지 않는 한.
모호함에 직면하여 추측하려는 유혹을 거부하십시오.
그것을하는 명백한 방법이 있어야합니다.
네덜란드 인이 아니라면 처음에는 그 방법이 명확하지 않을 수 있습니다.
지금보다 결코 낫습니다.
결코 결코 낫지 않지만바로 지금
구현이 설명하기 어렵다면 나쁜 생각입니다.
구현이 설명하기 쉬운 경우 좋은 생각 일 수 있습니다.
네임 스페이스는 훌륭한 아이디어 중 하나입니다. 더 많은 것을 해보자!
def any_sum_of_others (*nums):
num_elements = len(nums)
for i in range(num_elements):
discriminating_map = map(lambda j: -1 if j == i else 1, range(num_elements))
if sum(n * u for n, u in zip(nums, discriminating_map)) == 0:
return True
return False
print(any_sum_of_others(0, 0, 0)) # True
print(any_sum_of_others(1, 2, 3)) # True
print(any_sum_of_others(7, 12, 5)) # True
print(any_sum_of_others(4, 2, 2)) # True
print(any_sum_of_others(1, -1, 0)) # True
print(any_sum_of_others(9, 8, -4)) # False
print(any_sum_of_others(4, 3, 2)) # False
print(any_sum_of_others(1, 1, 1, 1, 4)) # True
print(any_sum_of_others(0)) # True
print(any_sum_of_others(1)) # False