Given two integers L and R . Find the resultant after applying the series of Bitwise AND ( & ) operation on every natural number between the Range L and R (including both).
 
Example 1:
Input: L = 8, R = 13
Output: 8
Explanation: 
8 AND 9 AND 10 AND 11 AND 12 AND 13 = 8.
Example 2:
Input: L = 2, R = 3
Output: 2
Explanation: 2 AND 3 = 2.
 
Your Task:
You don't need to read or print anything. Your task is to complete the function find_and() which takes l and r as input parameter and returns AND operation on every number between l to r.
 
Expected Time Complexity: O(log(n))
Expected Time Complexity: O(1)
 
Constraints:
1 <= L<= R < =10^{8}

Difficulty: EASY
Tags: Bit manipulation

Data structures
Skill types: Bit manipulation

Data structures
Expected Time Complexity: O(log(n))
Expected Auxiliary Space: O(1)

Starter code:
#User function Template for python3

class Solution:
	def find_and(self, l, r):
		# Code here


Solutions:
class Solution:

	def find_and(self, l, r):
		while r > l:
			r &= r - 1
		return r & l


from math import log

class Solution:

	def find_and(self, l, r):

		def msbPos(n):
			msb_p = -1
			while n > 0:
				n = n >> 1
				msb_p += 1
			return msb_p

		def andOperator(x, y):
			res = 0
			while x > 0 and y > 0:
				msb_p1 = msbPos(x)
				msb_p2 = msbPos(y)
				if msb_p1 != msb_p2:
					break
				msb_val = 1 << msb_p1
				res = res + msb_val
				x = x - msb_val
				y = y - msb_val
			return res
		return andOperator(l, r)


class Solution:

	def find_and(self, l, r):
		mask = 1 << 31
		ans = 0
		for i in range(32):
			if mask & l == mask & r:
				if mask & l != 0:
					ans += mask
			else:
				break
			mask >>= 1
		return ans


class Solution:

	def find_and(self, m, n):
		while n > m:
			n = n & n - 1
		return m & n


class Solution:

	def find_and(self, l, r):
		res = 0
		while l > 0 and r > 0:
			msb_l = self.find_mos_pos(l)
			msb_r = self.find_mos_pos(r)
			if msb_l != msb_r:
				break
			mult = 1 << msb_l
			res += mult
			l -= mult
			r -= mult
		return res

	def find_mos_pos(self, n):
		mos = -1
		while n > 0:
			n = n >> 1
			mos += 1
		return mos


class Solution:

	def find_and(self, l, r):
		count = 0
		while l != r and l:
			count += 1
			l >>= 1
			r >>= 1
		return l << count


class Solution:

	def find_and(self, l, r):
		(l, r) = (bin(l)[2:], bin(r)[2:])
		ans = ['0'] * len(l)
		if len(l) != len(r):
			return 0
		for i in range(len(l)):
			if l[i] != r[i]:
				break
			ans[i] = '1' if l[i] == '1' else '0'
		return int(''.join(ans), 2)


class Solution:

	def find_and(self, l, r):
		diff = l ^ r
		diff |= diff >> 1
		diff |= diff >> 2
		diff |= diff >> 4
		diff |= diff >> 8
		diff |= diff >> 16
		diff |= diff >> 32
		ans = l & ~diff
		return ans


class Solution:

	def find_and(self, a, b):
		c = 0
		while a != b and a > 0:
			c += 1
			a = a >> 1
			b = b >> 1
		return a << c


class Solution:

	def find_and(self, l, r):
		num_count = r - l
		tmp = r
		res = 0
		mask = 1
		while tmp > 0:
			if tmp & 1 and r % mask + 1 > num_count:
				res = res | mask
			mask = mask << 1
			tmp = tmp >> 1
		return res


class Solution:

	def find_and(self, l, r):
		res = 0
		while l != r:
			l = l >> 1
			r = r >> 1
			res += 1
		return l << res


class Solution:

	def find_and(self, l, r):
		c = 0
		while l != r:
			l >>= 1
			r >>= 1
			c += 1
		return l << c