Il mio "portachiavi" mi sta annoiando! Aiutami a trovare un numero minimo di tasti


13

Ringraziamenti a @ Agawa001 per aver posto questa domanda.

Spiegazione

Il mio nuovo "keybore" ha solo 2 pulsanti, vale a dire +e -.

Il numero in memoria inizia alle 0.

Ogni volta che si preme +o -si incrementa / diminuisce la memoria esattamente per quante volte è stata premuta consecutivamente.

Pertanto, se si preme +4 volte, la prima volta si aggiunge 1, la seconda volta si aggiunge 2, la terza volta si aggiunge 3, la quarta volta si aggiunge 4, dandoti 10(dieci).

Ora, se premi -3 volte, la prima volta sottrae 1, la seconda volta 2, la terza volta 3, lasciandoti con 4(quattro).

TL; DR

Data una stringa di + e -, dividila ad ogni cambio di carattere. Quindi ogni stringa risultante di +simboli m aggiunge il numero del triangolo M e ogni stringa di -simboli n sottrae il numero del triangolo n.

Procedura dettagliata

Ora, se ancora non capisci, ti mostrerò come +++--+--crea 1.

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

Compito

  • Prenderai un intero positivo come input, come argomento funzionale o da STDIN.
  • Quindi, verrà emesso / stampato il numero minimo di sequenze di tasti necessarie per creare quel numero utilizzando il metodo sopra.

Casi test

Poiché la riorganizzazione delle serie +o -dà lo stesso numero, per ciascuno di questi gruppi viene elencata solo la sequenza lessicograficamente più antica.

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 | ++++++++++++++++++++++++++-+++-+++

Risorse extra

punteggio

Questo è . Vince la soluzione più breve in byte.


9
Vuol dire che ... sei sotto pressione?
Busukxuan,

Penso che tu stia bene con 10 casi di test ora (incluso il mio).
Erik the Outgolfer,

@ ΈρικΚωνσταντόπουλος È stato aggiunto il caso di test 12, con una leggera modifica (poiché +++++--è anche un'alternativa, ma ho rimosso ++-++++poiché equivale a ++++-++). Ho ancora un altro caso che vorrei aggiungere in seguito nel caso qualcuno riesca a trovare una soluzione efficiente, se riesco a generarlo.
Sp3000,

@ Sp3000 non volevo essere ++-++++rimosso. Inoltre, questa era la MIA modifica, non LA TUA.
Erik the Outgolfer,

@ ΈρικΚωνσταντόπουλος È elencata solo 1 soluzione per ogni set di soluzioni equivalenti - Ho pensato che se fossero state elencate tutte le soluzioni minime, i casi di test sarebbero inutilmente lunghi (ci sono 6 soluzioni per 40 e 17 soluzioni per 97). Mi scuso se questa intenzione non era chiara. Inoltre mancavi +++++--(o, equivalentemente, --+++++), motivo per cui ho sentito la necessità di modificare in primo luogo.
Sp3000,

Risposte:


2

Python 2, 119 byte

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:])

Approccio a forza bruta molto lento. La terza riga calcola il punteggio di una stringa x; le altre linee si sovrappongono a tutte le possibili stringhe binarie fino a quando non viene trovata una il cui punteggio è uguale all'argomento.

@Leaky ha salvato tre byte!


s/x==n and len/(x==n)*len/
Leaky Nun,

Potrebbe salvare alcuni byte per sbarazzarsi di se usare solo la divisione ripetuta, in questo modo:def f(n): \n while n>0:print n%2;n/=2
Leaky Nun

2

Pyth, 25 byte

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

Provalo online.

Questo è estremamente inefficiente e la memoria si esaurisce per f(n)≥ 11. Calcola f(22)= 10 in circa 10 secondi sul mio laptop.

Spiegazione

  • A partire da 1, scorrere tra i numeri T. ( f)
    • Genera tutte le partizioni di T. ( ./T)
    • Genera tutte le permutazioni di quelli. ( .pM)
    • Appiattire l'elenco. ( s)
    • Unifica l'elenco. ( {) Questo passaggio può essere rimosso, ma rende il codice molto più veloce.
    • Filtra le permutazioni risultanti delle partizioni: ( f)
      • Moltiplica ogni numero ddella partizione ( *R) da solo più uno ( hd). Questo dà il doppio del numero da aggiungere / sottrarre al risultato.
      • Taglia l'elenco a parti di lunghezza 2. ( c... 2)
      • Sottrai qualsiasi secondo numero in quelle parti dal secondo numero. ( -M)
      • Somma i risultati. Questo dà il doppio del numero risultante se la permutazione della partizione è stata interpretata come numero di aggiunte, quindi sottrazioni, ecc.
      • Prendi il valore assoluto. ( .a) Se il risultato è stato negativo, scambiando le aggiunte e le sottrazioni si ottiene il risultato positivo.
      • Controlla se il risultato è uguale al doppio dell'input. ( qyQ) In questo caso la permutazione della partizione è corretta, restituirla.
    • Se il filtro restituiva risultati, c'era una soluzione di lunghezza T. Ritorna e stampa T.

2

MATL , 43 29 byte

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

Questa è memoria e tempo inefficiente. Il compilatore online può gestire solo fino all'input 45.

Provalo online!

Ecco una versione modificata con tutti i casi di test fino a 40(ci vuole quasi un minuto nel compilatore online).

Spiegazione

In questo modo vengono testate tutte le possibili sequenze di tasti premute di ogni lunghezza, in ordine crescente, fino a quando non viene trovata una sequenza valida.

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

@ Sp3000 Ne ho aggiunto anche uno, quindi, per riferimento, 4, 6, 9 e 19 sono i casi di test a cui si fa riferimento, in ordine.
Erik the Outgolfer,

1

Python, 105 100 byte

Utilizza una ricerca in ampiezza inefficiente.

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 è un elenco utilizzato come coda
  • m è il valore della sequenza all'inizio della lista
  • t è l'ultimo numero aggiunto a m
  • l è la lunghezza della sequenza che ha generato m
  • o è +/- 1, il segno è opposto al segno di t

Modifica: Leaky Nun ha rasato cinque byte.


s/m,t,l,h=0,0,0,[]/m=t=l=0,h=[]/
Leaky Nun

s/while m!=n/while m-n/
Leaky Nun
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.