"Keybore" saya sangat membosankan! Bantu saya menemukan penekanan tombol minimal

13

Kredit ke @ Agawa001 untuk pertanyaan ini.

Penjelasan

"Keybore" baru saya hanya memiliki 2 tombol, yaitu +dan -.

Nomor dalam memori dimulai pada 0.

Setiap penekanan berurutan +atau -akan menambah / mengurangi memori untuk berapa kali telah ditekan secara berurutan.

Karena itu, jika Anda menekan +4 kali, pertama kali menambahkan 1, kedua kali menambahkan 2, ketiga kali menambahkan 3, keempat kali menambahkan 4, memberi Anda 10(sepuluh).

Sekarang, jika Anda menekan -3 kali, pertama kali mengurangi 1, kedua 2, ketiga 3, meninggalkan Anda dengan 4(empat).

TL; DR

Diberikan string + dan -, bagilah di setiap perubahan karakter. Kemudian setiap string +simbol m yang dihasilkan menambahkan angka segitiga m-th, dan setiap string -simbol n mengurangi angka segitiga n-th.

Walk-through

Sekarang, jika Anda masih tidak mengerti, saya akan menunjukkan kepada Anda bagaimana cara +++--+--membuatnya 1.

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

Tugas

  • Anda akan mengambil bilangan bulat positif sebagai input, baik sebagai argumen fungsional atau dari STDIN.
  • Kemudian, Anda akan menampilkan / mencetak jumlah penekanan tombol minimum yang diperlukan untuk membuat angka itu menggunakan metode di atas.

Testcases

Karena menata ulang +atau -menjalankan memberikan nomor yang sama, untuk masing-masing kelompok tersebut hanya urutan paling leksikografis yang terdaftar.

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

Sumber daya tambahan

Mencetak gol

Ini adalah . Solusi terpendek dalam byte menang.

Biarawati Bocor
sumber
9
Apakah itu berarti ... Anda keybored?
busukxuan
Saya pikir Anda baik-baik saja dengan 10 test case sekarang (termasuk punyaku).
Erik the Outgolfer
@ ΈρικΚωνσταντόπουλος 12 uji kasus telah ditambahkan, dengan sedikit modifikasi (karena +++++--juga merupakan alternatif, tapi saya dihapus ++-++++karena itu setara dengan ++++-++). Saya masih punya satu kasus lagi yang ingin saya tambahkan nanti kalau-kalau ada yang datang dengan solusi yang efisien, jika saya berhasil menghasilkannya.
Sp3000
@ Sp3000 Saya tidak ingin ++-++++dihapus. Juga, ini adalah edit SAYA, bukan ANDA.
Erik the Outgolfer
@ ΈρικΚωνσταντόπουλος Hanya 1 solusi dari setiap set solusi yang setara terdaftar - Saya berpikir bahwa jika semua solusi minimal terdaftar, kasus uji akan terlalu lama (ada 6 solusi untuk 40 dan 17 solusi untuk 97). Saya minta maaf jika niat itu tidak jelas. Anda juga hilang +++++--(atau, setara, --+++++), itulah sebabnya saya merasa perlu mengedit sejak awal.
Sp3000

Jawaban:

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

Pendekatan brute-force sangat lambat. Baris ketiga menghitung skor string x; baris lain mengulangi semua string biner yang mungkin sampai satu yang nilainya sama dengan argumen ditemukan.

@ Leaky menyimpan tiga byte!

Lynn
sumber
s/x==n and len/(x==n)*len/
Leaky Nun
Mungkin menghemat beberapa byte untuk dihilangkan sdan hanya menggunakan pembagian berulang, seperti ini: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

Cobalah online.

Ini sangat tidak efisien, dan kehabisan memori untuk f(n)≥ 11. Menghitung f(22)= 10 dalam waktu sekitar 10 detik pada laptop saya.

Penjelasan

  • Mulai dari 1, loop melalui angka T. ( f)
    • Hasilkan semua partisi T. ( ./T)
    • Hasilkan semua permutasi dari itu. ( .pM)
    • Ratakan daftar. ( s)
    • Uniquify the list. ( {) Langkah ini bisa dihapus, tetapi itu membuat kode lebih cepat.
    • Memfilter permutasi partisi yang dihasilkan: ( f)
      • Lipat gandakan setiap nomor dpartisi ( *R) dengan sendirinya ditambah satu ( hd). Ini memberi dua kali lipat angka untuk menambah / mengurangi hasil.
      • Potong daftar ke bagian panjang 2. ( c... 2)
      • Kurangi angka kedua di bagian itu dari angka kedua. ( -M)
      • Jumlahkan hasilnya. Ini memberikan dua kali lipat jumlah yang dihasilkan jika permutasi partisi ditafsirkan sebagai jumlah penambahan, kemudian pengurangan, dll.
      • Ambil nilai absolut. ( .a) Jika hasilnya negatif, menukar penambahan dan pengurangan mendapat hasil positif.
      • Periksa apakah hasilnya sama dengan dua kali lipat input. ( qyQ) Dalam hal ini permutasi partisi sudah benar, kembalikan.
    • Jika filter mengembalikan hasil apa pun, ada solusi panjangnya T. Kembali dan cetak T.
PurkkaKoodari
sumber
2

MATL , 43 29 byte

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

Ini adalah memori dan waktu yang tidak efisien. Kompilator online dapat menangani hingga input 45saja.

Cobalah online!

Berikut ini adalah versi yang dimodifikasi dengan semua test case hingga 40(butuh hampir satu menit dalam kompiler online).

Penjelasan

Ini menguji semua urutan penekanan tombol yang mungkin dari setiap panjang, dalam urutan peningkatan panjang, sampai urutan yang valid ditemukan.

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
sumber
@ Sp3000 Saya telah menambahkan satu juga, jadi, untuk referensi, 4, 6, 9 dan 19 adalah test case yang dimaksud, secara berurutan.
Erik the Outgolfer
1

Python, 105 100 byte

Menggunakan pencarian pertama yang tidak efisien.

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 adalah daftar yang digunakan sebagai antrian
  • m adalah nilai urutan di bagian atas daftar
  • t adalah nomor terakhir yang ditambahkan ke m
  • l adalah panjang urutan yang dihasilkan m
  • o adalah +/- 1, tandanya berlawanan dengan tanda dari t

Sunting: Leaky Nun mencukur lima byte.

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