Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Integer in an interval with maximized number of trailing zero bits

Sought is an efficient algorithm that finds the unique integer in an interval [a, b] which has the maximum number of trailing zeros in its binary representation (a and b are integers > 0):

def bruteForce(a: Int, b: Int): Int =
  (a to b).maxBy(Integer.numberOfTrailingZeros(_))

def binSplit(a: Int, b: Int): Int = {
  require(a > 0 && a <= b)
  val res = ???
  assert(res == bruteForce(a, b))
  res
}

here are some examples

bruteForce(  5,   7) ==   6 // binary 110 (1 trailing zero)
bruteForce(  1, 255) == 128 // binary 10000000
bruteForce(129, 255) == 192 // binary 11000000

etc.

like image 268
0__ Avatar asked Dec 21 '22 13:12

0__


2 Answers

This one finds the number of zeros:

// Requires a>0
def mtz(a: Int, b: Int, mask: Int = 0xFFFFFFFE, n: Int = 0): Int = {
  if (a > (b & mask)) n
  else mtz(a, b, mask<<1, n+1)
}

This one returns the number with those zeros:

// Requires a > 0
def nmtz(a: Int, b: Int, mask: Int = 0xFFFFFFFE): Int = {
  if (a > (b & mask)) b & (mask>>1)
  else nmtz(a, b, mask<<1)
}

I doubt the log(log(n)) solution has a small enough constant term to beat this. (But you could do binary search on the number of zeros to get log(log(n)).)

like image 57
Rex Kerr Avatar answered May 12 '23 23:05

Rex Kerr


I decided to take Rex's challenge and produce something faster. :-)

// requires a > 0
def mtz2(a: Int, b: Int, mask: Int = 0xffff0000, shift: Int = 8, n: Int = 16): Int = {
  if (shift == 0) if (a > (b & mask)) n - 1 else n
  else if (a > (b & mask)) mtz2(a, b, mask >> shift, shift / 2, n - shift)
  else mtz2(a, b, mask << shift, shift / 2, n + shift)
}

Benchmarked with

import System.{currentTimeMillis => now}
def time[T](f: => T): T = {
  val start = now
  try { f } finally { println("Elapsed: " + (now - start)/1000.0 + " s") }
}

val range = 1 to 200
time(f((a, b) => mtz(a, b)))
time(f((a, b) => mtz2(a, b)))
like image 37
Daniel C. Sobral Avatar answered May 12 '23 22:05

Daniel C. Sobral