Hace unos años me presenté a un concurso de programación y éste era uno de los problemas: Abuela binaria
Resumen : Dado un número entero positivo N encuentre 2 enteros positivos tales que $$ x + y = N $$ Sea X y Y sea el número de bits fijados en la representación de base 2 de x e y respectivamente (peso Hamming de x e y). Maximizar X + Y .
Por alguna razón tuve dificultades al principio en python(sobre todo porque estaba usando un algoritmo estúpido que era demasiado lento con N grandes) así que decidí intentar resolverlo usando Haskell. Finalmente logré resolverlo de alguna manera con muy buen rendimiento con este código Haskell:
import IO
import Control.Monad
read_number_of_cases :: IO Integer
read_number_of_cases = do
s <- getLine
let number_of_cases = read s :: Integer
return number_of_cases
main :: IO ()
main = do
hSetBuffering stdin LineBuffering
number_of_cases <- read_number_of_cases
forM_ [1..number_of_cases] (\i -> do
line <- getLine
let number = read line :: Integer
a000120 0 = 0
a000120 n = a000120 n' + m where (n', m) = divMod n 2
middle = if even number
then truncate(toRational(number)/2)::Integer
else truncate(toRational(number)/2)::Integer
max_p1 = if (a000120 middle)>=(truncate(logBase 2 (fromIntegral middle))+1)
then middle
else truncate(2**fromIntegral(truncate(logBase 2 (fromIntegral middle)))-1)
max_p2 = if (a000120 number)>=(truncate(logBase 2 (fromIntegral number))+1)
then number
else truncate(2**fromIntegral(truncate(logBase 2 (fromIntegral number)))-1)
result = if max_p1 > max_p2
then a000120(max_p1) + a000120(number - max_p1)
else a000120(max_p2) + a000120(number - max_p2)
putStrLn ("Case #"++show i++": "++(show result)))`
(A000120 calcula el peso Hamming https://oeis.org/A000120 )
Lo que hace este código es: $$ middle = \left\lfloor {\frac{N}{2}} \right\rfloor\\ max_{p1}=\begin{cases} middle,& \text{if } Hamming(middle)\geq \left\lfloor log_2(middle) \right\rfloor + 1\\ \left\lfloor 2^{ \left\lfloor (log_2(middle) )\right\rfloor}-1 \right\rfloor, & \text{otherwise} \end{cases}\\ max_{p2}=\begin{cases} middle,& \text{if } Hamming(N)\geq \left\lfloor log_2(N) \right\rfloor + 1\\ \left\lfloor 2^{ \left\lfloor (log_2(N) )\right\rfloor}-1 \right\rfloor, & \text{otherwise} \end{cases}\\ result=\begin{cases} Hamming(max_{p1})+Hamming(N-max_{p1}),& \text{if } max_{p1} \gt max_{p2} \\ Hamming(max_{p2})+Hamming(N-max_{p2}), & \text{otherwise} \end{cases} $$
Eso funcionó, pero para ser honesto no tengo ni idea de por qué, o si funcionaría para todos los casos. Así que la pregunta es: ¿Hay una manera fácil de demostrar que es correcto? ¿O incorrecta si es el caso?