Kibrit çöpü oyunu programı

Öğ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}")
1 Beğeni

Oyunu oynayan/oynatan var mi?

Minimax ile 100k’ya kadar cozdum sanirim. Bir takim kazanan hamleler:

100k: 65536
10k: 4096
1000: 256
100: 64

“Niye hep 2^n” derseniz, hamle sayisini minimize ediyorum. (Yoksa max. recursion depth’i geciyor, nasil artiriyorduk hatirlamiyorum) 100’u 4 ile kazanmak da mumkun.

Cok daha hizli calisacagini tahmin ettigim bir yontem daha var, onu da bir dahaki bos vaktimde kurcalayacagim.

Algoritma tokusturmak veya test etmek isteyen olursa bot haline getirip bir yerlere koyabilirim.

2 Beğeni

Diger algoritmayi da cikarttim.

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.

1 Beğeni

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.

Oyun olarak bakinca tekrar ilginclesiyor. (Asallari veya hamleleri uretip birakmaktan ziyade.)

Mesela kazanan minimum hamle sayisi sormak, veya oyuna 10,000 hamle limiti koymak gibi.

Belki bir kaç kural eklenerek veya değiştirilerek dediğiniz gibi ilginçleşebilir.

Hatta benim bulduğum örüntüye yasak getirilinebilir. :slight_smile:

Neden?

Google: Chiper.
Google: cryptography

Sebep;

Kriptografide p**n katsayılı polinomlar kullanılarak en büyük asal sayılar ile tahmin edilmez değerler üretilmeye çalışılan bir yöntem vardır.

Dünyanın geri kalanın en büyük asal sayı peşinde koşması nedeni budur.

Aksi halde kaba kuvvet atakları ve tahmin yöntemleri ile p**n polinomları dahi çözülebilir hale gelmektedir.

Hele ki sizde p**n kadar eksilen bir kümeye düşürürseniz tahmin sayıları hızla azaltılabilir. Bu nedenle buradan patternler bulmak mümkün olur.

Başta anlatmak istedim ama sanırım bazan çok yönlü düşünemeyip daha önce deneyimlememiş biri ile empati kuramıyorum.

Biraz daha açıklayıcı yazmam gerekecek not aldım kendime.

Kusura bakma üstat bizim deneyimsizliğimiz.

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.

Ya öyle o an espriyle yazmıştım da evet sonradan okuyunca bana da tuhaf geldi. Düzelttim :slight_smile: