martes, 7 de enero de 2014

Rompecabezas - Todos los números (Solución)

Hace algunos días propuse el rompecabezas «Todos los números». Seguidamente doy una solución para el mismo, sin embargo, previo a la presentación de la solución, expongo el siguiente análisis:

  1. La cantidad de repeticiones de los valores de la tabla registro debe ser la igual a la cantidad de registros de la tabla repetición. Ya que los valores 1, 3 y 4 de la tabla de registro se repiten 3 veces y la cantidad de registros de la tabla repeticiones es 3, los números que pasan esta primera revisión son 1, 3 y 4. Queda el valor 2 descartado de una vez.

  2. Para cada valor de la tabla registro, la cantidad de repeticiones del campo repetición debe ser igual a la cantidad de repeticiones del campo repetición de la tabla repetición. Veamos: En la tabla repetición la letra «a» se repite dos veces y la letra «b» se repite una vez. Si se observa en la tabla registro, los únicos valores que están relacionados con la letra «a» dos veces y con la letra «b» una vez son los números 1 y 4.  Esto descarta el número 3, que «sobrevivió» en la revisión [1]


Una manera de solventar el siguiente problema es con la siguiente consulta:

select distinct a.valor  from

( select v.valor, v.repeticion, count (*) as cnt

from registro as v

group by v.valor, v.repeticion ) as a,

(select r.repeticion, count (*) as cnt from repeticion as r

group by r.repeticion ) as b,

(select count (*) as cnt from repeticion ) as c,

(select v.valor, count (*) as cnt

from registro as v

group by v.valor ) as d

where

a.repeticion = b.repeticion and a.cnt = b.cnt and c.cnt = d.cnt and a.valor = d.valor

Aunque la consulta funciona correctamente, cada una de las sub/consultas (a,b,c,d) deben ejecutarse para todos los registros antes de realizar las comparaciones y dar el resultado final. Para una gran cantidad de registros la consulta podría tomar un tiempo considerable en su ejecución.

Dicho esto, se propone la siguiente mejora en la consulta:

select distinct v.valor

from registro as v

group by v.valor, v.repeticion

having count (*) =

( select count (*) from repeticion as r where r.repeticion = v.repeticion and exists

( select 1 from registro as r where  r.valor = v.valor  having count (*) =

( select count (*) as cnt from repeticion )

)

)

A diferencia de la consulta anterior, ésta sólo toma en cuenta los subconjuntos derivados de las «primeras sub/consultas», lo que agiliza el tiempo de respuesta. Otra mejora consiste en sustituir la última sub/consulta por una variable que almacene la cantidad de registros de la tabla repetición. Esto evitaría el cálculo recurrente y acortaría el tiempo de proceso.

Claramente, existen otras soluciones para este rompecabezas.

Éstas se dejan como ejercicio a los lectores.

No hay comentarios: