Esta é uma pergunta da entrevista do google. Eu não sou capaz de resolver sozinho. Alguém pode lançar alguma luz?
Escreva um programa para imprimir a sequência de pressionamentos de tecla de forma que gere o número máximo de caracteres 'A's. Você está autorizado a usar apenas 4 teclas: A, Ctrl+ A, Ctrl+ Ce Ctrl+ V. Apenas N pressionamentos de tecla são permitidos. Todos os Ctrlcaracteres + são considerados como um toque de tecla, portanto Ctrl+ Aé um toque de tecla.
Por exemplo, a sequência de A, Ctrl+ A, Ctrl+ C, Ctrl+ Vgera dois de um em 4 batidas de tecla.
- Ctrl + A é Selecionar Tudo
- Ctrl + C é Copiar
- Ctrl + V é colar
Eu fiz matemática. Para qualquer N, usando x números de A's, um Ctrl+ A, um Ctrl+ Cey Ctrl+ V, podemos gerar max ((N-1) / 2) 2 números de A's. Para alguns N> M, é melhor usar tantas sequências Ctrl+ A's, Ctrl+ Ce Ctrl+ Vquanto dobra o número de A's.
A sequência Ctrl+ A, Ctrl+ V, Ctrl+ Cnão substituirá a seleção existente. Isso acrescentará a seleção copiada à selecionada.
^A
geralmente é "selecionar tudo",^C
é "copiar",^V
é "colar". Isso te dá uma ideia?Respostas:
Existe uma solução de programação dinâmica. Começamos sabendo que 0 chaves podem nos tornar 0 A's. Em seguida, iteramos por
i
atén
, fazendo duas coisas: pressionando A uma vez e pressionando selecionar tudo + copiar seguido porj
tempos de colar (na verdadej-i-1
abaixo; observe o truque aqui: o conteúdo ainda está na área de transferência, então podemos colá-lo várias vezes sem copiando cada vez). Só temos que considerar até 4 pastas consecutivas, pois selecionar, copiar, colar x 5 equivale a selecionar, copiar, colar, selecionar, copiar, colar e esta última é melhor porque nos deixa com mais na área de transferência. Assim que chegarmosn
, teremos o resultado desejado.A complexidade pode parecer O (N), mas como os números crescem a uma taxa exponencial, é na verdade O (N 2 ) devido à complexidade de multiplicar os grandes números. Abaixo está uma implementação Python. Leva cerca de 0,5 segundos para calcular N = 50.000.
No código,
j
representa o número total de teclas pressionadas após nossa nova sequência de pressionamentos de tecla. Já temosi
pressionamentos de tecla neste estágio, e 2 novos pressionamentos de tecla vão para selecionar tudo e copiar. Portanto, estamos batendoj-i-2
tempos de colar . Uma vez que colar adiciona à sequência existente dedp[i]
A
's, precisamos adicionar1
make itj-i-1
. Isso explica oj-i-1
na penúltima linha.Aqui estão alguns resultados (
n
=> número de A's):Concordo com @SB que você deve sempre declarar suas suposições: A minha é que você não precisa colar duas vezes para dobrar o número de caracteres. Isso obtém a resposta 7, portanto, a menos que minha solução esteja errada, a suposição deve estar certa.
No caso de alguém se pergunta por que eu não estou verificando seqüências de forma Ctrl+ A, Ctrl+ C, A, Ctrl+ V: O resultado final será sempre a mesma A, Ctrl+ A, Ctrl+ C, Ctrl+ Vque eu não considerar.
fonte
n => result
ouresult => n
? De qualquer forma, acho que está errado. Podemos digitar 9 As com 7 teclas. Se estivern => result
definitivamente errado. O número de conforme você pode digitar não pode ser inferior an
.n => result
. Você diz "Podemos digitar 9 como com 7 teclas", que é o que eu recebo. Leia o "truque" que acabei de editar.n
são as teclas que você pode usar. Você tem que calcular quantos As você pode digitar com asn
teclas. Então7 => 7
não faz sentido.O(n)
ou atéO(1)
:).Usando a solução de Marcog, encontrei um padrão que começa em
n=16
. Para ilustrar isso, aqui estão as combinações de teclas paran=24
atén=29
, substituí ^ A por S (selecionar), ^ C por C (copiar) e ^ V por P (colar) para facilitar a leitura:Após 4 As iniciais, o padrão ideal é selecionar, copiar, colar, colar, colar e repetir. Isso multiplicará o número de As por 4 a cada 5 pressionamentos de tecla. Se este padrão de 5 pressionamentos de tecla não puder consumir os pressionamentos de tecla restantes por conta própria, algum número de 4 padrões de pressionamento de tecla (SCPP) consumirá os pressionamentos de tecla finais, substituindo SCPPP (ou removendo uma das pastas) conforme necessário. Os 4 padrões de pressionamento de tecla multiplicam o total por 3 a cada 4 pressionamentos de tecla.
Usando esse padrão aqui está algum código Python que obtém os mesmos resultados da solução de marcog, mas é O (1) edit : Na verdade, é O (log n) devido à exponenciação, graças a IVlad por apontar isso.
Calculando e3: Sempre há entre 0 e 4 padrões SCPP no final da lista de pressionamentos de tecla, pois
n % 5 == 4
há 4,n % 5 == 1
há 3,n % 5 == 2
há 2,n % 5 == 3
há 1 en % 5 == 4
há 0. Isso pode ser simplificado para(4 - n) % 5
.Calculando e4: O número total de padrões aumenta em 1 sempre
n % 5 == 0
que acontece que esse número aumenta exatamenten / 5
. Usando a divisão de piso, podemos obter o número total de padrões, o número total dee4
é o número total de padrões menose3
. Para quem não//
está familiarizado com Python, é a notação preparada para o futuro para divisão de pisos.fonte
n=3000
, então provavelmente está certo. (Pena que estou sem votos hoje: /)O(1)
porque a exponenciação não pode ser feita em tempo constante. ÉO(log n)
.Aqui está como eu abordaria isso:
dado algum texto, são necessários 4 pressionamentos de tecla para duplicá-lo:
A partir daí, você pode considerar fazer 4 ou 5 A's e, em seguida, repetir o procedimento acima. Observe que isso
ctrl + a, c, v, v
aumentará o seu texto exponencialmente conforme você o percorre. Se os traços restantes <4, continue fazendo umCtrlVO segredo das entrevistas em locais como o Google é expor suas suposições e comunicar seu pensamento. eles querem saber como você resolve problemas.
fonte
ACVV-VVVVV
multiplica por 7,ACVV-ACVV-V
multiplica por 6. Portanto, Ctrl-V para os golpes restantes <6 em vez de 4.É solucionável em O (1): Como com os números de Fibonacci, há uma fórmula para calcular o número de As impressas (e a sequência de teclas):
1) Podemos simplificar a descrição do problema:
é igual a
2) Podemos descrever a sequência de pressionamentos de tecla como uma string de N caracteres de {'*', 'V', 'v'}, onde 'v' significa [Cv] e '*' significa [Ca] e 'V 'significa [Cc]. Exemplo: "vvvv * Vvvvv * Vvvv"
O comprimento dessa corda ainda é igual a N.
O produto dos comprimentos das palavras Vv nessa string é igual ao número de As produzidas.
3) Dado um comprimento fixo N para aquela string e um número fixo K de palavras, o resultado será máximo se todas as palavras tiverem comprimentos quase iguais. Sua diferença entre pares não é mais do que ± 1.
Agora, qual é o número ótimo K, se N for dado?
4) Suponha que queremos aumentar o número de palavras anexando uma única palavra de comprimento L, então temos que reduzir L + 1 vezes qualquer palavra anterior por um 'v'. Exemplo: "… * Vvvv * Vvvv * Vvvv * Vvvv" -> "… * Vvv * Vvv * Vvv * Vvv * Vvv"
Agora, qual é o comprimento ideal da palavra L?
(5 * 5 * 5 * 5 * 5) <(4 * 4 * 4 * 4 * 4) * 4, (4 * 4 * 4 * 4)> (3 * 3 * 3 * 3) * 3
=> O ideal é L = 4.
5) Suponha que temos um N grande o suficiente para gerar uma string com muitas palavras de comprimento 4, mas ainda faltam algumas teclas; como devemos usá-los?
Se sobrar 5 ou mais: acrescente outra palavra com comprimento 4.
Se sobrar 0: Concluído.
Se sobrarem 4: nós poderíamos
a) acrescente uma palavra com comprimento 3: 4 * 4 * 4 * 4 * 3 = 768.
b) ou aumente 4 palavras para 5: 5 * 5 * 5 * 5 = 625. => Anexar uma palavra é melhor.
Se sobrarem 3: nós poderíamos
a) ou acrescente uma palavra com comprimento 3 ajustando a palavra anterior do comprimento 4 para 3: 4 * 4 * 4 * 2 = 128 <4 * 4 * 3 * 3 = 144.
b) aumentar 3 palavras para 5: 5 * 5 * 5 = 125. => Anexar uma palavra é melhor.
Se sobrarem 2: nós poderíamos
a) ou acrescente uma palavra com comprimento 3 ajustando as duas palavras anteriores de comprimento 4 para 3: 4 * 4 * 1 = 16 <3 * 3 * 3 = 27.
b) aumentar 2 palavras para 5: 5 * 5 = 25. => Anexar uma palavra é melhor.
Se sobrar 1: nós poderíamos
a) ou acrescente uma palavra com comprimento 3 ajustando as três palavras anteriores do comprimento 4 para 3: 4 * 4 * 4 * 0 = 0 <3 * 3 * 3 * 3 = 81.
b) aumentar uma palavra para o comprimento 5: 4 * 4 * 5 = 80. => Anexar uma palavra é melhor.
6) Agora, e se não tivermos um "N grande o suficiente" para usar as regras em 5)? Temos que seguir o plano b), se possível! As strings para N pequeno são:
1: "v", 2: "vv", 3: "vvv", 4: "vvvv"
5: "vvvvv" → 5 (plano b)
6: "vvvvvv" → 6 (plano b)
7: "vvv * Vvv" → 9 (plano a)
8: "vvvv * Vvv" → 12 (plano a)
9: "vvvv * Vvvv" → 16
10: "vvvv * Vvvvv" → 20 (plano b)
11: "vvv * Vvv * Vvv" → 29 (plano a)
12: "vvvv * Vvv * Vvv" → 36 (plano a)
13: "vvvv * Vvvv * Vvv" → 48 (plano a)
14: "vvvv * Vvvv * Vvvv" → 64
15: "vvv * Vvv * Vvv * Vvv" → 81 (plano a)
…
7) Agora, qual é o número ideal K de palavras em uma string de comprimento N?
Se N <7 então K = 1 senão se 6 <N <11 então K = 2; caso contrário: K = ceil ((N + 1) / 5)
Escrito em C / C ++ / Java:
int K = (N<7)?(1) : (N<11)?(2) : ((N+5)/5);
E se N> 10, então o número de palavras com comprimento 3 será: K * 5-1-N. Com isso, podemos calcular o número de As impressas:
Se N> 10, o número de As será: 4 ^ {N + 1-4K} · 3 ^ {5K-N-1}
fonte
Usar CtrlA+ CtrlC+ CtrlVé uma vantagem somente após 4 'A's.
Então, eu faria algo assim (em código pseudo-BASIC, uma vez que você não especificou uma linguagem adequada):
Editar
fonte
São necessários 3 pressionamentos de tecla para dobrar o número de As. Só faz sentido começar a dobrar quando você tiver 3 ou mais As já impressos. Você deseja que o último pressionamento de tecla permitido seja um CtrlVpara ter certeza de que está dobrando o maior número possível; portanto, para alinhá-lo, preencheremos quaisquer pressionamentos de tecla extras após os primeiros três As no início com mais As.
Editar:
Isso é terrível, eu me precipitei completamente e não considerei várias pastas para cada cópia.
Editar 2:
Acredito que colar 3 vezes é o ideal, quando você tem teclas suficientes para fazê-lo. Em 5 pressionamentos de tecla, você multiplica seu número de As por 4. Isso é melhor do que multiplicar por 3 usando 4 pressionamentos de tecla e melhor do que multiplicar por 5 usando 6 pressionamentos de tecla. Eu comparei isso dando a cada método o mesmo número de pressionamentos de tecla, o suficiente para que cada um terminasse um ciclo ao mesmo tempo (60), deixando o multiplicador 3 fazer 15 ciclos, o multiplicador 4 fazer 12 ciclos e o 5- multiplicador fazer 10 ciclos. 3 ^ 15 = 14.348.907, 4 ^ 12 = 16.777.216 e 5 ^ 10 = 9.765.625. Se houver apenas 4 pressionamentos de tecla restantes, fazer um multiplicador de 3 é melhor do que colar mais 4 vezes, essencialmente fazendo com que o multiplicador 4 anterior se torne um multiplicador de 8. Se houver apenas 3 pressionamentos de tecla restantes, um multiplicador 2 é o melhor.
fonte
Suponha que você tenha x caracteres na área de transferência e x caracteres na área de texto; vamos chamá-lo de "estado x".
Vamos pressionar "Colar" algumas vezes (eu denoto por
m-1
por conveniência), depois "Selecionar tudo" e "Copiar"; após esta sequência, chegamos ao "estado m * x". Aqui, perdemos um total de m + 1 pressionamentos de tecla. Portanto, o crescimento assintótico é (pelo menos) algo comof^n
, onde f =m^(1/(m+1))
. Acredito que seja o máximo crescimento assintótico possível, embora (ainda) não possa provar.Tentar vários valores de m mostra que o máximo para f é obtido para
m=4
.Vamos usar o seguinte algoritmo:
(não tenho certeza se é o ideal).
O número de vezes para pressionar A no início é 3: se você pressioná-lo 4 vezes, perderá a oportunidade de dobrar o número de A em mais 3 pressionamentos de tecla.
O número de vezes para pressionar Colar no final não é mais do que 5: se você tiver 6 ou mais pressionamentos de tecla restantes, você pode usar Colar, Colar, Colar, Selecionar tudo, Copiar, Colar ao invés.
Então, temos o seguinte algoritmo:
(não tenho certeza se é o ideal). O número de caracteres após a execução é algo como
3 * pow(4, floor((n - 6) / 5)) * (2 + (n - 1) % 5)
.Valores da amostra: 1,2,3,4,5,6,9,12,15,18,24,36,48,60,72,96,144,192,240,288, ...
fonte
O que segue usa a segunda edição do OP de que colar não substitui o texto existente.
Observe algumas coisas:
Cada sequência razoável de teclas pode ser interpretada como um grupo de Ys separados por Xs, por exemplo, YYYXYXYYXY. Denote por V (s) o número de 'A's produzidos pela sequência s. Então V (nXm) = V (n) * V (m), porque X essencialmente substitui todo Y em m por V (n) 'A's.
O problema de copiar e colar é, portanto, isomórfico ao seguinte problema: "usando m + 1 números que somam Nm, maximiza seu produto." Por exemplo, quando N = 6, a resposta é m = 1 e os números (2,3). 6 = 2 * 3 = V (YYXYYY) = V (AA ^ A ^ C ^ V ^ V) (ou V (YYYXYY) = V (AAA ^ A ^ C ^ V).)
Podemos fazer algumas observações:
Para um valor fixo de
m
, os números a escolher sãoceil( (N-m)/(m+1) )
efloor( (N-m)/(m+1) )
(em qualquer combinação que faça a soma funcionar; mais especificamente, você precisará(N-m) % (m+1)
ceils
e os demaisfloor
s). Isto porque, paraa < b
,(a+1)*(b-1) >= a*b
.Infelizmente, não vejo uma maneira fácil de encontrar o valor de
m
. Se esta fosse minha entrevista, eu proporia duas soluções neste momento:Opção 1. Faça um loop em todos os possíveis
m
. Uman log n
solução O ( ).Código C ++:
Opção 2. Permitir
m
obter valores não inteiros e encontrar seu valor ótimo tomando a derivada de[(N-m)/(m+1)]^m
em relação am
e resolvendo para sua raiz. Não há solução analítica, mas a raiz pode ser encontrada usando, por exemplo, o método de Newton. Em seguida, use o piso e o teto dessa raiz para o valor dem
e escolha o que for melhor.fonte
fonte
Aqui está minha abordagem e solução com o código abaixo.
Abordagem:
Existem três operações distintas que podem ser realizadas.
Agora, dadas as três operações distintas e suas respectivas saídas, temos que percorrer todas as permutações dessas operações.
Suposição:
Agora, alguma versão desse problema afirma que a sequência de pressionamentos de tecla, Ctrl + A -> Ctrl + C -> Ctrl + V, sobrescreve a seleção destacada. Para levar em consideração essa suposição, apenas uma linha de código precisa ser adicionada à solução abaixo, onde a variável impressa no caso 2 é definida como 0
Para esta solução
O código abaixo irá imprimir algumas sequências e a última sequência é a resposta correta para qualquer N. por exemplo, para N = 11 esta será a sequência correta
Com a suposição
A, A, A, A, A, C, S, V, V, V, V,: 20:
Sem suposições
A, A, A, C, S, V, V, C, S, V, V,: 27:
Legenda das teclas:
'A' - A
'C' - Ctrl + A
'S' - Ctrl + C
'V' - Ctrl + V
Código:
fonte
Usando os truques mencionados nas respostas acima, Matematicamente, a Solução pode ser explicada em uma equação como,
4 + 4 ^ [(N-4) / 5] + ((N-4)% 5) * 4 ^ [(N-4) / 5]. onde [] é o maior fator inteiro
fonte
Há uma compensação entre imprimir mAs manualmente e, em seguida, usar Ctrl+ A, Ctrl+ Ce Nm-2 Ctrl+ V. A melhor solução está no meio. Se o máximo de pressionamentos de tecla = 10, a melhor solução é digitar 5 As ou 4 As.
tente usar isso Veja este http://www.geeksforgeeks.org/how-to-print-maximum-number-of-a-using-given-four-keys/ e talvez otimize um pouco procurando os resultados em torno do meio ponto.
fonte
Aqui está minha solução com programação dinâmica, sem um loop aninhado, e que também imprime os caracteres reais que você precisa digitar:
Esta é a saída ('a' significa 'CTRL + A', etc.)
fonte
Se N toques de tecla forem permitidos, o resultado será N-3.
A's -> N-3
CTRL+ A-> Selecionando esses N caracteres: +1
CTRL+ C-> Copiando esses N caracteres: +1
Ctrl+ V-> Colando os N caracteres. : +1 ie, (Uma vez que selecionamos todos os caracteres usando CTRL+ A) Substituindo esses caracteres N-3 existentes pelos N-3 caracteres copiados (que está substituindo os mesmos caracteres) e o resultado é N-3.
fonte
→
. Isso melhorará a legibilidade da sua resposta!