क्या बूलियन अभिव्यक्ति लिखने के लिए एक अधिक कॉम्पैक्ट या पायथोनिक तरीका है
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)
लेकिन यह थोड़ा अजीब है।
जवाबों:
यदि हम पायथन के ज़ेन को देखते हैं, तो मेरा जोर दें:
टिम पीटर्स द्वारा ज़ेन ऑफ़ पायथन
सुंदर बदसूरत से बेहतर है।
निहितार्थ की तुलना में स्पष्ट है।
सरल जटिल से बेहतर है।
कॉम्प्लेक्स जटिल से बेहतर है।
फ्लैट नेस्टेड से बेहतर है।
विरल घने से बेहतर है।
पठनीयता मायने रखती है।
नियम तोड़ने के लिए विशेष मामले पर्याप्त नहीं हैं।
यद्यपि व्यावहारिकता शुद्धता को हरा देती है।
त्रुटियों को कभी भी चुपचाप नहीं गुजरना चाहिए।
जब तक स्पष्ट रूप से चुप नहीं कराया जाता।
अस्पष्टता के सामने, अनुमान लगाने के प्रलोभन से इनकार करें।
वहाँ एक होना चाहिए - और अधिमानतः इसे करने के लिए केवल एक ही - स्पष्ट तरीका।
हालांकि यह तरीका पहली बार में स्पष्ट नहीं हो सकता जब तक कि आप डच न हों।
अब पहले से बेहतर है।
हालांकि कभी-कभी इससे बेहतर नहीं होता हैसही अब।
यदि कार्यान्वयन को समझाना कठिन है, तो यह एक बुरा विचार है।
यदि कार्यान्वयन की व्याख्या करना आसान है, तो यह एक अच्छा विचार हो सकता है।
नाम स्थान एक महान विचार का सम्मान कर रहे हैं - चलो उन में से अधिक करते हैं!
सबसे पाइथोनिक समाधान वह है जो स्पष्ट, सबसे सरल और सबसे आसान है:
a + b == c or a + c == b or b + c == a
इससे भी बेहतर, आपको इस कोड को समझने के लिए पायथन जानने की आवश्यकता नहीं है! यह इतना आसान है। यह, आरक्षण के बिना, सबसे अच्छा समाधान है। और कुछ भी बौद्धिक हस्तमैथुन है।
इसके अलावा, यह संभवतः सबसे अच्छा प्रदर्शन करने वाला समाधान है, क्योंकि यह सभी प्रस्तावों में से केवल एक है जो शॉर्ट सर्किट करता है। यदि 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
"शॉर्ट-सर्किट" जो वे दिए गए हैं, उसकी जांच करने की प्रक्रिया ; लेकिन अगर यह एक जनरेटर के बजाय चलने योग्य है, तो फ़ंक्शन कॉल होने से पहले ही इसका पूरी तरह से मूल्यांकन किया जा चुका है ।
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
पहले से ही बहुत अजगर है।
यदि आप अधिक चर का उपयोग करने की योजना बनाते हैं तो आपके तर्क करने की विधि:
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
और यह या तो क, ख, ग या के लिए सच धारण करने के लिए है, जिसका अर्थ है कि हाँ यह बराबर होगा होगा 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()
कॉल के साथ इसे लागू करने के बाद , यह ओपी के स्निपेट की तुलना में पाइथोनिक है (मैं वास्तव में इसे काफी कम रीडिंग कहूंगा)।
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])
, ओपी के सुझाव के काफी करीब है
कोशिश मत करो और इसे सरल करो। इसके बजाय, एक फ़ंक्शन के साथ आप क्या कर रहे हैं नाम :
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
यदि किसी भी दो शब्दों का योग तीसरे शब्द के बराबर है, तो कारकों में से एक शून्य होगा, जिससे संपूर्ण उत्पाद शून्य हो जाएगा।
(a+b<>c) && (a+c<>b) && (b+c<>a) == false
कैसे बस के बारे में:
a == b + c or abs(a) == abs(b - c)
ध्यान दें कि यदि चर अप्रकाशित हैं तो यह काम नहीं करेगा।
कोड ऑप्टिमाइज़ेशन के दृष्टिकोण से (कम से कम x86 प्लेटफ़ॉर्म पर) यह सबसे कुशल समाधान लगता है।
आधुनिक संकलक दोनों एब्स () फ़ंक्शन कॉल को इनलाइन करेंगे और सीडीक्यू, एक्सओआर और एसयूबी निर्देशों के एक चतुर अनुक्रम का उपयोग करके साइन टेस्टिंग और बाद में सशर्त शाखा से बचेंगे । उपरोक्त उच्च-स्तरीय कोड इस प्रकार केवल निम्न-विलंबता, उच्च-थ्रूपुट ALU निर्देशों और सिर्फ दो स्थितियों के साथ दर्शाया जाएगा।
fabs()
इसका उपयोग float
प्रकारों के लिए किया जा सकता है ;)।
एलेक्स वर्गा द्वारा प्रदान किया गया समाधान "ए (बी + सी, बीसी, सीबी)" कॉम्पैक्ट और गणितीय रूप से सुंदर है, लेकिन मैं वास्तव में इस तरह से कोड नहीं लिखूंगा क्योंकि साथ आने वाले अगले डेवलपर तुरंत कोड के उद्देश्य को नहीं समझ पाएंगे। ।
मार्क रैंसम के समाधान
any((a + b == c, a + c == b, b + c == a))
अधिक स्पष्ट है, लेकिन बहुत अधिक रसीला नहीं है
a + b == c or a + c == b or b + c == a
जब कोड लिखते हैं कि किसी और को देखना होगा, या कि मुझे लंबे समय बाद देखना होगा जब मैं भूल गया हूं कि मैं क्या सोच रहा था जब मैंने इसे लिखा था, बहुत छोटा या चालाक होना अच्छा से अधिक नुकसान करने के लिए जाता है। कोड पठनीय होना चाहिए। इसलिए सक्सेसफुल अच्छा है, लेकिन इतना सक्सेन्केट नहीं कि अगला प्रोग्रामर इसे समझ न सके।
अनुरोध अधिक कॉम्पैक्ट या अधिक पायथोनिक के लिए है - मैंने अपने हाथ को और अधिक कॉम्पैक्ट करने की कोशिश की।
दिया हुआ
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
पायथन के ज़ेन के संदर्भ में मुझे लगता है कि अन्य उत्तरों की तुलना में जोर दिए गए बयानों का अधिक पालन किया जाता है:
टिम पीटर्स द्वारा ज़ेन ऑफ़ पायथन
सुंदर बदसूरत से बेहतर है।
निहितार्थ की तुलना में स्पष्ट है।
सरल जटिल से बेहतर है।
कॉम्प्लेक्स जटिल से बेहतर है।
फ्लैट नेस्टेड से बेहतर है।
विरल घने से बेहतर है।
पठनीयता मायने रखती है।
नियम तोड़ने के लिए विशेष मामले पर्याप्त नहीं हैं।
यद्यपि व्यावहारिकता शुद्धता को हरा देती है।
त्रुटियों को कभी भी चुपचाप नहीं गुजरना चाहिए।
जब तक स्पष्ट रूप से चुप नहीं कराया जाता।
अस्पष्टता के सामने, अनुमान लगाने के प्रलोभन से इनकार करें।
वहाँ एक होना चाहिए - और अधिमानतः इसे करने के लिए केवल एक ही - स्पष्ट तरीका।
हालाँकि यह तरीका पहली बार में स्पष्ट नहीं हो सकता जब तक कि आप डच न हों।
अब पहले से बेहतर है।
हालांकि कभी-कभी इससे बेहतर नहीं होता हैसही अब।
यदि कार्यान्वयन को समझाना कठिन है, तो यह एक बुरा विचार है।
यदि कार्यान्वयन की व्याख्या करना आसान है, तो यह एक अच्छा विचार हो सकता है।
नाम स्थान एक महान विचार का सम्मान कर रहे हैं - चलो उन में से अधिक करते हैं!
मेरी प्रोग्रामिंग की एक पुरानी आदत के रूप में, मुझे लगता है कि एक क्लॉज में दाईं ओर जटिल अभिव्यक्ति रखने से इसे इस तरह अधिक पठनीय बनाया जा सकता है:
a == b+c or b == a+c or c == a+b
प्लस ()
:
((a == b+c) or (b == a+c) or (c == a+b))
और मुझे भी लगता है कि मल्टी-लाइनों का उपयोग करके इस तरह से अधिक इंद्रियां बनाई जा सकती हैं:
((a == b+c) or
(b == a+c) or
(c == a+b))
एक सामान्य तरीके से,
m = a+b-c;
if (m == 0 || m == 2*a || m == 2*b) do_stuff ();
यदि, इनपुट चर में हेरफेर करना आपके लिए ठीक है,
c = a+b-c;
if (c==0 || c == 2*a || c == 2*b) do_stuff ();
अगर आप बिट हैक्स का उपयोग करके शोषण करना चाहते हैं, तो आप "!", ">> 1" और "<< 1" का उपयोग कर सकते हैं
मैंने विभाजन को टाल दिया हालांकि यह राउंड ऑफ एरर से बचने के लिए दो गुणा से बचने के लिए उपयोग को सक्षम बनाता है। हालांकि, ओवरफ्लो की जांच करें
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