Saya sedang menulis beberapa permainan kuis dan memerlukan komputer untuk menyelesaikan 1 permainan dalam kuis jika pemain gagal menyelesaikannya.
Data yang diberikan:
- Daftar 6 angka yang akan digunakan, misalnya 4, 8, 6, 2, 15, 50.
- Nilai yang ditargetkan, dimana 0 ‹ nilai ‹ 1000, misalnya 590.
- Operasi yang tersedia adalah pembagian, penjumlahan, perkalian dan pembagian.
- Tanda kurung dapat digunakan.
Menghasilkan ekspresi matematika yang evaluasinya sama, atau sedekat mungkin, dengan nilai target. Misalnya untuk bilangan di atas, ekspresi dapat berupa : (6 + 4) * 50 + 15 * (8 - 2) = 590
Algoritma saya adalah sebagai berikut:
- Hasilkan semua permutasi dari semua himpunan bagian dari bilangan yang diberikan dari (1) di atas
- Untuk setiap permutasi, hasilkan semua kombinasi tanda kurung dan operator
- Lacak nilai terdekat saat algoritme berjalan
Saya tidak dapat memikirkan optimasi cerdas apa pun pada algoritma brute force di atas, yang akan mempercepatnya sesuai urutan besarnya. Saya juga harus mengoptimalkan untuk kasus terburuk, karena banyak permainan kuis akan dijalankan secara bersamaan di server.
Kode yang ditulis hari ini untuk mengatasi masalah ini adalah (hal-hal relevan yang diambil dari proyek):
from operator import add, sub, mul, div
import itertools
ops = ['+', '-', '/', '*']
op_map = {'+': add, '-': sub, '/': div, '*': mul}
# iterate over 1 permutation and generates parentheses and operator combinations
def iter_combinations(seq):
if len(seq) == 1:
yield seq[0], str(seq[0])
else:
for i in range(len(seq)):
left, right = seq[:i], seq[i:] # split input list at i`th place
# generate cartesian product
for l, l_str in iter_combinations(left):
for r, r_str in iter_combinations(right):
for op in ops:
if op_map[op] is div and r == 0: # cant divide by zero
continue
else:
yield op_map[op](float(l), r), \
('(' + l_str + op + r_str + ')')
numbers = [4, 8, 6, 2, 15, 50]
target = best_value = 590
best_item = None
for i in range(len(numbers)):
for current in itertools.permutations(numbers, i+1): # generate perms
for value, item in iter_combinations(list(current)):
if value < 0:
continue
if abs(target - value) < best_value:
best_value = abs(target - value)
best_item = item
print best_item
Ini mencetak : ((((4*6)+50)*8)-2). Mengujinya sedikit dengan nilai berbeda dan tampaknya berfungsi dengan benar. Saya juga memiliki fungsi untuk menghapus tanda kurung yang tidak perlu tetapi tidak relevan dengan pertanyaan sehingga tidak diposting.
Masalahnya adalah hal ini berjalan sangat lambat karena semua permutasi, kombinasi dan evaluasi ini. Di Mac Book Air saya, ini berjalan selama beberapa menit untuk 1 contoh. Saya ingin menjalankannya dalam beberapa detik paling lama di mesin yang sama, karena banyak contoh permainan kuis akan dijalankan pada waktu yang sama di server. Jadi pertanyaannya adalah:
- Bisakah saya mempercepat algoritme saat ini (berdasarkan urutan besarnya)?
- Apakah saya melewatkan algoritma lain untuk masalah ini yang akan berjalan lebih cepat?
<number> { <operation> <number> }+
yang dapat diurai menjadi hasil<number>
, mengingat operasi dibatasi hingga 4, penguraian dari kiri ke kanan, dan angka tidak digunakan kembali.. Algoritme linier yang lengkap pasti ada, karena ada Ada sejumlah kemungkinan kombinasi yang terbatas dengan cara ini - person Khaled.K   schedule 19.12.2013division, addition,
division,
multiplication and division
? Oh, tunggu,op_map
termasuk'-': sub
. - person greybeard   schedule 08.03.2019