एक अंश के लिए द्विआधारी खोज
मैं किताब के एल्गोरिदम से एक अभ्यास को हल करने की कोशिश कर रहा हूँ जो सेडग्विक से है जो निम्नानुसार है:
फॉर्म के प्रश्नों की लघुगणक संख्या का उपयोग करने वाली एक विधि को तैयार करें क्या संख्या x से कम है? एक परिमेय संख्या p / q ज्ञात करने के लिए ऐसा 0 <p <q <N. संकेत: एन से कम भाजक वाले दो अंश 1 / N ^ 2 से अधिक भिन्न नहीं हो सकते।
मुझे पता है कि जिस अंतराल में मुझे बाइनरी सर्च करना है] 0, 1 [लेकिन मुझे यकीन नहीं है कि मुझे क्या देखना चाहिए और क्या है। क्या कोई इसे मुझे समझा सकता है?
जवाब
संकेत की उपेक्षा, यहाँ एक बहुत कठिन समस्या का समाधान है।
अर्थात् खोजने के किसी भी , द्विआधारी खोज से तर्कसंगत एक लघुगणकीय अंश / भाजक का निरपेक्ष मान पर बाध्य के साथ, पहले से जानते हुए भी है कि कितना बड़ा बिना।
यह स्टर्न-ब्रोकोट पेड़ की एक द्विआधारी खोज है।
class GuessState:
def __init__ (self):
self.direction = None
self.start = [0, 1]
self.bound = [0, 0]
self.multiple_upper = 1
self.multiple_lower = 1
self.is_widening = True
self.is_choosing = None
def next_guess (self):
if self.is_widening:
multiple = self.multiple_upper
else:
multiple = (self.multiple_lower + self.multiple_upper) // 2
return (self.start[0] + multiple * self.bound[0], self.start[1] + multiple * self.bound[1])
def add_response (self, response):
next_level = False
if self.direction is None:
if 0 < response:
self.bound[0] = 1
self.direction = 1
else:
self.bound[0] = -1
self.direction = -1
self.is_choosing = True
return
elif self.is_choosing:
if self.direction * response < 0:
# Reverse direction.
self.direction = - self.direction
(self.start, self.bound) = (self.bound, self.start)
self.multiple_upper = 2
self.is_choosing = False
elif self.is_widening:
if 0 < response * self.direction:
self.multiple_lower = self.multiple_upper
self.multiple_upper += self.multiple_upper
else:
self.is_widening = False
if self.multiple_lower + 1 == self.multiple_upper:
next_level = True
elif self.multiple_lower + 1 < self.multiple_upper:
if 0 < self.direction * response:
self.multiple_lower = (self.multiple_lower + self.multiple_upper) // 2
else:
self.multiple_upper = (self.multiple_lower + self.multiple_upper) // 2
else:
next_level = True
if next_level:
next_start = (self.start[0] + self.multiple_lower * self.bound[0], self.start[1] + self.multiple_lower * self.bound[1])
next_bound = (self.start[0] + self.multiple_upper * self.bound[0], self.start[1] + self.multiple_upper * self.bound[1])
self.start = next_start
self.bound = next_bound
self.multiple_lower = 1
self.multiple_upper = 1
self.is_choosing = True
self.is_widening = True
def guesser (answerer):
state = GuessState()
response = answerer(state.next_guess())
while response != 0:
state.add_response(response)
response = answerer(state.next_guess())
return state.next_guess()
def answerer (answer):
def compare (guess):
val = guess[0] / guess[1]
print(f"Comparing answer {answer} to guess {val} ({guess[0]}/{guess[1]})")
if val < answer:
return 1
elif answer < val:
return -1
else:
return 0
return compare
print(guesser(answerer(0.124356)))