Introducción
Supongamos que usted y su amigo están jugando un juego. Tu amigo piensa en una secuencia particular de nbits, y tu tarea es deducir la secuencia haciéndoles preguntas. Sin embargo, el único tipo de pregunta que se le permite hacer es "¿Cuánto dura la subsecuencia común más larga de su secuencia y S", dónde Ses cualquier secuencia de bits. Cuantas menos preguntas necesite, mejor.
La tarea
Su tarea es escribir un programa o función que tome como entrada un entero positivo ny una secuencia binaria Rde longitud n. La secuencia puede ser una matriz de enteros, una cadena o algún otro tipo razonable de su elección. Su programa generará la secuencia R.
Su programa no puede acceder a la secuencia Rdirectamente. Lo único que se le permite hacer Res darle como entrada a la función len_lcsjunto con otra secuencia binaria S. La función len_lcs(R, S)devuelve la longitud de la subsecuencia común más larga de Ry S. Esto significa la secuencia más larga de bits que ocurre como una subsecuencia (no necesariamente contigua) en ambos Ry S. Las entradas de las len_lcscuales pueden ser de diferentes longitudes. El programa debe invocar esta función Ry otras secuencias varias veces, y luego reconstruir la secuencia en Rfunción de esa información.
Ejemplo
Considere las entradas n = 4y R = "1010". Primero, podríamos evaluar len_lcs(R, "110"), lo que da 3, ya que "110"es la subsecuencia común más larga de "1010"y "110". Entonces sabemos que Rse obtiene "110"al insertar un bit en alguna posición. A continuación, podríamos intentar len_lcs(R, "0110"), que regresa 3ya que las subsecuencias comunes más largas son "110"y "010", por "0110"lo tanto, no es correcta. Luego intentamos len_lcs(R, "1010"), que vuelve 4. Ahora sabemos eso R == "1010", por lo que podemos devolver esa secuencia como la salida correcta. Esto requirió 3 llamadas a len_lcs.
Reglas y puntaje
En este repositorio , encontrará un archivo llamado que subsequence_data.txtcontiene 100 secuencias binarias aleatorias de longitudes entre 75 y 124. Se generaron tomando tres flotadores aleatorios entre 0 y 1, tomando su promedio como a, y luego volteando una amoneda imparcial nveces. Su puntaje es el número promedio de llamadas alen_lcs estas secuencias, siendo menor el puntaje menor. Su envío debe registrar el número de llamadas. No hay límites de tiempo, excepto que debe ejecutar su programa en el archivo antes de enviarlo.
Su presentación será determinista. Los PRNG están permitidos, pero deben usar la fecha de hoy 200116(o el equivalente más cercano) como semilla aleatoria. No está permitido optimizar su envío en relación con estos casos de prueba particulares. Si sospecho que esto está sucediendo, generaré un nuevo lote.
Este no es un código de golf, por lo que se recomienda escribir código legible. Rosetta Code tiene una página en la subsecuencia común más larga ; puede usar eso para implementar len_lcsen su idioma de elección.

lcslugar de hacerlolen_lcs.lcs(R, "01"*2*n)regresaR. ;) Pero eso podría funcionar si llamarlcs(R, S)aumentaría el puntaje enlen(S)lugar de 1, o algo así ...Respuestas:
Java,
99.0498.4697.66 llamadas lcs ()Cómo funciona
Exaple: Nuestra línea que se va a reconstruir es
00101. Primero descubrimos cuántos ceros hay, comparando (aquí comparando = calculando lcs con la cadena original) por una cadena de solo ceros00000. Luego pasamos por cada posición, volteamos0a a1y verificamos si ahora tenemos una subcadena común más larga. En caso afirmativo, acepte e ir a la siguiente posición, si no, voltee la corriente de1nuevo a ay0vaya a la siguiente posición:Optimizaciones
Esta es solo una implementación "ingenua", quizás sería posible encontrar un algoritmo más sofisticado que verifique varias posiciones a la vez. Pero no estoy seguro de si realmente hay uno mejor (por ejemplo, basado en el cálculo de bits de paridad similares al código de Hamming), ya que siempre puede evaluar la longitud de la subcadena común.
Para una línea de dígitos dada, este algoritmo necesita
#ofDigitsUntilTheLastOccurenceOf1 + 1verificaciones exactas . (Reste uno si los últimos dígitos son an1.)EDITAR: Una pequeña optimización: si solo verificamos el 2do último dígito y aún necesitamos insertar un
1, sabemos con certeza que debe estar en la última posición, y podemos omitir la verificación correspondiente.EDIT2: Acabo de notar que puedes aplicar la idea anterior a las últimas
k.Por supuesto, podría ser posible lograr un puntaje ligeramente más bajo con esta optimización, al reordenar todas las líneas primero, porque podría ser que obtenga más líneas con unas al final, pero eso obviamente sería una optimización para la actual. casos de prueba que ya no es gracioso.
Tiempo de ejecución
El límite superior es
O(#NumberOfBits).Código completo
Aquí el código completo:
fuente
1, lo que equivale a que solo quedan ceros.