Antecedentes
Alice y Bob juegan un juego llamado construir una palabra binaria . Para jugar el juego, arreglas una longitud n >= 0
, un conjunto G
de n
palabras binarias de longitud llamadas meta fijadas y una n
cadena de longitud que t
contiene las letras A
y B
, llamada orden de turno . El juego dura n
turnos, y en turno i
, el jugador definido por t[i]
selecciona un poco w[i]
. Cuando termina el juego, los jugadores miran la palabra binaria w
que han construido. Si esta palabra se encuentra en el objetivo establecido G
, Alice gana el juego; de lo contrario, Bob gana.
Por ejemplo, la solución deje n = 4
, G = [0001,1011,0010]
y t = AABA
. Alice obtiene el primer turno, y ella elige w[0] = 0
. El segundo turno también es de Alice, y ella elige w[1] = 0
. Bob tiene el tercer turno, y él elige w[2] = 0
. En el turno final, Alice elige w[3] = 1
. La palabra resultante 0001
, se encuentra en G
, por lo que Alice gana el juego.
Ahora, si Bob hubiera elegido w[2] = 1
, Alice podría haber elegido w[3] = 0
en su turno final, y aún así ganar. Esto significa que Alice puede ganar el juego sin importar cómo juegue Bob. En esta situación, Alice tiene una estrategia ganadora . Esta estrategia se puede visualizar como un árbol binario etiquetado, que se ramifica en los niveles correspondientes a los turnos de Bob, y cuyas ramas contienen una palabra de G
:
A A B A
-0-0-0-1
\
1-0
Alice juega simplemente siguiendo las ramas en su turno; no importa qué rama elija Bob, Alice finalmente gana.
Entrada
Se le da como entrada la longitud n
y el conjunto G
como una lista (posiblemente vacía) de cadenas de longitud n
.
Salida
Su salida es la lista de órdenes de turno para las cuales Alice tiene una estrategia ganadora, que es equivalente a la existencia de un árbol binario como se describió anteriormente. El orden de las órdenes de turno no importa, pero los duplicados están prohibidos.
Reglas detalladas
Puede escribir un programa completo o una función. En el caso de un programa, puede elegir el delimitador para la entrada y la salida, pero debe ser el mismo para ambos. El conteo de bytes más corto gana, y las lagunas estándar no se permiten.
Casos de prueba
3 [] -> []
3 [000,001,010,011,100,101,110,111] -> [AAA,AAB,ABA,ABB,BAA,BAB,BBA,BBB]
4 [0001,1011,0010] -> [AAAA,BAAA,AABA]
4 [0001,1011,0010,0110,1111,0000] -> [AAAA,BAAA,ABAA,BBAA,AABA,AAAB]
5 [00011,00110,00111,11110,00001,11101,10101,01010,00010] -> [AAAAA,BAAAA,ABAAA,BBAAA,AABAA,AAABA,BAABA,AAAAB,AABAB]
Hecho de la diversión
El número de órdenes de turno en la salida siempre es igual al número de palabras en el conjunto de objetivos.
11101
dos veces; El hecho divertido sigue siendo válido para los sets. Zgarb, ¿puede la entrada contener elementos repetidos o fue un error?Respuestas:
Dyalog APL, 59 bytes
{(a≡,⊂⍬)∨0=⍴a←∪⍵:a⋄(∇h/t)(('A',¨∪),'B',¨∩)∇(~h←⊃¨a)/t←1↓¨a}
Mismo algoritmo que en la solución de @ xnor.
fuente
Python, 132
Ejemplo de ejecución:
Esto es solo una especie de golf, principalmente para mostrar el algoritmo. Las entradas y salidas son conjuntos de cadenas. Python no parece tener las características correctas para expresar partes de esto de manera compacta, por lo que sería genial si alguien escribiera esto en un lenguaje más adecuado.
Así es como la recursividad se puede expresar matemáticamente. Desafortunadamente, PPCG todavía carece de representación matemática, por lo que tendré que usar bloques de código.
Los objetos de interés son conjuntos de cadenas. Deje
|
representar conjunto de unión y&
represent set set intersection.Si
c
es un carácter,c#S
represente anteponer el carácterc
a todas las cadenasS
. Por el contrario, deje que la contracciónc\S
sea la cadena de un carácter más cortaS
que sigue al carácter inicialc
, por ejemplo,0\{001,010,110,111} = {01,10}
.Podemos dividir de manera única un conjunto de cadenas
S
con caracteres01
por su primer personaje.Luego, podemos expresar la función deseada de la
f
siguiente manera, con los casos base en las dos primeras líneas y la lata recursiva en la última línea:Tenga en cuenta que no necesitamos usar la longitud
n
.¿Por qué funciona esto? Pensemos en las cadenas de movimiento que permiten que Alice gane por un conjunto de cadenas
S
.Si el primer personaje es
A
, Alice puede elegir el primer movimiento ('0' o '1'), permitiéndole elegir reducir el problema aS0
oS1
. Entonces, la cadena de movimiento restante debe estar en al menos uno def(S0)
of(S1)
, por lo tanto, tomamos su unión|
.Del mismo modo, si el primer personaje es 'B', Bob elige, y elegirá el peor para Alice, por lo que la cadena de movimiento restante debe estar en la intersección (
&
).Los casos base simplemente comprueban si
S
está vacío o no al final. Si estamos rastreando la longitud de las cadenasn
, restando 1 cada vez que repetimos, las bases pueden escribirse en su lugar:La solución recursiva también explica el hecho divertido que
f(S)
tiene el mismo tamaño queS
. Es cierto para los casos base y para el caso inductivotenemos
fuente
TypeError: 'int' object is not subscriptable
. ¿Tiene un enlace a un programa ejecutable? Me acaba de pegar y corrí conprint f([0001,1011,0010],4)
f({'000','001','010','011','100','101','110','111'},3)
. ¿Recibes un error de esta manera?print f(['0001','1011','0010'],4)
n
independencia de los parámetros, serían=len(S[0])if S!=[]else 0