Meu “furo de chave” é um chato para mim! Ajude-me a encontrar um número mínimo de pressionamentos de tecla

13

Créditos para @ Agawa001 por ter feito essa pergunta.

Explicação

Meu novo "furo de chave" possui apenas 2 botões, a saber +e -.

O número na memória começa em 0.

Cada pressão consecutiva +ou -incrementa / diminui a memória exatamente quantas vezes ela foi pressionada consecutivamente.

Portanto, se você pressionar +4 vezes, na primeira vez em que adicionar 1, na segunda vez em adicionar 2, na terceira vez em adicionar 3 e na quarta vez em adicionar 4, fornecendo a você 10(dez).

Agora, se você pressionar -3 vezes, na primeira vez subtrai 1, na segunda vez 2, na terceira vez 3, deixando você com 4(quatro).

TL; DR

Dada uma sequência de + e -, divida-a a cada mudança de caractere. Então, cada sequência resultante de m +símbolos adiciona o m-ésimo número do triângulo e cada seqüência de n -símbolos subtrai o n-ésimo número do triângulo.

Walk-through

Agora, se você ainda não entende, mostrarei como +++--+--cria 1.

Program   | Counter | Memory
----------------------------
          |  0      | 0
+         | +1      | 1
++        | +2      | 3
+++       | +3      | 6
+++-      | -1      | 5
+++--     | -2      | 3
+++--+    | +1      | 4
+++--+-   | -1      | 3
+++--+--  | -2      | 1

Tarefa

  • Você receberá um número inteiro positivo como entrada, como argumento funcional ou de STDIN.
  • Em seguida, você imprimirá / imprimirá o número mínimo de teclas necessárias para criar esse número usando o método acima.

Casos de teste

Como reorganizar as execuções +ou -fornece o mesmo número, para cada grupo, apenas a sequência lexicograficamente mais antiga é listada.

Input | Output | Possible corresponding sequences
-------------------------------------------------
    4 |      5 | -+++-
    6 |      3 | +++
    9 |      5 | ++++-
   11 |      7 | +++-+++
   12 |      7 | +++++--, ++++-++
   19 |      8 | -++++++-
   39 |     12 | +++++++++---
   40 |     13 | +++++++++---+, ++++++++-+++-
   45 |      9 | +++++++++
   97 |     20 | ++++++++++++++--+---, +++++++++++++-++++--, ++++++++++++-++++++-
  361 |     34 | ++++++++++++++++++++++++++-+++-+++

Recursos extras

Pontuação

Isso é . A solução mais curta em bytes vence.

Freira Furada
fonte
9
Isso significa que você está com o teclado?
Busukxuan 29/05
Acho que você está bem com 10 casos de teste agora (incluindo o meu).
Erik the Outgolfer
@ ΈρικΚωνσταντόπουλος O caso de teste 12 foi adicionado, com uma ligeira modificação (já que +++++--também é uma alternativa, mas eu removi ++-++++porque isso é equivalente a ++++-++). Ainda tenho mais um caso que gostaria de adicionar mais tarde, caso alguém tenha uma solução eficiente, se eu conseguir gerá-la.
Sp3000
@ Sp3000 Eu não queria ++-++++remover. Além disso, esta foi a minha edição, não a sua.
Erik the Outgolfer
@ SolutionρικΚωνσταντόπουλος Apenas 1 solução de cada conjunto de soluções equivalentes é listada - pensei que, se todas as soluções mínimas fossem listadas, os casos de teste seriam desnecessariamente longos (existem 6 soluções para 40 e 17 soluções para 97). Peço desculpas se essa intenção não foi clara. Também estava faltando +++++--(ou, equivalentemente --+++++), e foi por isso que senti a necessidade de editar em primeiro lugar.
Sp3000

Respostas:

2

Python 2, 119 bytes

def g(n,i=0,s=''):
 c=x=t=0
 for d in s:C=int(d)*2-1;t=(c==C)*t+1;c=C;x+=c*t
 return(x==n)*len(s)or g(n,i+1,bin(i)[3:])

Abordagem de força bruta muito lenta. A terceira linha calcula a pontuação de uma string x; as outras linhas passam por todas as seqüências binárias possíveis até encontrar uma pontuação igual à do argumento.

@Leaky salvou três bytes!

Lynn
fonte
s/x==n and len/(x==n)*len/
Leaky Nun
Ele pode salvar alguns bytes para se livrar de se usar apenas divisão repetida, como este:def f(n): \n while n>0:print n%2;n/=2
Leaky Nun
2

Pitão, 25 bytes

ffqyQ.as-Mc*RhdY2{s.pM./T

Experimente online.

Isso é extremamente ineficiente e fica sem memória por f(n)≥ 11. Calcula f(22)= 10 em cerca de 10 segundos no meu laptop.

Explicação

  • A partir de 1, percorra os números T. ( f)
    • Gere todas as partições de T. ( ./T)
    • Gere todas as permutações dessas. ( .pM)
    • Achate a lista. ( s)
    • Unifique a lista. ( {) Esta etapa pode ser removida, mas torna o código muito mais rápido.
    • Filtre as permutações resultantes das partições: ( f)
      • Multiplique cada número dda partição ( *R) por ele próprio mais um ( hd). Isso fornece o dobro do número para adicionar / subtrair ao resultado.
      • Pique a lista em partes do comprimento 2. ( c2)
      • Subtraia qualquer segundo número nessas partes do segundo número. ( -M)
      • Soma os resultados. Isso fornece o dobro do número resultante se a permutação da partição foi interpretada como número de adições, subtrações etc.
      • Tome o valor absoluto. ( .a) Se o resultado foi negativo, a troca das adições e subtrações obtém o resultado positivo.
      • Verifique se o resultado é igual ao dobro da entrada. ( qyQ) Nesse caso, a permutação da partição está correta, retorne-a.
    • Se o filtro retornou algum resultado, havia uma solução de comprimento T. Devolva e imprima T.
PurkkaKoodari
fonte
2

MATL , 43 29 bytes

E:"@TFEqZ^!"@Y'tQ**s]vGE=a?@.

Isso é ineficiente na memória e no tempo. O compilador online pode manipular 45apenas entradas .

Experimente online!

Aqui está uma versão modificada com todos os casos de teste até 40(leva quase um minuto no compilador online).

Explicação

Isso testa todas as seqüências possíveis de pressionar teclas de cada tamanho, em ordem crescente, até que uma sequência válida seja encontrada.

E:       % Range [1 2 ... 2*N] where N is implicit input. The required sequence length is
         % less than 2*N, so this is enough
"        % For each
  @      %   Push current value: length of sequence
  TFEq   %   Push array [1 -1]
  Z^     %   Cartesian power. Gives all possible sequences of 1, -1 of that length
  !      %   Transpose. Each sequence is now a row
  "      %   For each sequence
    @    %     Push current sequence
    Y'   %     Run-length decoding: Pushes an array of values 1 and -1, and then an
         %     array of run-lengths
    tQ*  %     Duplicate, add 1, multiply. Gives twice the triangular number for each run
    *    %     Multiply element-wise by 1 or -1 to produce correct sign
    s    %     Sum of array. This is the number produced by the current sequence
  ]      %   End for
  v      %   Concatenate all numbers into an array
  GE=a   %   True if any of those numbers equals twice the input
  ?      %   If so
    @    %     Push current sequence length. This is the final result
    .    %     Break loop
         %   End if
         % End for
         % Implicit display
Luis Mendo
fonte
@ Sp3000 Também adicionei um, portanto, para referência, 4, 6, 9 e 19 são os casos de teste mencionados, em ordem.
Erik the Outgolfer
1

Python, 105 100 bytes

Usa uma pesquisa ineficiente em termos de largura.

def k(n):
 m=t=l=0;h=[]
 while m-n:o=1-2*(t>0);(m,t,l),*h=h+[(m+t-o,t-o,l+1),(m+o,o,l+1)]
 return l
  • h é uma lista usada como uma fila
  • m é o valor da sequência no topo da lista
  • t é o último número adicionado a m
  • l é o comprimento da sequência que gerou m
  • o é +/- 1, o sinal é oposto ao sinal de t

Editar: Freira gotejante raspou cinco bytes.

RootTwo
fonte
s/m,t,l,h=0,0,0,[]/m=t=l=0,h=[]/
Leaky Nun
s/while m!=n/while m-n/
Leaky Nun