Öğrendiklerimi de ekledikten sonra son hali şudur. Biraz biraz çalışmaya başladı. Bir kaç hamle ilerisini görecek hale nasıl getiririm diye düşünmek lazım.
import asalusliste
import numpy as np
import random
kalancop = 1000000
asal_us_deger = np.array(asalusliste.asal_us)
def asal(n):
for i in range(2,int(n**0.5)+1):
if (n%i) == 0:
return False
return True
def tablo_kucult(copler):
# kalan çöplerin üstündeki değerleri numpy diziden sil
global asal_us_deger
mask = asal_us_deger[:, -1] <= copler
filtrele = asal_us_deger[mask]
asal_us_deger = filtrele
def kalan_kontrol(sayi):
# kalan çöpler listede var mı diye kontrol
# varsa return değeri alma
indexler = np.where(asal_us_deger[:, -1] == sayi)
return indexler[0]
def kullanici_kontrol(p,n):
# işlem yapmak yerine numpy dizisinde var mı yok mu kontrol?
if asal(p) and n>=0 and p**n<=kalancop:
return True
else:
return False
def sistem_sayi(copler):
# kalan asal tablosundan kontrollü bir seçim yapacak
if kalan_kontrol(copler):
index = kalan_kontrol(copler)[0]
return asal_us_deger[index][0],asal_us_deger[index][1],asal_us_deger[index][2]
rast = random.choice(asal_us_deger)
# rast söylenirse eğer kalan kontrol yapacak? (bir sonraki hamle)
return rast[0],rast[1],rast[2]
print("""Bir masa üzerine 1.000.000 (bir milyon) kibrit çöpü bırakılmıştır.
İki kişi bu kibrit çöpleri ile aşağıdaki kurala göre oyun oynuyorlar.
Sırası gelen oyuncu bir asal sayı p ve negatif olmayan bir n sayısı seçip masa üzerinden p^n tane kibrit çöpünü alabiliyor.
(örneğin 8, 1, 25, 5 ,49, 125 vs)
En son kibrit çöpünü alan oyuncu oyunu kazanıyor.""")
while kalancop>0:
p,n = map(int,input("Bir asal ve bir üs giriniz aralarında boşlukla.").split())
if kullanici_kontrol(p,n):
kalancop -= p**n
print(f"Girdiğiniz sayılar {p} ^ {n} ve kalan çöp sayısı {kalancop}")
tablo_kucult(kalancop)
else:
print("Geçersiz, lütfen yeniden girin")
continue
sp,sn,sd= sistem_sayi(kalancop)
kalancop -= sd
print(f"Söylediğim sayılar {sp} ^ {sn} ve kalan çöp sayısı {kalancop}")
Memoizasyonlu minimax’tan cok daha hizli olmadi. Hatta algoritmik kompleksitelerinin esit oldugunu dusunuyorum (O(n^2) veya daha dogrusu onunla O(n π(n) arasinda bir yerde)
1,000,000 copu ~10 dakikada cozdu.
Bu arada cevaplarda o kadar cok duzen/oruntu (pattern) var ki, cok daha hizli cozumlerin uretilebilecegini dusunuyorum. Matematik bilgimi asiyor ama.
Maalesef ben örüntüyü buldum ve benim için tadı kaçtı oyunun. Ama yazarken öğrendiğim şeyler (numpy dizileri vs) yine de yararlı oldu. Sorunun matematiksel örüntüsünü spoiler şeklinde yazıyorum. İsteyen bakabilir veya kendi keşfetmek isteyebilir.
Çözüm Örüntüsü
Oyunun bir noktasında 6 ya bölünebilmeyi yakalayan oyunu kazanıyor. Yani kalan çöp sayısı 6 nın katıysa ve hamle sırası rakipteyse oyunu kazanır. Dolayısı ile oyuna ilk başlayan yerde 6 nın katı şekilde bir sayı bırakır ve aynı örüntüye devam ederse oyunu kazanmış olur.
Nahoş bir cümle olmuş. Biraz daha detaylı anlatıp kod örneğiyle çözümlemeleri göstermem gerekirdi. Zaman ayıramadım. Elimde bir şeyler vardı onlarla uğraşıyordum. Benimkisi bir öz eleştiri. Sizlik bir durum yok.