Esta es una pregunta de entrevista de Google. No puedo resolverlo solo. ¿Alguien puede arrojar algo de luz?
Escriba un programa para imprimir la secuencia de pulsaciones de teclas de modo que genere el número máximo de caracteres 'A'. Usted está autorizado a utilizar sólo 4 teclas: A, Ctrl+ A, Ctrl+ Cy Ctrl+ V. Solo se permiten N pulsaciones de tecla. Todos los Ctrlcaracteres + se consideran como una pulsación de tecla, por lo que Ctrl+ Aes una pulsación de tecla.
Por ejemplo, la secuencia A, Ctrl+ A, Ctrl+ C, Ctrl+ Vgenera dos A de en 4 pulsaciones de teclas.
- Ctrl + A es Seleccionar todo
- Ctrl + C es Copiar
- Ctrl + V es Pegar
Hice algunas matemáticas. Para cualquier N, usando x números de A, uno Ctrl+ A, uno Ctrl+ Ce y Ctrl+ V, podemos generar un máximo de ((N-1) / 2) 2 números de A. Para algunos N> M, es mejor utilizar la mayor cantidad Ctrl+ A's, Ctrl+ Cy Ctrl+ Vsecuencias, ya que duplica el número de Atléticos.
La secuencia Ctrl+ A, Ctrl+ V, Ctrl+ Cno sobrescribirá la selección existente. Anexará la selección copiada a la seleccionada.
^A
suele ser "seleccionar todo",^C
es "copiar",^V
es "pegar". ¿Eso te da una idea?Respuestas:
Hay una solución de programación dinámica. Empezamos sabiendo que las teclas 0 pueden convertirnos en 0 A. Luego iteramos
i
hastan
, haciendo dos cosas: presionando A una vez y presionando seleccionar todo + copiar seguido de pegarj
veces (en realidadj-i-1
debajo; observe el truco aquí: el contenido todavía está en el portapapeles, por lo que podemos pegarlo varias veces sin copiando cada vez). Solo tenemos que considerar hasta 4 pegadas consecutivas, ya que seleccionar, copiar, pegar x 5 equivale a seleccionar, copiar, pegar, seleccionar, copiar, pegar y esto último es mejor ya que nos deja con más en el portapapeles. Una vez que llegamosn
, tenemos el resultado deseado.La complejidad puede parecer O (N), pero dado que los números crecen a una tasa exponencial, en realidad es O (N 2 ) debido a la complejidad de multiplicar los números grandes. A continuación se muestra una implementación de Python. Se necesitan unos 0,5 segundos para calcular N = 50.000.
En el código,
j
representa el número total de teclas presionadas después de nuestra nueva secuencia de pulsaciones de teclas. Ya tenemosi
pulsaciones de teclas en esta etapa, y 2 pulsaciones nuevas van a seleccionar todo y copiar. Por lo tanto, estamos alcanzandoj-i-2
tiempos de pegado . Dado que pegar se suma a la secuencia existente dedp[i]
A
's, debemos agregar1
make itj-i-1
. Esto explica elj-i-1
en la segunda y última línea.Aquí hay algunos resultados (
n
=> número de A):Estoy de acuerdo con @SB en que siempre debes establecer tus suposiciones: la mía es que no necesitas pegar dos veces para duplicar la cantidad de caracteres. Esto obtiene la respuesta para 7, así que a menos que mi solución sea incorrecta, la suposición debe ser correcta.
En caso maravillas alguien por qué no estoy de cheques secuencias de la forma Ctrl+ A, Ctrl+ C, A, Ctrl+ V: El resultado final siempre será el mismo que A, Ctrl+ A, Ctrl+ C, Ctrl+ V, que yo no considero.
fuente
n => result
oresult => n
? De cualquier manera, creo que está mal. Podemos escribir 9 como con 7 pulsaciones de teclas. Sin => result
definitivamente está mal. El número de Como puede escribir no puede ser menor quen
.n => result
. Dices "Podemos escribir 9 como con 7 pulsaciones de teclas", que es lo que obtengo. Lee el "truco" que acabo de editar.n
son las pulsaciones de teclas que puede utilizar. Tiene que calcular cuántas A puede escribir con lasn
pulsaciones de teclas. Entonces7 => 7
no tiene sentido.O(n)
o inclusoO(1)
:).Al usar la solución de marcog, encontré un patrón que comienza en
n=16
. Para ilustrar esto, aquí están las pulsaciones de teclas paran=24
hastan=29
, reemplacé ^ A con S (seleccionar), ^ C con C (copiar) y ^ V con P (pegar) para facilitar la lectura:Después de 4 As iniciales, el patrón ideal es seleccionar, copiar, pegar, pegar, pegar y repetir. Esto multiplicará el número de As por 4 cada 5 pulsaciones de tecla. Si este patrón de 5 pulsaciones no puede consumir las pulsaciones restantes por sí solo, algunos patrones de 4 pulsaciones (SCPP) consumen las pulsaciones finales, reemplazando a SCPPP (o eliminando una de las pastas) según sea necesario. Los 4 patrones de pulsación de teclas multiplican el total por 3 cada 4 pulsaciones.
El uso de este patrón aquí es un código de Python que obtiene los mismos resultados que la solución de marcog, pero es O (1) editar : esto es en realidad O (log n) debido a la exponenciación, gracias a IVlad por señalar eso.
Cálculo de e3: Siempre hay entre 0 y 4 patrones SCPP al final de la lista de pulsaciones de teclas, por
n % 5 == 4
hay 4,n % 5 == 1
hay 3,n % 5 == 2
hay 2,n % 5 == 3
hay 1 yn % 5 == 4
hay 0. Esto se puede simplificar a(4 - n) % 5
.Cálculo de e4: El número total de patrones aumenta en 1 siempre que
n % 5 == 0
, como resultado, este número aumenta exactamenten / 5
. Usando la división del piso podemos obtener el número total de patrones, el número total dee4
es el número total de patrones menose3
. Para aquellos que no están familiarizados con Python,//
es la notación a prueba de futuro para la división de pisos.fuente
n=3000
, por lo que probablemente sea correcto. (Lástima que meO(1)
ya que la potenciación no se puede hacer en tiempo constante. EsO(log n)
.Así es como lo abordaría:
dado algo de texto, se necesitan 4 pulsaciones para duplicarlo:
A partir de ahí, puede considerar hacer 4 o 5 A, luego recorrer lo anterior. Tenga en cuenta que hacerlo
ctrl + a, c, v, v
hará que su texto crezca exponencialmente a medida que lo recorra. Si los trazos restantes son <4, sigue haciendo unCtrlVLa clave para las entrevistas en lugares como Google es expresar sus suposiciones y comunicar su pensamiento. quieren saber cómo resuelves los problemas.
fuente
ACVV-VVVVV
multiplica por 7,ACVV-ACVV-V
multiplica por 6. Entonces Ctrl-V para los trazos restantes <6 en lugar de 4.Se puede resolver en O (1): al igual que con los números de Fibonacci, hay una fórmula para calcular el número de As impresos (y la secuencia de pulsaciones de teclas):
1) Podemos simplificar la descripción del problema:
es igual a
2) Podemos describir la secuencia de pulsaciones de teclas como una cadena de N caracteres de {'*', 'V', 'v'}, donde 'v' significa [Cv] y '*' significa [Ca] y 'V 'significa [Cc]. Ejemplo: "vvvv * Vvvvv * Vvvv"
La longitud de esa cuerda aún es igual a N.
El producto de las longitudes de las Vv-palabras en esa cadena es igual al número de As producidas.
3) Dada una longitud fija N para esa cadena y un número fijo K de palabras, el resultado será máximo si todas las palabras tienen casi la misma longitud. Su diferencia entre pares no es más de ± 1.
Ahora bien, ¿cuál es el número óptimo K, si se da N?
4) Supongamos que queremos aumentar el número de palabras agregando una sola palabra de longitud L, luego tenemos que reducir L + 1 veces cualquier palabra anterior en una 'v'. Ejemplo: "… * Vvvv * Vvvv * Vvvv * Vvvv" -> "… * Vvv * Vvv * Vvv * Vvv * Vvv"
Ahora, ¿cuál es la longitud de palabra óptima L?
(5 * 5 * 5 * 5 * 5) <(4 * 4 * 4 * 4 * 4) * 4, (4 * 4 * 4 * 4)> (3 * 3 * 3 * 3) * 3
=> Óptimo es L = 4.
5) Supongamos que tenemos una N suficientemente grande para generar una cadena con muchas palabras de longitud 4, pero quedan algunas pulsaciones de teclas; ¿cómo debemos usarlos?
Si quedan 5 o más: agregue otra palabra con longitud 4.
Si quedan 0: Listo.
Si quedan 4: Podríamos
a) agregue una palabra con longitud 3: 4 * 4 * 4 * 4 * 3 = 768.
b) o aumentar 4 palabras para que tengan una longitud de 5: 5 * 5 * 5 * 5 = 625. => Es mejor agregar una palabra.
Si quedan 3: Podríamos
a) o agregue una palabra con longitud 3 ajustando la palabra anterior de longitud 4 a 3: 4 * 4 * 4 * 2 = 128 <4 * 4 * 3 * 3 = 144.
b) aumenta 3 palabras para que tengan una longitud de 5: 5 * 5 * 5 = 125. => Es mejor agregar una palabra.
Si quedan 2: Podríamos
a) o agregue una palabra con longitud 3 ajustando las dos palabras anteriores de longitud 4 a 3: 4 * 4 * 1 = 16 <3 * 3 * 3 = 27.
b) aumenta 2 palabras para que tengan una longitud de 5: 5 * 5 = 25. => Es mejor agregar una palabra.
Si queda 1: Podríamos
a) o agregue una palabra con longitud 3 ajustando las tres palabras anteriores de longitud 4 a 3: 4 * 4 * 4 * 0 = 0 <3 * 3 * 3 * 3 = 81.
b) aumenta una palabra para que tenga una longitud de 5: 4 * 4 * 5 = 80. => Es mejor agregar una palabra.
6) Ahora, ¿qué pasa si no tenemos una "N suficientemente grande" para usar las reglas en 5)? ¡Tenemos que ceñirnos al plan b), si es posible! Las cadenas para N pequeña son:
1: "v", 2: "vv", 3: "vvv", 4: "vvvv"
5: "vvvvv" → 5 (plan b)
6: "vvvvvv" → 6 (plan b)
7: "vvv * Vvv" → 9 (plan a)
8: "vvvv * Vvv" → 12 (plan a)
9: "vvvv * Vvvv" → 16
10: "vvvv * Vvvvv" → 20 (plan b)
11: "vvv * Vvv * Vvv" → 29 (plan a)
12: "vvvv * Vvv * Vvv" → 36 (plan a)
13: "vvvv * Vvvv * Vvv" → 48 (plan a)
14: "vvvv * Vvvv * Vvvv" → 64
15: "vvv * Vvv * Vvv * Vvv" → 81 (plan a)
...
7) Ahora, ¿cuál es el número óptimo K de palabras en una cadena de longitud N?
Si N <7, entonces K = 1; de lo contrario, si 6 <N <11, entonces K = 2; de lo contrario: K = ceil ((N + 1) / 5)
Escrito en C / C ++ / Java:
int K = (N<7)?(1) : (N<11)?(2) : ((N+5)/5);
Y si N> 10, entonces el número de palabras con longitud 3 será: K * 5-1-N. Con esto, podemos calcular el número de As impresos:
Si N> 10, el número de As será: 4 ^ {N + 1-4K} · 3 ^ {5K-N-1}
fuente
Usar CtrlA+ CtrlC+ CtrlVes una ventaja solo después de 4 'A's.
Entonces haría algo como esto (en código pseudo-BÁSICO, ya que no ha especificado ningún idioma adecuado):
Editar
fuente
Se necesitan 3 pulsaciones para duplicar el número de As. Solo tiene sentido comenzar a duplicar cuando ya tenga 3 o más Como ya impresos. Desea que la última pulsación de tecla permitida sea a CtrlVpara asegurarse de que está duplicando el número más grande que pueda, por lo que para alinearlo, completaremos las pulsaciones de tecla adicionales después de las tres primeras As al principio con más As.
Editar:
Esto es terrible, me adelanté por completo y no consideré múltiples pastas para cada copia.
Edición 2:
Creo que pegar 3 veces es óptimo, cuando tienes suficientes pulsaciones de teclas para hacerlo. Con 5 pulsaciones de tecla, multiplica su número de As por 4. Esto es mejor que multiplicar por 3 utilizando 4 pulsaciones de tecla y mejor que multiplicar por 5 utilizando 6 pulsaciones de tecla. Comparé esto dando a cada método el mismo número de pulsaciones de teclas, lo suficiente para que cada uno termine un ciclo al mismo tiempo (60), dejando que el multiplicador 3 haga 15 ciclos, el multiplicador 4 haga 12 ciclos y el multiplicador 5 el multiplicador hace 10 ciclos. 3 ^ 15 = 14.348.907, 4 ^ 12 = 16.777.216 y 5 ^ 10 = 9.765.625. Si solo quedan 4 pulsaciones de tecla, hacer un multiplicador de 3 es mejor que pegar 4 veces más, esencialmente haciendo que el multiplicador de 4 anterior se convierta en un multiplicador de 8. Si solo quedan 3 pulsaciones de teclas, lo mejor es un multiplicador de 2.
fuente
Suponga que tiene x caracteres en el portapapeles y x caracteres en el área de texto; llamémoslo "estado x".
Presionemos "Pegar" unas cuantas veces (lo denoto por
m-1
por conveniencia), luego "Seleccionar todo" y "Copiar"; después de esta secuencia, llegamos al "estado m * x". Aquí, desperdiciamos un total de m + 1 pulsaciones de teclas. Entonces, el crecimiento asintótico es (al menos) algo así comof^n
, donde f =m^(1/(m+1))
. Creo que es el crecimiento asintótico máximo posible, aunque no puedo probarlo (todavía).Probar varios valores de m muestra que el máximo de f se obtiene para
m=4
.Usemos el siguiente algoritmo:
(no estoy seguro de que sea el óptimo).
El número de veces que debe presionar A al principio es 3: si lo presiona 4 veces, pierde la oportunidad de duplicar el número de A en 3 pulsaciones más.
El número de veces que debe presionar Pegar al final no es más de 5: si le quedan 6 o más pulsaciones de teclas, puede usar Pegar, Pegar, Pegar, Seleccionar todo, Copiar, Pegar en su lugar.
Entonces, obtenemos el siguiente algoritmo:
(no estoy seguro de que sea el óptimo). La cantidad de caracteres después de ejecutar esto es algo así como
3 * pow(4, floor((n - 6) / 5)) * (2 + (n - 1) % 5)
.Valores de muestra: 1,2,3,4,5,6,9,12,15,18,24,36,48,60,72,96,144,192,240,288, ...
fuente
Lo que sigue usa la segunda edición del OP que pegar no reemplaza el texto existente.
Note algunas cosas:
Por tanto, cada secuencia de pulsaciones de teclas razonable se puede interpretar como un grupo de Y separados por X, por ejemplo YYYXYXYYXY. Denote por V (s) el número de 'A's producidos por la secuencia s. Entonces V (nXm) = V (n) * V (m), porque X esencialmente reemplaza cada Y en m con V (n) 'A's.
El problema de copiar y pegar es, por tanto, isomórfico al siguiente problema: "utilizando m + 1 números que suman Nm, maximizan su producto". Por ejemplo, cuando N = 6, la respuesta es m = 1 y los números (2,3). 6 = 2 * 3 = V (YYXYYY) = V (AA ^ A ^ C ^ V ^ V) (o V (YYYXYY) = V (AAA ^ A ^ C ^ V).)
Podemos hacer algunas observaciones:
Para un valor fijo de
m
, los números a elegir sonceil( (N-m)/(m+1) )
yfloor( (N-m)/(m+1) )
(en cualquier combinación que haga que la suma funcione; más específicamente, necesitará(N-m) % (m+1)
ceils
y el restofloor
s). Esto es porque, paraa < b
,(a+1)*(b-1) >= a*b
.Desafortunadamente, no veo una manera fácil de encontrar el valor de
m
. Si esta fuera mi entrevista propondría dos soluciones en este punto:Opción 1. Repetir todo lo posible
m
. Unan log n
solución O ( ).Código C ++:
Opción 2. Permitir
m
obtener valores no enteros y encontrar su valor óptimo tomando la derivada de[(N-m)/(m+1)]^m
con respecto am
y resolviendo por su raíz. No existe una solución analítica, pero la raíz se puede encontrar usando, por ejemplo, el método de Newton. Luego use el piso y el techo de esa raíz para el valor dem
y elija el que sea mejor.fuente
fuente
Aquí está mi enfoque y solución con el código a continuación.
Acercarse:
Hay tres operaciones distintas que se pueden realizar.
Ahora, dadas las tres operaciones distintas y sus respectivos resultados, tenemos que ejecutar todas las permutaciones de estas operaciones.
Suposición:
Ahora, alguna versión de este problema establece que la secuencia de pulsaciones de teclas, Ctrl + A -> Ctrl + C -> Ctrl + V, sobrescribe la selección resaltada. Para tener en cuenta esta suposición, solo se debe agregar una línea de código a la solución a continuación donde la variable impresa en el caso 2 se establece en 0
Para esta solución
El siguiente código imprimirá un par de secuencias y la última secuencia es la respuesta correcta para cualquier N. por ejemplo, para N = 11 esta será la secuencia correcta
Con la suposición
A, A, A, A, A, C, S, V, V, V, V,: 20:
Sin la suposición
A, A, A, C, S, V, V, C, S, V, V,: 27:
Leyenda de pulsaciones de teclas:
'A' - A
'C' - Ctrl + A
'S' - Ctrl + C
'V' - Ctrl + V
Código:
fuente
Usando los trucos mencionados en las respuestas anteriores, Matemáticamente, la Solución se puede explicar en una ecuación como,
4 + 4 ^ [(N-4) / 5] + ((N-4)% 5) * 4 ^ [(N-4) / 5]. donde [] es el mayor factor entero
fuente
Existe una compensación entre imprimir mA manualmente y luego usar Ctrl+ A, Ctrl+ Cy Nm-2 Ctrl+V . La mejor solución está en el medio. Si el número máximo de pulsaciones de tecla = 10, la mejor solución es escribir 5 A o 4 A.
intente usar esto Mire esto http://www.geeksforgeeks.org/how-to-print-maximum-number-of-a-using-given-four-keys/ y tal vez optimice un poco buscando los resultados en la mitad punto.
fuente
Aquí está mi solución con programación dinámica, sin un ciclo anidado, y que también imprime los caracteres reales que necesitaría escribir:
Esta es la salida ('a' significa 'CTRL + A', etc.)
fuente
Si se permiten N pulsaciones de tecla, el resultado es N-3.
A's -> N-3
CTRL+A -> Seleccionando esos N caracteres: +1
CTRL+ C-> Copiando esos N caracteres: +1
Ctrl+ V-> Pegar los N caracteres. : +1 es decir, (ya que hemos seleccionado todos los caracteres usando CTRL+ A) Reemplazando estos N-3 caracteres existentes con los N-3 caracteres copiados (que anula los mismos caracteres) y el resultado es N-3.
fuente
→
. ¡Esto mejorará la legibilidad de su respuesta!