Lab Rat Yarışı: genetik algoritmalarda egzersiz


113

Bu, Fortnightly Challenge # 3'tür. Tema: Genetik Algoritmalar

Bu zorluk bir deney biraz. Genetik algoritmalarla ne yapabileceğimizi görmek istedik. Her şey en uygun olmayabilir, ancak erişilebilir duruma getirmek için elimizden geleni yaptık. Bu işe yararsa, gelecekte neler görebileceğimizi kim bilebilir. Belki tepenin genetik kralı?

Spec oldukça uzun! Spesifikasyonu Temeller'e ayırmaya çalıştık - çerçeve ile oynamaya başlamak ve bir cevap göndermek için bilmeniz gereken en düşük miktar - ve The Gory Ayrıntıları - tam şartname, denetleyiciyle ilgili tüm detayları içeren, kendi yazabilir.
Herhangi bir sorunuz varsa, bize sohbette katılmaktan çekinmeyin!

Davranış psikolojisinde bir araştırmacısın. Cuma akşamı ve siz ve meslektaşlarınız biraz eğlenmeye karar verin ve laboratuar farelerinizi küçük bir fare yarışı için kullanın. Aslında, onlara duygusal olarak bağlanmadan önce, onlara örnek diyelim .

Örnekler için küçük bir yarış pisti kurdunuz ve daha ilginç hale getirmek için pistte birkaç duvar, tuzak ve ışınlayıcı kullandınız. Şimdi, örnekleriniz hala fareler ... bir tuzağın ya da bir telsizin ne olduğu hakkında hiçbir fikirleri yok. Tek gördükleri farklı renklerde bazı şeyler. Ayrıca herhangi bir belleğe de sahip değiller - tek yapabildikleri mevcut çevrelerine göre kararlar almak. Sanırım doğal seleksiyon yapmayanlardan tuzaktan nasıl kaçınılacağını bilen örnekleri seçecek (bu yarış biraz zaman alacak ...). Oyunlar başlasın!

Kullanılan pano örneği

Bu zorluğun ortaya çıkmasında 84.465 örnek zarar görmüştür.

Temeller

Bu tek oyunculu bir oyundur (siz ve meslektaşlarınız popülasyonları karıştırmak istemediniz, böylece her biri kendi yarış pistini kurdu). Yarış pisti, 15 hücre yüksekliğinde ve 50 hücre genişliğinde dikdörtgen bir ızgaradır . Sol kenardaki rastgele (zorunlu olarak farklı) hücrelerde 15 örnekle başlarsınız (burada x = 0 ). Numuneleriniz, x ≥ 49 ve 0 ≤ y ≤ 14'teki herhangi bir hücre olan hedefe ulaşmaya çalışmalıdır (örnekler pisti sağa aştırabilir). Bu ne zaman olursa olsun, bir puan kazanıyorsun. Ayrıca oyuna 1 puanla başlıyorsunuz. 10.000 dönüşün ardından puanlarınızı en üst düzeye çıkarmaya çalışmalısınız .

Birden fazla örnek aynı hücreyi işgal edebilir ve etkileşime girmez.

Her dönüşte, her bir örnek, çevresinin 5x5'lik bir ızgarasını (kendisi de ortada) görür. Bu ızgaranın her bir hücre, bir renk içerir -1için 15. -1sınır dışı olan hücreleri temsil eder. Numuneniz sınırların dışına çıkarsa ölür. Diğer renklere gelince, bunlar boş hücreleri, tuzakları, duvarları ve teleportları temsil eder. Ancak, numuneniz hangi rengin neyi temsil ettiğini ve neyin sizi temsil ettiğini bilmiyor. Yine de bazı kısıtlamalar var:

  • 8 renk boş hücreleri temsil eder.
  • 4 renk bir telsizi temsil edecektir. Bir telsiz, örneği 9x9 mahallesindeki belirli bir hücreye gönderir. Bu ofset, aynı renkteki tüm ışınlayıcılar için aynı olacaktır.
  • 2 renk duvarları temsil eder. Bir duvara taşınmak, durmakla aynıdır.
  • 2 renk bir tuzağı temsil eder. Bir tuzak göstermektedir bir kendi yakında 9 hücreleri öldürücü (ille tuzak hücre kendisi) 'dir. Bu ofset aynı renkteki tüm tuzaklar için aynı olacaktır.

Şimdi, bu doğal seçilimle ilgili olarak, her numunede 100 bitlik bir sayı olan bir genom vardır . Mevcut iki numunenin çapraz yetiştirilmesi ve ardından genomun hafifçe mutasyona uğramasıyla yeni örnekler oluşturulacaktır. Bir numune ne kadar başarılı olursa, çoğalma şansı o kadar büyük olur.

İşte sizin göreviniz: Bir numunenin gördüğü 5x5 renk ızgarasını ve genomunu girdi olarak alan tek bir fonksiyon yazacaksınız. İşleviniz, örnek için movex ve Δy'nin biri olacağı bir hareket (Δx, ,y) döndürür {-1, 0, 1}. İşlev çağrıları arasında hiçbir veri sürdürmemelisiniz. Bu, kendi rasgele sayı üreteçlerinizi kullanmanızı içerir. İşleviniz, istediğiniz gibi kullanmakta özgür olduğunuz seri bir RNG ile sağlanacaktır.

Gönderiminizin puanı, 50 rastgele parçadaki puan sayısının geometrik ortalaması olacaktır . Bu puanın adil bir miktar değişime tabi olduğunu tespit ettik. Bu nedenle, bu puanlar ön olacaktır . Bu zorluk bir kez sona erdiğinde, son tarih açıklanacak. Son teslim tarihinin sonunda, 100 kurul rastgele seçilecek ve tüm yazılar bu 100 kurulda yeniden değerlendirilecektir. Cevabınıza tahmini bir puan vermek için çekinmeyin, ancak kimsenin aldatmadığından emin olmak için her gönderimi kendimiz puanlayacağız.

Kontrolör programlarını birkaç dilde sağladık. Şu anda, gönderinizi Python (2 veya 3), Ruby , C ++ , C # veya Java ile yazabilirsiniz . Kontrolör tahtaları oluşturur, oyunu çalıştırır ve genetik algoritma için bir çerçeve sağlar. Tek yapmanız gereken hareket eden işlevi sağlamak.

Bekle, peki genomla tam olarak ne yapacağım?

Zorluk, bunu çözmektir!

Örneklerin hafızası olmadığı için, belirli bir sıra ile sahip olduğunuz tek şey, sizin için hiçbir şey ifade etmeyen 5x5 renk ızgarasıdır. Bu nedenle, hedefe ulaşmak için genomu kullanmanız gerekecek. Genel fikir, renkler veya ızgara düzeni hakkındaki bilgileri depolamak için genomun bölümlerini kullanmanızdır ve botunuz kararlarını genomda depolanan ek bilgilere dayandırmaktadır.

Şimdi, elbette orada hiçbir şeyi manuel olarak saklayamazsınız. Böylece orada depolanan gerçek bilgiler başlangıçta tamamen rasgele olacaktır. Ancak, genetik algoritma, yakında yanlış bilgiye sahip olanları öldürürken, genomu doğru bilgiyi içeren örnekleri seçecektir. Amacınız, genom bitlerinden ve görüş alanınıza bir hamle yapmak için bir eşleme bulmaktır, bu da hedefe çabucak bir yol bulmanızı sağlar ve sürekli olarak kazanan bir stratejiye dönüşür.

Başlamanız için bu yeterli bilgi olmalı. İsterseniz, bir sonraki bölümü atlayabilir ve alt kısımdaki denetleyiciler listesinden (bu belirli denetleyicinin nasıl kullanılacağına ilişkin bilgiler de içeren) seçeceğiniz denetleyicinizi seçebilirsiniz.

Hepsini istersen oku ...

Kanlı Detaylar

Bu şartname tamamlandı. Tüm kontrolörler bu kuralları uygulamak zorundadır.

Aksi belirtilmediği sürece tüm rastgelelik düzgün bir dağılım kullanır.

Parça üretimi:

  • İz, dikdörtgen bir ızgaradır, X = 53 hücre genişliğinde ve Y = 15 hücre yüksekliğindedir. İçeren hücreler x ≥ 49 olan hedef hücreler (burada x sıfır bazlı).
  • Her hücre tek bir renge sahiptir ve öldürücü olabilir veya olmayabilir - hücreler, aşağıdaki hücre türlerinden biri tarafından belirtilmedikçe öldürücü değildir.
  • Orada 16 den etiketli farklı hücre renkler, 0için 15, anlamı oyundan oyuna değişir. Ek olarak, -1sınırları aşan hücreleri temsil eder - bunlar öldürücüdür .
  • 8 rastgele renk seçin . Bunlar boş hücreler olacak (etkisiz).
  • 4 daha rastgele renk seçin . Bunlar teleporterler. Bu renklerin ikisi için, 9x9 semtinde sıfır olmayan bir ofset seçin ((0,0) hariç (-4, -4) ila (4,4) arası). Diğer iki renk için bu ofsetleri ters çevirin. Bir örnek bir telici üzerine basarsa, derhal o ofset tarafından taşınır.
  • 2 rastgele renk daha seçin . Bunlar tuzaklar. Bu renklerin her biri için 3x3 semtinde bir ofset seçin ((-1, -1) ila (1,1)). Bir tuzak, bu uzaklıktaki hücrenin öldürücü olduğunu gösterir . Not: Tuzak hücresinin kendisi mutlaka öldürücü değildir.
  • Kalan 2 renk , hareketi engelleyen duvarlardır. Bir duvar hücresine doğru hareket etmeye çalışmak, hareketi hareketsiz kalmaya dönüştürecektir. Duvar hücrelerinin kendileri öldürücüdür .
  • Kılavuzun hedef olmayan her hücresi için rastgele bir renk seçin. Her hedef hücre için rastgele boş bir renk seçin.
  • Pistin sol kenarındaki her hücre için, hedefe 100 tur içinde ulaşılıp ulaşılamayacağını belirleyin ( aşağıdaki sıra sırası kurallarına göre ). Eğer öyleyse, bu hücre kabul edilebilir bir başlangıç ​​hücresidir . 10'dan az başlangıç ​​hücresi varsa, parçayı atın ve yeni bir tane oluşturun.
  • Her biri rastgele genom ve 0 yaşında olan 15 örnek oluşturun . Her örneği rastgele bir başlangıç ​​hücresine yerleştirin.

Dönüş sırası:

  1. Her numune için sırasıyla aşağıdaki adımlar uygulanacaktır. Örnekler etkileşime girmez veya birbirlerini görmez ve aynı hücreyi işgal edebilir.
    1. Örnek yaşı 100 ise , ölür. Aksi takdirde, yaşı 1 ile artar.
    2. Örneğe görüş alanı verilmiştir - numuneye merkezlenmiş 5x5 renk ızgarası - ve 3x3 mahallesinde bir hamle. Bu aralığın dışına taşınması denetleyicinin sonlandırılmasına neden olur.
    3. Hedef hücre bir duvar ise, hareket (0,0) olarak değiştirilir.
    4. Eğer hedef hücre bir teleporter ise, örnek teleporter ofseti tarafından taşınır. Not: Bu adım yinelemeli değil , bir kez gerçekleştirilir .
    5. Hali hazırda örnek tarafından işgal edilen (potansiyel olarak bir teleporter kullandıktan sonra) hücre öldürücü ise, örnek ölür. Bu örneklerin öldüğü tek zamandır (yukarıdaki 1.1. Adımdan ayrı). Özellikle, ölümcül bir hücreye açılan yeni bir numune hemen ölmeyecek, ancak önce tehlikeli hücreden ayrılma şansına sahip olacaktır.
    6. Örnek bir hedef hücreyi kapsıyorsa, bir puan kazanın, örneği rastgele bir başlangıç ​​hücresine taşıyın ve yaşını 0'a ayarlayın.
  2. Tahtada ikiden az numune kalıyorsa, oyun biter.
  3. 0 yaşında 10 yeni örnek oluşturun . Her genom (ayrı ayrı) aşağıdaki üreme kuralları ile belirlenir. Her örneği rastgele bir başlangıç ​​hücresine yerleştirin.

Yetiştirme:

  • Yeni bir örnek oluşturulduğunda , sağa doğru ilerlemiş olan örneklere karşı önyargılı, rastgele iki ayrı ebeveyn seçin . Bir örneğin seçilebilme olasılığı, mevcut zindelik puanıyla orantılıdır . Bir numunenin fitness puanı

    1 + x + 50 * hedefe ulaşma sayısı

    buradaki x , 0 tabanlı yatay dizindir. Aynı sırada oluşturulan örnekler ebeveyn olarak seçilemez.

  • İki ebeveynden ilk genom bitini almak için rastgele birini seçin.

  • Şimdi genom boyunca yürürken, ebeveynleri 0.05 olasılıkla değiştirin ve ortaya çıkan ebeveynden bit almaya devam edin.
  • Tam olarak monte edilmiş genomu mutasyona uğratın: Her bir bit için, olasılık 0.01 ile çevir .

Puanlama:

  • Bir oyun 10.000 tur sürer .
  • Oyuncular oyuna 1 puan ile başlar (geometrik ortalamanın kullanılmasına izin vermek için).
  • Bir örnek hedefe her ulaştığında, oyuncu bir puan alır.
  • Şimdilik, her oyuncunun teslimi , her biri farklı bir rastgele parçaya sahip olan 50 oyun için çalıştırılacak .
  • Yukarıdaki yaklaşım, istenenden daha fazla varyansa neden olur. Bu zorluk bir kez sona erdiğinde, son tarih açıklanacak. Son teslim tarihinin sonunda, 100 kurul rastgele seçilecek ve tüm yazılar bu 100 kurulda yeniden değerlendirilecektir.
  • Bir oyuncunun genel puanı, bu bireysel oyunların puanlarının geometrik ortalamasıdır .

Kontrolörler

Aşağıdaki kontrol cihazlarından herhangi birini seçebilirsiniz (fonksiyonel olarak eşdeğer oldukları için). Bunların hepsini test ettik, ancak bir hata görürseniz, kodu veya performansı geliştirmek istiyorsanız veya grafiksel çıktı gibi bir özellik eklerseniz, lütfen bir sorun yaratın veya GitHub! Ayrıca başka bir dilde yeni bir denetleyici ekleyebilirsin!

README.mdTam kullanım talimatlarını içeren GitHub'da doğru dizine ulaşmak için her denetleyicinin dil adını tıklayın .

Git ve / veya GitHub’a aşina değilseniz, tüm havuzu ön sayfadan ZIP olarak indirebilirsiniz (kenar çubuğundaki düğmeye bakın).

piton

  • En iyisi test edildi. Bu bizim referans uygulamamız.
  • Hem Python 2.6+ hem de Python 3.2+ ile çalışır!
  • Çok yavaş. Önemli bir hızlandırma için PyPy ile çalıştırmanızı öneririz .
  • pygameVeya kullanarak grafik çıktısını destekler tkinter.

Yakut

  • Ruby 2.0.0 ile test edilmiştir. Daha yeni sürümlerle çalışmalı.
  • Aynı zamanda oldukça yavaş, ama Ruby bir sunum için bir fikir prototipleme için uygun olabilir.

C ++

  • C ++ 11 gerektirir.
  • İsteğe bağlı olarak çoklu kullanım destekler.
  • Gruptaki en hızlı kontrolör.

C #

  • LINQ kullanır, bu yüzden .NET 3.5 gerektirir.
  • Oldukça Yavaş.

Java

  • Özellikle yavaş değil. Çok hızlı değil.

Ön Afiş

Tüm puanlar ön. Yine de, eğer bir şey yanlış ya da güncel değilse, lütfen bana bildirin. Örnek gönderimimiz karşılaştırma için listelenmiştir ancak tartışmaya dahil değildir.

  Score   | # Games | User               | Language   | Bot           
===================================================================================
2914.13   |   2000  | kuroi neko         | C++        | Hard Believers
1817.05097|   1000  | TheBestOne         | Java       | Running Star
1009.72   |   2000  | kuroi neko         | C++        | Blind faith
 782.18   |   2000  | MT0                | C++        | Cautious Specimens
 428.38   |         | user2487951        | Python     | NeighborsOfNeighbors
 145.35   |   2000  | Wouter ibens       | C++        | Triple Score
 133.2    |         | Anton              | C++        | StarPlayer
 122.92   |         | Dominik Müller     | Python     | SkyWalker
  89.90   |         | aschmack           | C++        | LookAheadPlayer
  74.7    |         | bitpwner           | C++        | ColorFarSeeker
  70.98   |   2000  | Ceribia            | C++        | WallGuesser
  50.35   |         | feersum            | C++        | Run-Bonus Player
  35.85   |         | Zgarb              | C++        | Pathfinder
 (34.45)  |   5000  | Martin Büttner     | <all>      | ColorScorePlayer
   9.77   |         | DenDenDo           | C++        | SlowAndSteady
   3.7    |         | flawr              | Java       | IAmARobotPlayer
   1.9    |         | trichoplax         | Python     | Bishop
   1.04   |   2000  | fluffy             | C++        | Gray-Color Lookahead

Kredi

Bu zorluk büyük bir işbirlikçi çaba oldu:

  • Nathan Merril: Python ve Java denetleyicileri yazdı. Meydan kavramını bir Tepenin Kralı'ndan bir Sıçan Yarışına çevirdim
  • trichoplax: Oyun testi . Python denetleyicisinde çalıştı.
  • feersum: C ++ denetleyicisini yazdı.
  • VisualMelon: C # kontrol cihazını yazdı.
  • Martin Büttner: Kavramı. Ruby denetleyicisi yazdı. Playtesting. Python denetleyicisinde çalıştı.
  • T Abraham: Oynama testi. Test Python ve C # ve C ++ denetleyicisini inceledi.

Yukarıdaki kullanıcıların tümü (ve muhtemelen unuttuğum bir kaç tane daha) meydan okumanın genel tasarımına katkıda bulunmuştur.

C ++ denetleyici güncellemesi

Visual Studio ile C ++ kullanıyorsanız ve çoklu okuma kullanıyorsanız, çoğaltılmış panoların üretilmesine olanak tanıyan rastgele sayı üreteci tohumlamasıyla ilgili bir hata nedeniyle en son güncellemeyi edinmelisiniz .


3
Birisi sadece bu problem için en uygun genetik algoritmayı bulmak için genetik bir genetik algoritma yapamaz mıydı?
mbomb007

1
@ anon3202 Peki, bu elbette nerede olduğunuzu ölçebildiğiniz için parça düzeni hakkında daha fazla bilgi verir. Temel olarak, botlar için arayüzü basit tutmak ve küresel ilerlemeniz için hangi yerel çözümün en yararlı olduğunu öğrenmek için genomun gerekli olacağı, tamamen yerel bir sorun yapmak istedik.
Martin Ender

1
@matovitch Gory Details’in Sıra Siparişi bölümünün 5. bölümüne bakın (tam 'In particular, a new specimen which spawns on a lethal cell will not die immediately, but has a chance to move off the dangerous cell first.'
özellik

1
Örnek ortalamasını, stddev, stderr ve% 99 eşleşme aralığını ("geometrik" log / exp'inizden önce) göstermek için C ++ kodunu değiştirdim ve şaşırtıcı bir keşif yaptım. "Kör İnanç" cevabı, 50 çalışmadan sonra "Örnek Ortalaması 116529 + - 2.78337e + 010 (% 99) stddev = 7.77951e + 010" değerine sahipti. Geometrik ortalama yine de belirleyici oldu: "159.458 + - 117262 (% 99) stddev = 32.6237" (800 puan güncellemesinden önce)
Mooing Duck

1
Mutasyon oranı ile ilgili bazı deneyler yaptım ve eğer olasılık 0,01'den 0,022'ye yükseltildiyse, bu sayede olasılık% 0,010 olan bir DNA verirse, meydan okuma daha ilginç olurdu (ve kontrolörler çok daha hızlı çalışırdı). mutasyon, geçerli değerle% 37 yerine değişmedi. Bu, saçma nüfus patlamalarını önler (bu da çok fazla hesaplama süresi kazandırır) ve yetersiz çeşitlilik nedeniyle çok fazla başarısızlığı önler. Bireysel puanlar daha düşüktür, ancak daha fazla sayıda koşunun kazananı kazanması nedeniyle, küresel ortalama yükselme eğilimindedir.

Yanıtlar:


37

Kör inanç - C ++ - 2000 çalışmasında 800 (!) Puanın üstünde görünüyor

Gizemli iz geri bildirimi ve etkili duvar çarpma engelleyici renk kodlu genom

#include "./gamelogic.cpp"

#define NUM_COLORS 16

// color meanings for our rats
typedef enum { good, bad, trap } colorType_t;
struct colorInfo_t {
    colorType_t type;
    coord_t offset; // trap relative location
    colorInfo_t() : type(good) {} // our rats are born optimists
};

// all 8 possible neighbours, carefully ordered
coord_t moves_up  [] = { { 1, 0 }, { 1,  1 }, { 1, -1 }, { 0,  1 }, { 0, -1 }, { -1, 0 }, { -1,  1 }, { -1, -1 } };  // toward the goal, going up   first
coord_t moves_down[] = { { 1, 0 }, { 1, -1 }, { 1,  1 }, { 0, -1 }, { 0,  1 }, { -1, 0 }, { -1, -1 }, { -1,  1 } };  // toward the goal, going down first

// map of the surroundings
struct map_t {
    static const size_t size = 5;
    static const int max = size / 2;
    static const int min = -max;
    colorType_t map[size*size];
    colorType_t & operator() (int x, int y) { return map[(x + max)*size + y + max]; }
    colorType_t & operator() (coord_t pos) { return operator()(pos.x, pos.y); }
    bool is_inside(int x, int y) { return abs(x) <= max && abs(y) <= max; }
    bool is_inside(coord_t pos) { return is_inside(pos.x,pos.y); }
};

// trap mapping info
struct trap_t {
    coord_t detector;
    colorInfo_t color;
    trap_t(int x, int y, colorInfo_t & color) : color(color) { detector.x = x; detector.y = y; }
    trap_t() {}
};

coord_t blindFaith(dna_t d, view_t v)
{
    colorInfo_t color[NUM_COLORS]; // color informations

    // decode colors
    for (size_t c = 0; c != 16; c++)
    {
        size_t base = c * 4;
        if (d[base])
        {
            color[c].type = d[base+1] ? good : bad;
        }
        else // decode trap location
        {
            color[c].type = trap;
            int offset = d[base+1] + 2 * d[base+2] + 4 * d[base+3];
            color[c].offset = moves_up[offset]; // the order is irrelevant as long as all 8 neighbours are listed
        }
    }

    // build a map of the surrounding cells
    map_t map;
    unsigned signature = 0;
    int i = 0;
    for (int x = map.min; x <= map.max; x++)
    for (int y = map.min; y <= map.max; y++)
    {
        int c = v(x, y);
        map(x, y) = (c == -1) ? bad : color[c].type;
        if (c != -1) signature ^= v(x, y) << ((i++) % 28);
    }

    // map traps
    for (int x = map.min; x <= map.max; x++)
    for (int y = map.min; y <= map.max; y++)
    {
        if (map(x, y) != trap) continue;
        const colorInfo_t & trap = color[v(x, y)];
        int bad_x = x + trap.offset.x;
        int bad_y = y + trap.offset.y;
        if (!map.is_inside(bad_x, bad_y)) continue;
        map(bad_x, bad_y) = bad;
        map(x, y) = good;
    }

    // pick a vertical direction according to surroundings signature
    int go_up = d[64 + signature % (DNA_BITS - 64)];

    // try to move to a good cell nearer the goal
    for (const coord_t &move : go_up ? moves_up : moves_down) if (map(move.x, move.y) == good) return move;

    // try not to increase fitness of this intellectually impaired specimen
    return{ -1, 0 };
}

int main() {
    time_t start = time(NULL);
    double score = runsimulation(blindFaith);
    slog << "Geometric mean score: " << score << " in " << time(NULL) - start << " seconds";
}

Örnek sonuçlar:

Scores: 15 4113306 190703 1 1 44629 118172 43594 63023 2 4 1 1 205027 1 455951 4194047 1 5 279 1 3863570 616483 17797 42584 1 37442 1 37 1 432545 5 94335 1 1 187036 1 4233379 1561445 1 1 1 1 35246 1 150154 1 1 1 1 90141 6 1 1 1 26849 1 161903 4 123972 1 55 988 7042063 694 4711342 90514 3726251 2 1 383389 1 593029 12088 1 149779 69144 21218 290963 17829 1072904 368771 84 872958 30456 133784 4843896 1 2 37 381780 14 540066 3046713 12 5 1 92181 5174 1 156292 13 1 1 29940 66678 125975 52714 1 5 3 1 101267 69003 1 1 10231 143110 282328 4 71750 324545 25 1 22 102414 1 3884626 4 28202 64057 1 1 1 1 70707 4078970 1623071 5047 1 1 549040 1 1 66 3520283 1 6035495 1 79773 1 1 1 218408 1 1 15 33 589875 310455 112274 1 1 4 1 3716220 14 180123 1 2 12785 113116 12 2 1 59286 822912 2244520 1840950 147151 1255115 1 49 2 182262 109717 2 9 1049697 59297 1 11 64568 1 57093 52588 63990 331081 54110 1 1 1537 3 38043 1514692 360087 1 260395 19557 3583536 1 4 152302 2636569 12 1 105991 374793 14 3934727 1 2 182614 1 1675472 121949 11 5 283271 207686 175468 1 1 173240 1 138778 1 1 59964 3290382 1 4 1757946 1 23520 1 2 94 1 124577 497071 1749760 39238 1 301144 3 1 2871836 1 1 10486 1 11 8 1 111421 11 1807900 1 587479 1 42725 116006 3 1 6 5441895 1 1 22 52465 952 1 18 1 1 46878 2 1 1 1994 4 593858 123513 4692516 820868 4247357 1 1 2 1 2 8770 2 1 95371 4897243 2 22741 1 1 1 1 325142 6 33650 4 51 102993 1 182664 1 4040608 18153 2045673 462339 1 1 617575 2 2551800 3 7760 1 108012 76167 143362 1148457 1 53460 1 71503 1 1 1 1 81482 3208 62286 69 139 1 3503941 1 253624 101903 3081954 80123 84701 9 16 1 1070688 71604 613064 2076 15009 9 1 1 1 199731 1 2 1 63132 1 1843855 27808 1 3569689 273144 1 460524 2703719 22443 10876 51242 1 6972678 4591939 1 140506 43981 45076 2 1 91301 5 1 1874615 1758284 608 13 1 96545 75161 1 618144 4 2056133 1 1 2 57401 1394307 6 188116 83545 1 41883 1 1 467189 371722 1 1122993 1 17912 159499 1 5 3355398 33 1 2 246304 1 2 168349 1 50292 12 141492 2723076 3 1 6 3060433 223360 171472 106409 1 2 1 102729 8814 1 285154 1 11 1 65 930 2 689644 3271116 1 5 4 60 77447 1 1 1477538 256023 100403 2480335 1 39888 1 1 70052 66090 1 250 1 2 8 115371 1523106 1424 168148 1 1 1 42938 17 1 364285 185080 1 1 36 4903764 13 51987 1106 276212 67460 1 251257 2 6867732 1 1 1890073 1 1 8 5 2118932 210 0 3792346 5209168 1 1 1 1 51 1 4621148 1 37 337073 3506096 1 1 1 1 458964 2 16 52930 1 15375 267685 1 1 1259646 14930 3248678 527105 1 103 24 1 3252685 6009 1 1 176340 3971529 121 1722808 1 31483 194232 2314706 95952 3625407 3 216755 56 1 8 1 1 1 1 885 229 9056 172027 31516 2526805 1 76076 1589061 1 1 8 90812 1 21 72036 1681271 2 212431 1581814 85993 79967 4 7 514708 1070070 1 71698 1 23478 15882 94453 1 27382 495493 277308 12127 91928 248593 1 1 1 26540 1709344 2119856 1 1 48867 107017 251374 64041 15924 15 87474 8 1 23 9 48 1 1 1 51793 2 61029 84803 15 689851 1 1 873503 10 140084 420034 87087 82223 1 163273 12 1 5 570463 19 26665 1 170311 1 39983 1 475306 1 2 36417 746105 11 141345 1 3 1 30 3 1 1 1 1 1312289 408117 1 42210 273871 561592 1 1 1 1 4448568 48448 7 378508 1 351858 278331 1 79515 1169309 3670107 14711 4686395 1156554 33 2528441 24537 76 335390 63545 122108 76675 21929 34 1 861361 83000 417781 1 90487 1 1 85116 7 2 1 60129 647991 79 1 2755780 726845 244217 50007 187212 1 3674051 286071 44068 3 307427 26973 1 26059 1957457 230783 58102 545318 1 4 172542 168365 1 89402 1 4 1 1 1 1 2 3 16 62935 5643183 117961 109942 85762 5 117376 118883 1 61 23893 122536 70185 1 64252 208409 179269 55381 1579240 3434491 1 4964284 3356245 3 21 2197119 346542 44340 59976 772220 5590844 199721 90858 63785 125989 57219 129737 81836 1 3671 16810 1 4151040 1 15 40108 1 443679 3224921 2 27498 2 3 146529 169409 19 1 1 1 1 41627 1 3 2722438 1 2013730 1 1649406 1 1 6943 125772 58652 1 1 1 2413522 1 2 48 36067 253807 2 146464 1 248 07 3359223 139896 395985 65241 43988 594638 69033 275085 1 17973 1 1 1 594835 1 1 4468341 3496274 222854 94769 55 161056 36185 8793 277592 3 1 6746 1 138151 66 37365 1 2729315 1 3 57091 22408 249875 246514 85058 1 20 5463152 1 3 1 45293 1 70488 2792458 461 441 951926 2236205 2 171980 1 1 48 3893009 1 458077 1 268203 1 70005 7 19299 1 278978 1 45286 26 2 1883506 274393 342679 1 1 913722 911600 12688 1 1 115020 1249307 1529878 53426 1 226862 3721440 23537 86033 397433 1 1 1 161423 96343 94496 1 1 1 2 1 111576 1 4039782 1 1 1 5742393 3569 46072 1 1 2 1 1 85335 219988 1 78871 115876 43405 1 300835 1 166684 53134 1 3 111487 6 3 3 77 1 115971 3 205782 10 1932578 356857 43258 47998 1 27648 127096 573939 32650 523906 45193 1 2 128992 1 10144 1 257941 1 19841 5077836 14670 5 3 6 1 1 21 14651 2906084 37942 45032 9 304192 3035905 6214026 2 177952 1 51338 1 65594 46426 553875 2676479 245774 95881 3 216364 3064811 1198509 223982 3 6 1 533254 1 590363 264940 68346 127284 1 7 1 1 4617874 5 45400 1 1 3097950 360274 1 3 1 8421 14 469681 418563 3 1 6 1 1 575766 405239 11 2631108 152667 1 1 1 467383 1 1 775499 1 157998 2 1 143351 92021 1 1 1173046 3636579 1 70635 162303 1 1534876 834682 2 1 1 11981 346908 245124 607794 17 1570641 126995 13 57050 1 2 33731 29739 1 1 35460 1 33716 168190 214704 1 443156 701674 2636870 108081 1604895 1 1 11 115901 23 571891 360680 1 1 35 1 2036975 1 1 2555536 4742615 5 360553 287044 1 1814255 7 59632 1 216 41546 1 540920 353424 2625301 223744 1 1 1 15717 3 429871 1 4 2329632 18 11 1 2 4 1 3905 5 1 1 1 2 5431442 1 859628 1 3 338378 15236 13764 1 3384362 1 15 65293 24 619599 152620 2 189921 35854 16647 7 2 404790 360096 1 2 189459 1097768 191610 1 1 470254 1 12 2 330299 364219 2365542 312023 2273374 2 10527 1 115453 1 2 3845592 52388 913449 1 14695 1 44 37352 90302 1 1 1 233577 51639 3474983 44010 1650727 31 2 2 1 8 7 1 3 5 25603 17799 45630 758457 1 4571839 37 4 3 2 1 1 1351271 196673 12 2880765 263886 2926173 1 2 1 241502 5 6 1 278576 9 7 290722 42749 143391 82753 21771 57887 1 1 60400 1766903 1 296392 1 5 2861787 125560 1 9 199218 1 1 308226 517598 2246753 12 1168981 3 98447 1 488613 9 842865 202108 10 1 238493 1 1523706 5383982 29435 1 1 207071 1 8 4 125742 70531 253135 72207 124291 23364 184376 2 40034 9569353 194109 102854 2 3247153 58313 85995 1 598 63 1 2676692 10 3573233 1 36651 118016 2486962 65456 46760 1 5813 723 178120 2 153305 1 1 2 1 2354413 3 1 17126 132953 437123 299778 3070490 1 6490 403704 2261 511439 1 39 33410 173045 1 1 120970 641346 132042 1 44906 1 33940 132124 467702 45472 9 44 1 1 1 107008 1 46635 1 121431 130760 1 7 3 1 56251 1299306 3 1 1 1 15 2147678 215169 1374943 1 332995 231089 269310 1 7816944 1 1 1 46 134426 1 1 1 2 76112 1 1 30438 299927 25 139373 76048 278757 71 3474997 1 294046 1 3126554 2518019 2 1 6 1 3054393 1 1 1 2 525 96 419528 1 1 154718 233 207879 26 1 6 57436 3 5944942 1 1 318198 147536 1 22 420557 1 1 120938 1 1 167412 4082969 73299 1 11 3557361 1 4 330028 269051 1 2569546 2 1 1 4 1 1 377412 1 1 1 213800 58131 1422177 54 109617 117751 12432 3830664 419046 3 6821 741 919 1 22335 1 1 15069 80694 488809 2389 2308679 145548 51411 115786 110984 107713 1 12 6 1 5 8365 1 2001874 210250 4674015 14 1 1204101 314354 89066 1 1 2438200 68350 1 1575329 5593838 2743787 151670 57 16 5948210 597158 128060 189160 23628 1 1 15 4171774 1 8206 4157492 1 2 315607 1618680 24736 18520 4787225 33842 134431 1 1 1 1 1 1115809 17759 1 33016 123117 1 77322 169633 219091 1 321593 57231 135536 175401 4 1 435702 1 253132 100707 114547 1 119324 6382967 1472898 3 72567 1707408 177958 26 208719 1 27083 74 12 576410 19375 177069 4 3 1 31 507048 2 1 1 2 1 2 1 40 7 99892 95202 60649 241396 232370 1 136579 70649 1 2877 280695 13603 102860 404583 29717 112769 1 54089 1 97579 40819 2 868629 64848 2 63432 5 1 1888426 99623 2 1 7911 53646 3047637 1 2 3 152910 1 3244662 105187 1 1 1 1 8966 200347 1 1 22 302654 6 17 1 10 328150 55259 1016 117291 2 1 224524 23846 74645 1 1 1 1 1 3117394 10847 33976 144613 4 201584 1 1 26959 3 4410588 27019 6 66749 55935 23 4126812 4089989 99959 1 1 1 1 55490 1 4275599 13652 33967 2 8126062 337093 320653 128015 4 1 7729132 1 10594 116651 20990 3046630 1 353731 132989 2066431 4 80 15575 147430 1 621461 3100943 2306122 5 33439 407945 25634 1 2911806 32511 2174235 298281 15159 54125 1 2 3063577 2205013 1 407984 1 319713 1 22171 1 2763843 1 2607606 1 100015 3096036 1 55905 1 1 635265 2890760 1 1 1 1 35854 1 352022 2652014 1 2 274366 1 4 1 602980 4 83828 602270 2816 2 59116 25340 1 11 1 5162051 34 8 218372 1186732 142966 1 1 170557 503302 1 84924 5 1 1350329 1 1 1 130273 78055 902762 1 8581 5 1 3635882 1 1 1 224255 44044 61250 2 438453 8 1 2729357 28 1 17658 82640 1 31809 10 1 33 1 1 45495 5798 5000217 40018 588787 67269 1 12 83512 2798339 1 609271 1 3 1 7 67912 189808 3388775 60961 81311 1167 24939 433791 405306 85934 1 1170651 2 1 66 552579 122985 515363 2188340 1 1 1 3807012 1502582 4 13 149593 1 1 2108196 3 34279 24613 1282047 27 1 2 1 1 584435 27487 1 1 5 33278 1 1 1202843 1 1 1 6 3649820 3100 2 266150 13 164117 10 53163 3295075 1 1 1 1 77890 1 286220 90823 18866 3139039 481826 1 3994676 23 116901 132290 6 3927 84948 1 1 1 1 256310 1 11 8 1 102002 8392 887732 98483 444991 1 1 49408 409967 1158979 1 1 1 81469 189764 3960930 296231 64258 1 1 176030 4 1 2 1 486856 1 1135146 31 2 13112 227077 31
Geometric mean score: 831.185 in 14820 seconds

Feersum'un gönülsüzce uzun testine dayanarak, 2000 çalışmanın kabul edilebilir bir şekilde kararlı bir sonuç üretmek için yeterli olduğunu düşünüyorum.
Değiştirilmiş kontrolörüm her çalışmadan sonra mevcut geometrik ortalamayı gösterdiğinden, son 50 çalışmadaki varyasyonun nispeten küçük (+ - 10 puan) olduğunu görsel olarak onayladım.

Bu yaratıkları tıkatan nedir?

Her renge eşit öncelik vermek yerine, şu olası değerleri göz önünde bulundururum:

  1. iyi -> sıçan orada güvenle gidebileceğini düşünüyor
  2. kötü -> sıçan oraya gitmeyecek
  3. tuzak -> fare kapanı pozisyonunu dikkate alacaktır bad ve tuzak gösteren hücreyi iyi .
    Yeniden adlandırmak için tembel olmama rağmen, bu gerçek bir tuzağın, bir duvarın, şüphesiz bir gezginin tatsız bir yere, hatta bir ölülerin girişine gönderilmesini bekleyen bir telsizi belirten bir "tehlike dedektörü". -son. Kısacası, akıllı bir farenin gitmeyeceği bir yer.

iyi veya kötü genlerin depolanması sadece 2 bit alır (örneğin 11ve 10), ancak tuzaklar 4 bit gerektirir ( 0tttburada ttt8 olası "tehlikeli" konumdan birini temsil eder).

(Yani anlam sonra sabit bir konumda olduğu için, her bir renk-kodlama geni gerektirir tamamen farklı bir genom içine karıştırılmış tutma) tutarlı her genin tutmak için, tüm değerler 4 bit kodlanır (çok iyi olarak kodlanır 11xxve kötü olarak 10xx), toplamda 16 * 4 = 64 bit.

Kalan 36 bit, "duvar çarpması önleyici" olarak kullanılır (daha fazlası için). Çevreleyen 25 renk, bu 36 bitin bir dizinine eklenir. Her bit, iki hücre arasında olası bir seçim olduğunda kullanılan tercih edilen bir dikey yönü (yukarı veya aşağı) gösterir.

Strateji aşağıdaki gibidir:

  • genom göre her bir rengi çözer (veya "kötü" hücreler için doğrudan kontrolör raporu)
  • yakın çevreye bir harita oluşturun (3x3 hücre, 8 olası komşu)
  • çevrenin bir imzasını hesaplar (iz bırakmayan hücreler hariç 25 rengin bir karması)
  • İmzadan tercih edilen dikey bir yön seçin (36 karma kova arasından)
  • hedefe en yakın olanlardan başlayıp ilk önce tercih edilen dikey yöne giden "iyi" olarak işaretlenen bir komşuya gitmeye çalışın
  • Eğer hiçbir "iyi" komşu bulunamazsa, bir hücreyi geri hareket ettirmeye çalışın (bu nedenle muhtemelen talihsiz bir kazanın mağduru olmak ve herhangi bir oranda zindeliği artırmaktan kaçının)

Siz kemirgenler, türünüzün düşmanlarına bakın

korkunç duvar ışınlanma döngüsü

Bir popülasyonun başına gelebilecek en kötü şey henüz kazananı kazanmamış olmaktır, ancak bir duvarda veya üreme için seçilme şansını yakalama hedefine yetecek kadar yakın bir ışınlanma döngüsünün içine sıkışmış birçok sıçan vardır .
Bir tuzakta ezilmiş veya duvarlara ışınlanmış sıçanların aksine, bu kemirgenler sadece yaşlılar tarafından öldürülecektir.
Kuzenleri karşısında rekabet avantajları yoktur, başlangıçtan itibaren 3 hücreye sıkışmışlardır, ancak genomları baskın hale gelinceye kadar kretin üretilmesinden sonra üremeye yetecek kadar zamana sahip olacaklar, bu nedenle genetik çeşitliliği iyi bir nedenden dolayı kötü şekilde zarar verecek.

Bu fenomeni hafifletmek için, fikir bu kötü, kötü farelerin yavrularını atalarının adımlarını takip etmekten kaçınması daha muhtemel kılmaktır.
Dikey yön göstergesi yalnızca 1 bit uzunluğundadır (temel olarak "bu çevrede ilk önce yukarı ya da aşağı gitmeyi dene" diyerek) ve birkaç bitin izlenen yolu etkileme olasılığı yüksektir, bu nedenle mutasyonların ve / veya geçitlerin önemli bir etkisi.
Bir çok yavru farklı bir davranış sergileyecek ve aynı duvarda (açlıkta bulunan atalarının cesetleri arasında) başlarını çarpmayacak.
Buradaki alt tezi, bu endikasyonun sıçanın davranışındaki baskın faktör olmadığıdır. Çoğu zaman renk yorumlaması hâlâ geçerli olacak (yukarı / aşağı seçimi sadece gerçekten iki "iyi" olması durumunda önemli olacaktır.ve sıçanın zararsız bir renk olarak gördüğü şey, onu duvara dökmeyi bekleyen bir telsiz değil.

Neden işe yarıyor?

Hala nedenini tam olarak bilmiyorum.

Çözülemeyen bir gizem kalan mutlak şans felsefesi tuzak haritalama mantığıdır. Kuşkusuz başarının temel taşıdır, ancak kendi gizemli yöntemleriyle çalışır.

Kullanılan kodlamayla, rastgele bir genom% 25 "iyi",% 25 "kötü" ve% 50 "tuzak" renk tanımlayıcıları üretecektir.
"tuzak" tanımlayıcıları, 5x5 çevresi ile bağlantılı olarak "iyi" ve "kötü" tahminler üretecektir.
Sonuç olarak, belirli bir yerdeki bir sıçan dünyayı "istikrarlı ve bağlamsal" gitme / gitme "renklerinin bir karışımı olarak" görecektir ".

Oldukça başarılı bir çarpışma önleme mekanizmasının belirttiği gibi, pistteki en kötü eleman türü korkutucu duvar (ve onun ışınlanma döngüsünün kuzeni), ama sanırım bunlar çok daha az yaygındır).

Sonuç olarak, başarılı bir program her şeyden önce, hedefe ulaşmadan yavaş bir açlığa yol açacak pozisyonları tespit edebilen sıçanlar geliştirmeyi başarmalıdır.

Duvarları temsil eden iki rengi "tahmin etmeden" bile, "tuzak" renkleri, bir farenin duvarları "gördüğünden" değil, "tuzak" tahmininin önüne koyduğu için birkaç engeli aşmasına izin vererek duvarın önlenmesine katkıda bulunur gibi görünmektedir. bu özel ortamda belirli duvar hücreleri.

Sıçan, hedefe doğru hareket etmeye çalışsa da (ki bu, en "faydalı" tuzak göstergelerinin önündeki bir tehlike olduğunu düşünmesine neden olabilir), tüm tuzak yönlerinin kabaca aynı etkiye sahip olduğunu düşünüyorum: "bir sıçanın önüne yerleştirilmiş 2 hücre, sıçan tam üstünde durduğunda" ileride tehlikeyi "belirten ile aynı etkiye sahiptir.

Bu karışımın genomun bu kadar başarılı bir şekilde birleşmesini sağlama özelliği neden matematiğimin ötesinde.

Duvar caydırıcı caydırıcılığını daha rahat hissediyorum. Bu sadece planladığım gibi çalıştı, beklentilerimin oldukça üzerinde olmasına rağmen (puan temelde dörtle çarpıldı).

Bazı verileri görüntülemek için kumandayı ağır bir şekilde kırdım. İşte birkaç çalışma:

Turns:2499 best rat B  B  B  G  B  G  T3 G  T4 B  G  B  B  B  G  G  ^vv^^vv^v^v^^^vvv^v^^^v^^^v^vv^^v^^^ Max fitness: 790 Specimens: 1217 Score: 2800
Turns:4999 best rat B  B  B  G  B  G  T3 G  T4 B  G  B  B  B  G  G  ^vv^^vv^v^v^^^vvv^v^^^v^^^v^vv^^v^^^ Max fitness: 5217 Specimens: 15857 Score: 685986
Turns:7499 best rat B  B  B  G  B  G  T3 G  T4 B  G  B  B  B  G  G  ^vv^^vv^v^v^^^vvv^v^^^vvvvv^^v^v^^^^ Max fitness: 9785 Specimens: 31053 Score: 2695045
Turns:9999 best rat B  B  B  G  B  G  T3 G  T4 B  G  B  B  B  G  G  ^vv^^vv^v^v^^^vvv^v^^^vvvvv^^v^v^^^^ Max fitness: 14377 Specimens: 46384 Score: 6033904
Scored 6035495 in game 146 current mean 466.875

Burada bir süper-sıçan ırkı erken göründü (parkurun muhtemelen düz bir çizgide çalışmasına izin verildi ve ilk nesillerdeki bazı şanslı sıçanlar bundan faydalanmak için doğru DNA'ya sahipti). Sonundaki örneklerin sayısı, yaklaşık 100.000 farenin teorik maksimumunun yarısı kadardır, bu, eleştirmenlerin neredeyse yarısının bu belirli parçada süresiz olarak hayatta kalma kabiliyeti kazandığı anlamına gelir (!).
Tabii ki, sonuçta elde edilen puan sadece müstehcen - bu arada hesaplama zamanı gibi.

Turns:2499 best rat B  T0 G  B  T7 B  G  B  T6 T0 T3 B  G  G  G  T4 ^v^^^^^v^^v^v^^^^^^^^v^v^v^^vvv^v^^^ Max fitness: 18 Specimens: 772 Score: 1
Turns:4999 best rat T7 G  G  G  G  T7 G  B  T6 T0 T3 T5 G  G  B  T4 ^vvvvvvv^^^vvv^^v^v^^^^^^^^^^^^^v^^^ Max fitness: 26 Specimens: 856 Score: 1
Turns:7499 best rat G  T0 G  T3 G  T0 G  B  T6 T0 T2 B  T4 G  B  T4 ^^v^vvv^^^vv^^v^vvv^v^^vvvv^^^^^^^^^ Max fitness: 55 Specimens: 836 Score: 5
Turns:9999 best rat T6 T0 G  T5 B  T1 G  B  T6 T0 T3 B  T4 G  B  T4 ^^vv^^^^vv^^v^v^^v^^vvv^vv^vvv^^v^^v Max fitness: 590 Specimens: 1223 Score: 10478
Scored 10486 in game 258 current mean 628.564

Burada işte genomda incelme görebiliriz. Son iki genom arasındaki soy açıkça ortaya çıkıyor. İyi ve kötü değerlendirmeler en önemli bulunmaktadır. Tuzak endikasyonları onlar ya bir "yararlı" olarak stabilize kadar salınmaya görünüyor tuzağına ya dönüşmeye iyi veya kötü .

Renk genlerinin birkaç yararlı özelliği olduğu görülüyor:

  • kendi kendine yeten bir anlama sahiptirler
    (belirli bir rengin belirli bir şekilde ele alınması gerekir)
    Her renk kodlaması, davranışı dramatik biçimde değiştirmeden tamamen farklı bir genom içine atılabilir - renk aslında belirleyici bir durum olmadıkça (tipik olarak) sonsuz bir döngüye neden olan bir duvar veya teleporter).
    Bu, temel öncelikli kodlamaya sahip durum için daha az geçerlidir, çünkü en öncelikli renk nereye taşınacağına karar vermek için kullanılan tek bilgidir. Burada tüm "iyi" renkler eşittir, bu nedenle "iyi" listesine eklenen belirli bir renk daha az etkili olacaktır.
  • bunlar
    iyi / kötü kodlamanın 4'ten sadece 2 önemli bitine sahip olduğu mutasyonlara karşı nispeten dirençlidir ve tuzak konumu çoğu zaman sıçan davranışını önemli ölçüde değiştirmeden değiştirilebilmektedir.
  • onlar küçüktür (4 bit), bu yüzden bir geçit tarafından enkaza alınma olasılığı çok düşüktür.
  • mutasyonlar anlamlı değişikliklerden zararsız olarak üretirler
    "İyi" olarak mutasyon yapan bir genin ya da çok az etkisi olur (örneğin, boş bir hücreye karşılık gelirse, yeni, daha kısa bir yol bulmasına izin verebilir, ancak sıçanı doğruca içine götürebilir) bir tuzak) ya da dramatik olanı (eğer renk bir duvarı temsil ederse, yeni sıçanın bir yere sıkışması çok muhtemeldir).
    "Tuzağa" sıçrayan bir gen, sıçanı temel bir renkten mahrum edecektir ya da gözle görülür bir etkisi yoktur.
    Bir tuzak bölgesinin değişmesi ancak ileride bir tuzak (ya da zararlı herhangi bir şey) varsa, bunun nispeten küçük bir olasılığı vardır (1/3 gibi bir şey söyleyebilirim).

Son olarak, son 36 bitin yalnızca farelerin sıkışmasını önlemek için değil, aynı zamanda fareleri pistte daha eşit şekilde yaymaya katkıda bulunmadığını, böylece kazanan bir genom ortaya çıkıp renk kodlama kısmı boyunca baskın hale gelinceye kadar genetik çeşitliliğin korunmasına katkıda bulunduğunu tahmin ediyorum.

Daha fazla iş

Söylemeliyim ki bu küçük yaratıklar büyüleyici.
Bu mükemmel mücadeleye katkıda bulunan herkese tekrar teşekkürler.

Başarılı bir farenin ataları gibi daha önemli verileri görüntülemek için kontrol cihazını daha fazla kasaplamayı düşünüyorum.

Bu fareleri çalışırken görmek de çok isterdim, ama bir dilin bu C ++ b ** ch'ı yaratıyor - tek başına canlandırıyor - görüntüleri (birçok şeyin yanında) dağınık bir angarya.

Sonunda, en azından tuzak sisteminin bir açıklamasını yapmak ve muhtemelen iyileştirmek istiyorum.

Denetleyici hack

Birisi ilgileniyorsa, denetleyicide yaptığım değişiklikleri yayınlayabilirim.
Kirli ve ucuzlar ama işi yapıyorlar.

Ben GitHub meraklısı değilim, bu yüzden sadece bir yazıdan geçmek zorunda kalacaktı.


16
10.000 oyunla 208.14 puan aldı. 1000 için test etmeye çalışıyordum ama fazladan 0 yazdığımı hiç fark etmemiştim, bu yüzden 7 saatten fazla sürdü.
feersum,

Lol hepinize teşekkür ederim. İki 1000 koşuşumla karşılaştırdığımda, 2000 koşusu daha sonra kararlı bir sonuç vermiş gibi görünüyor.

Ne ^^v^vvv^^^vv^^v^vvv^v^^vvvv^^^^^^^^^anlama geliyor? Gerisini tahmin edebilirim ama bu konuda sorun yaşıyorum?
Mooing Duck

Her seferinde bir sıçan çalıştıran ayrı bir "hata ayıklama" denetleyicisi yapmayı düşünüyordum ve her yeni sıçan üretildiğinde, hem ebeveynlerin hem de çocuğun DNA'sını gösterir (bazı özelleştirilebilir işlevlerle). Bu, sıçanın nasıl çalıştığını incelemeyi çok daha kolaylaştırır.
Mooing Duck

2
Bu, 36 "yukarı / aşağı" gösterge bitini temsil eder, ancak bu örneklerde kazanan DNA zaten baskın hale gelmiştir, bu yüzden fazla değişmezler.

18

Sert inananlar - C ++ - (gelişmiş teleporters): 2000 çalışma için 10.000+

(Bu Kör inancının bir evrimidir , bu yüzden bundan önce bir başka metin duvarına tırmanmak isteyebilirsiniz)

#ifndef NDEBUG
#define NDEBUG
#include "./gamelogic.cpp"
#endif // NDEBUG
#include <cassert>

#define NUM_COLORS 16
#define BITS_OFFSET  3
#define BITS_TYPE    2
#define BITS_SUBTYPE 2
#define BITS_COLOR (BITS_TYPE+BITS_OFFSET)

// how our rats see the world
typedef unsigned char enumSupport_t;
typedef unsigned char trapOffset_t;
typedef enum : enumSupport_t {
    danger,   // code      trap detector
    beam,     // code      safe teleporter
    empty,    // code      empty
    block,    // code      wall, pit or teleporter
    trap,     // computed  detected trap
    pit,      // read      off-board cell
} colorType_t;

// color type encoding (4 first bits of a color gene)
// the order is critical. A single block/empty inversion can cost 2000 points or more
const colorType_t type_decoder[16] = {
    /*00xx-*/
    danger,
    empty,
    beam,
    block,
    /*01xx-*/
    beam,
    danger,
    empty,
    block,
    /*10xx-*/
    empty,
    beam,
    block,
    danger,
    /*11xx-*/
    block,
    empty,
    danger,
    beam,
};

// all 8 possible neighbours, carefully ordered
typedef coord_t neighborhood_t[8];
neighborhood_t moves_up =   { { 1, 0 }, { 1,  1 }, { 1, -1 }, { 0,  1 }, { 0, -1 }, { -1, 0 }, { -1,  1 }, { -1, -1 } };  // toward the goal, going up   first
neighborhood_t moves_down = { { 1, 0 }, { 1, -1 }, { 1,  1 }, { 0, -1 }, { 0,  1 }, { -1, 0 }, { -1, -1 }, { -1,  1 } };  // toward the goal, going down first

// using C++ as a macro-assembler to speedup DNA reading
/*
Would work like a charm *if* a well-paid scatterbrain at Microsoft had not defined
std::bitset::operator[] as

bool operator[](size_t _Pos) const
{   // subscript nonmutable sequence
return (test(_Pos));
}

Bounds checking on operator[] violates the spec and defeats the optimization.
Not only does it an unwanted check; it also prevents inlining and thus generates
two levels of function calls where none are necessary.
The fix is trivial, but how long will it take for Microsoft to implement it, if
the bug ever makes it through their thick layer of tech support bullshit artists?
Just one of the many reasons why STL appears not to live up to the dreams of
Mr Stroustrup & friends...
*/
template<size_t BITS> int DNA_read(dna_t dna, size_t base)
{
    const size_t offset = BITS - 1;
    return (dna[base + offset] << offset) | DNA_read<offset>(dna, base);
}
template<> int DNA_read<0>(dna_t, size_t) { return 0; }

// color gene
struct colorGene_t {
    colorType_t  type;
    trapOffset_t offset;  // trap relative location
    colorGene_t() : type(empty) {} // our rats are born optimists
};

// decoded DNA
class dnaInfo_t {
private:
    const dna_t & dna;
    static const size_t
        direction_start = NUM_COLORS*(BITS_TYPE + BITS_OFFSET),
        direction_size = DNA_BITS - direction_start;

public:
    colorGene_t color[NUM_COLORS];
    int         up_down; // anti-wall-banger

    // decode constant informations during construction
    dnaInfo_t(const dna_t & d) : dna(d)
    {
        for (size_t c = 0; c != NUM_COLORS; c++)
        {
            unsigned raw = DNA_read<BITS_COLOR>(d, c * BITS_COLOR);
            color[c].type = type_decoder[raw >> 1];
            if      (color[c].type == danger) color[c].offset = raw & 7;
            else if (color[c].type == beam  ) color[c].offset = raw & 3;
        }
    }

    // update with surroundings signatures
    void update(size_t signature)
    {
        // anti-blocker
        up_down = (direction_size > 0) ? dna[direction_start + signature % direction_size] : 0;
    }
};

// map of the surroundings
class map_t {
    struct cell_t {
        coord_t pos;
        int     color;
    };

    static const size_t size = 5;
    static const int max = size / 2;
    static const int min = -max;

    size_t local_signature[size*size]; // 8 neighbours signatures for teleporters
    cell_t track_cell[size*size]; // on-track cells
    size_t cell_num;
    colorType_t map[size*size];
    size_t raw_index(int x, int y) { size_t res = x * size + y + max + max * size; assert(res < size*size); return res; }
    size_t raw_index(coord_t pos) { return raw_index(pos.x, pos.y); }

    bool is_inside(int x, int y) { return abs(x) <= max && abs(y) <= max; }

public:
    size_t compute_signatures(view_t v, dnaInfo_t genome)
    {
        cell_num = 0;
        size_t signature = 0;
        memset (local_signature, 0, sizeof(local_signature));
        int i = 0;
        for (int x = min; x <= max; x++)
        for (int y = min; y <= max; y++)
        {
            int c = v(x, y);
            if (c == -1)
            {
                (*this)(x, y) = pit; continue;
            }
            track_cell[cell_num++] = { { x, y }, c };
            signature ^= c << (4 * (i++ & 1));

            if (genome.color[c].type == beam)
            {
                int in = 0;
                for (coord_t n : moves_up)
                {
                    coord_t pn = {x+n.x,y+n.y};
                    if (!is_inside(pn)) continue;
                    int cn = v(pn.x, pn.y);
//                    if (cn == -1) continue;
                    local_signature[raw_index(pn.x,pn.y)] ^= cn << (4 * (in++ & 1));
                }
            }
        }
        return signature;
    }

    void build(dnaInfo_t genome)
    {
        coord_t traps[size*size];
        size_t t_num = 0;

        // plot color meanings
        for (size_t c = 0; c != cell_num; c++)
        {
            const cell_t& cell = track_cell[c];
            const colorGene_t& color = genome.color[cell.color];
            (*this)(cell.pos) = (color.type == beam && (local_signature[raw_index(cell.pos.x,cell.pos.y)] % 4) == color.offset)
                    ? block
                    : color.type;

            // build a list of trap locations
            if (color.type == danger)
            {
                coord_t location = cell.pos + moves_up[color.offset];
                if (is_inside(location)) traps[t_num++] = location;
            }
        }

        // plot trap locations
        while (t_num) (*this)(traps[--t_num]) = trap;
    }

    // quick & dirty pathing
    struct candidate_t {
        coord_t pos;
        candidate_t * parent;
        candidate_t() {} // default constructor does not waste time in initializations
        candidate_t(int) : parent(nullptr) { pos.x = pos.y = 0; } // ...this is ugly...
        candidate_t(coord_t pos, candidate_t * parent) : pos(pos), parent(parent) {} // ...but so much fun...
    };

    coord_t path(const neighborhood_t & moves)
    {
        candidate_t pool[size*size]; // private allocation for express garbage collection...
        size_t alloc;

        candidate_t * border[size*size]; // fixed-size FIFO 
        size_t head, tail;

        std::bitset<size*size>closed;

        // breadth first search. A* would be a huge overkill for 25 cells, and BFS is already slow enough.
        alloc = head = tail = 0;
        closed = 0;
        closed[raw_index(candidate_t(0).pos)] = 1;
        border[tail++] = new (&pool[alloc++]) candidate_t(0);
        while (tail > head)
        {
            candidate_t & candidate = *(border[head++]); // FIFO pop
            for (const coord_t move : moves)
            {
                coord_t new_pos = candidate.pos + move;
                if (is_inside(new_pos))
                {
                    size_t signature = raw_index(new_pos);
                    if (closed[signature]) continue;
                    closed[signature] = 1;
                    if ((*this)(new_pos) > empty) continue;
                    if (new_pos.x == 2) goto found_exit; // a path to some location 2 cells forward
                    assert(alloc < size*size);
                    assert(tail < size*size);
                    border[tail++] = new(&pool[alloc++]) candidate_t(new_pos, &candidate); // allocation & FIFO push
                    continue;
                }
                // a path out of the 5x5 grid, though not 2 cells forward
            found_exit:
                if (candidate.parent == nullptr) return move;
                candidate_t * origin;
                for (origin = &candidate; origin->parent->parent != nullptr; origin = origin->parent) {}
                return origin->pos;
            }
        }

        // no escape
        return moves[1]; // one cell forward, either up or down
    }

    colorType_t & operator() (int x, int y) { return map[raw_index(x, y)]; }
    colorType_t & operator() (coord_t pos) { return operator()(pos.x, pos.y); }
    bool is_inside(coord_t pos) { return is_inside(pos.x, pos.y); }
};

std::string trace_DNA(const dna_t d, bool graphics = false)
{
    std::ostringstream res;
    dnaInfo_t genome(d);
    for (size_t c = 0; c != NUM_COLORS; c++)
    {
        if (graphics)
        {
            res << "tbew--"[genome.color[c].type];
            if (genome.color[c].type == danger) res << ' ' << moves_up[genome.color[c].offset].x << ' ' << moves_up[genome.color[c].offset].y;
            if (genome.color[c].type == beam) res << ' ' << genome.color[c].offset << " 0";
            if (c != NUM_COLORS - 1) res << ',';
        }
        else switch (genome.color[c].type)
        {
        case danger: res << "01234567"[genome.color[c].offset]; break;
        case beam  : res <<     "ABCD"[genome.color[c].offset]; break;
        default: res << "!*-#X@"[genome.color[c].type]; break;
        }
    }
    return res.str();
}

coord_t hardBelievers(dna_t d, view_t v)
{
    dnaInfo_t genome(d); // decoded DNA
    map_t     map;       // the surroundings seen by this particular rodent

    // update genome with local context
    genome.update(map.compute_signatures(v, genome));

    // build a map of the surrounding cells
    map.build(genome);

    // move as far to the right as possible, in the contextually preffered direction
    return map.path(genome.up_down ? moves_up : moves_down);
}

int main() {
    time_t start = time(NULL);
    double score = runsimulation(hardBelievers, trace_DNA);
    slog << "Geometric mean score: " << score << " in " << time(NULL) - start << " seconds";
}

Bölüm IV: Rulmanlarımızı şebekeye alma

Sonuçlar

Scores: 309371 997080 1488635 1 19 45832 9 94637 2893543 210750 742386 1677242 206614 111809 1 1738598 1 1 342984 2868939 190484 3354458 568267 280796 1 1 1 679704 2858998 1 409584 3823 200724 1 973317 849609 3141119 1 1987305 1 1 57105 245412 1223244 2 1603915 2784761 9 12 1 1839136 1 298951 2 14 138989 501726 1365264 308185 707440 22 772719 17342 63461 3142044 19899 3 409837 48074 3549774 138770 32833 1 1 1184121 67473 310905 1996452 4201 1701954 2799895 2041559 218816 174 433010 51036 1731159 1871641 1 23 2877765 1 127305 27875 626814 142177 2101427 167548 2328741 4 8433 2674119 2990146 466684 1 2 8 83193 388542 2350563 1 1140807 100543 1313548 31949 73117 73300 121364 1899620 1280524 1 10726 12852 7 2165 1 3 44728 2 122725 41 2 1902290 3 1 8581 70598 1148129 429767 1 112335 1931563 521942 3513722 1 2400069 1 3331469 141319 220942 205616 57033 63515 34 6 1419147 1983123 1057929 1 599948 2730727 2438494 5586 268312 1728955 1183258 95241 1537803 11 13 1157309 1750630 1 1 2690947 101211 3463501 1 258589 101615 212924 137664 19624 251591 509429 510302 1878788 1 4045925 1 21598 459159 118663 7 3606309 3 13016 17765 640403 1 72841 695439 1 135297 2380810 1 43 31516 14 1442940 1001957 95903 194951 1 238773 773431 1 1 975692 2 4990979 52016 3261784 2 413095 12 3 420624 7905 60087 760051 2702333 2572405 1 1717432 1 12 3040935 1 1 31787 60114 513777 1 3270813 9639 581868 127091 270 164228 274393 1275008 261419 597715 138913 28923 13059 1848733 2895136 7754 14 1 107592 1 3557771 2067538 147790 112677 119004 1 13791082842974 249727 838699 4067558 6 470799 695141 1 3 1 1276069 23691 831013 5 165142 1236901 1 187522 2599203 1 67179 81345 44111 2909946 94752 7 406018 991024 4 1 3 573689 6 748463 2166290 33865 670769 322844 5657 1131171 1990155 5 4536811 1785704 3226501 2030929 25987 3055355 192547 1761201 433330 27235 2 312244 13203 756723 81459 12 1 1 54142 307858 2 25657 30507 1920292 3945574 1 191775 3748702 3348794 4188197 366019 1540980 3638591 1 1840852 1 26151 2888481 112861 8 11 2 1 27231 1 74 106853 3 173389 2390495 25 1 83116 3238625 75443 1 1 2125260 1 49626 1 6 312084 159735 358268 54351 367201 2868856 5779 172554 119016 141728 3 1 6 9 1 1504011 1 168968 1868493 1 5 1 244563 2 2887999 3144375 1598674 1 1578910 45313 176469 30969 8 127652 1911075 9 1300092 224328 168752 8 1619669 292559 9090 2040459 705819 1852774 10 139217 16 1221670 355060 339599 3 2184244 2546028 1 1 11 70958 242187 1 80737 1 190246 3 1 1 577711 150064 1 1047154 3851461 92399 224270 612237 1 3 3330053 1 1 1192533 615756 267923 144724 2 1 150018 4621881 1 6 299247 115996 2 10 6 185495 76351 465554 178786 1802565 257101 56 2491615 1 24547 1 1203267 32 5741149 541203 11393 1 368082 540534 16167 113481 2004136 13045 17 1 12 333803 14 1955075 1 4 38034 1286203 2382725 26777 1 180312 1 87161 4773392 1244024 1146401 3 80598 2983715 1 63741 1 1 2561436 16 1 1 1807854 1239680 200398 2 46153 1400933 11 5058787 8787 1 98841 89162 1106459 112566 1 4138891 2858906 101835 81375 539485 6587808 1 5359988 1 1 869106 443452 120748 436156 2 2 3944932 1 1875599 2 3081185 733911 447824 1 1 23187 3082414 33 3 1 1 2053904 410824 104571 885952 1946162 2 294773 364169 1 101310 2166548 1177524 2192461 12 4 3457016 90975 2356374 573234 53746 187527 7837 1441335 458407 52139 3387239 2030900 38 1648216 215105 212589 8278 1201586 244282 1 1 1897515 3957343 46 1 134481 1 1 2041785 3 1 37593 163173 1565457 3 1026885 1 34530 4655639 2 18 1940645 1550444 593209 1 2270700 706918 1 1 610113 9 1287883 3 1472134 1998685 1916822 1 296017 2 1 1737607 4155665 1510560 553342 56130 14436 13240604 4025888 1 4253261 174177 2043316 504151 2370989 420666 155232 1 219327 3752236 130062 571247 24 1 29015 31392 1020196 3 1117502 460873 7 1 228 8 133656 1 147008 1 93471 1 1 1 513410 4834094 1 14 1875636 182714 1504903 95263 4418053 1 357853 1135536 3698641 3 239316 4237884 131730 3878724 2158931 55650 1906785 1 26372 32 99217 1645677 379838 1 450352 7329657 112909 1 897980 2114198 308917 126215 1 53839 539997 238036 2 2270000 5 2388928 1668820 519153 58227 347528 1 1 2339954 10 5 2031341 54 2341529 2189774 112731 1 21918 748662 2068921 2 2232504 2923457 97740 3858 16604 398940 388755 1875003 667810 53633 315866 839868 1 7 1 14238 185 4 14 1 2 178947 1965719 398323 120849 48 1397222 961772 34124 2 160652 1 252629 246554 14529 1 299866 135255 490837 2863773 8 10 2 1906405 57 9782 118940 870003 255097 6 4187677 50965 3354376 17611 1804789 183601 158748 1539773 116107 77684 34738 2862836 1 2081903 727739 50328 2740070 17 923524 18 3089706 3144082 1 20 205247 347420 2076952 3725220 39270 2 15 49329 422629 5 1693818 2570558 2146654 1 5 129085 653766 47438 102243 389910 59715 21769 1246783 361571 4 120502 255235 1314165 3 3 5 2902624 76351 3117137 174413 2546645 14534 166054 1013583 1 1 2 9 3027288 3173742 338261 94929 1071263 4659804 1 506576 42798 4 984508 1 4 4 1 18541 7 1 269761 188905 2 1 92011 147031 677955 27484 1291675 2420682 99970 57943 1 4081062 1 250953 704904 4 349180 4273479 30528 2092508 2352781 3700946 1 77799 328993 3684623 3930179 1250080 1975798 54981 1621677 91664 1355832 1084049 721612 56950 197563 246868 5031 1 924076 1328694 58562 1 457662 2445958 1345169 957845 1056809 2485300 1687907 199029 3 9474 86928 1 2419980 3585265 570673 1 1514184 437383 1596697 29709 199606 126031 2 1541777 1 3 2090249 2402438 15 19 1423959 28 37852 4 1652596 1 405512 52 3 1948029 1 2 376 1155902 3 631665 3741991 57673 284026 424787 1 11569 5 1200313 1 20 2360854 1 119994 3889143 673424 797763 1 1 144306 1007659 1231874 75607 1 15 66187 8763 21366 146277 2684501 4458542 162223 3 1 5 94232 3036009 401312 19775 510737 3305062 58905 125783 274094 3089988 118483 1 106213 1 1289180 127905 30 528859 2 1215596 1955900 30 2236528 218643 1 2396631 1598175 1148688 452064 1 1840394 198540 1 1307187 107463 341396 2684981 9602 536871 1 148107 4068 4918434 1 2430254 2066144 88915 3585780 6464 259394 3098337 49601 42 79205 925658 1 2513666 26817 2738302 1 28 345735 5086930 361294 505662 386194 1103890 2653001 412247 4074274 2217918 1 519433 1338570 4289317 140138 18 2519983 168656 4546204 8 1 76545 511580 979214 9318 210013 50508 40 152908 17969 922507 1 7 32 1 388579 1 49886 13319 1066048 4663 27883 38419 1418098 2538216 1 778734 3556791 490764 666880 22746 5666164 4 20 1806284 21142 1 527906 2 12417 182224 49536 105029 206917 2427623 294247 1405136 321480 354137 84225 50 128073 1391176 352835 26074 91159 34229 237942 1 1519676 1 2428669 272681 148689 528951 560736 1 3548197 3833513 1438699 286613 1 1290904 47145 3456135 249648 277045 1012397 271073 1 6 149276 94843 11 177134 32336 2772732 7 22 37065 1 105299 76735 44 2211334 511942 30639 522056 5162 1899842 74 1 1448039 1 88817 21 1027532 555416 1 364383 1335609 167332 283252 49564 220972 1006800 3108886 801258 265596 61651 1 2413276 252747 416606 960925 54 311956 267135 3871698 22581 8978 2 10 1966155 3123429 28 46409 1 18433963725323 1769396 114766 49071 1 1 4228762 3483932 1139490 602592 2700468 770273 3 1 1 212087 281247 27093 156094 286299 1204001 18374 1 330780 1 1 25384 906728 99334 1250819 2161201 34 1027892 1 33449 2 129787 52246 94872 1536841 23470 1 1700323 1 1 3785351 1 95315 1014155 56570 22586 66842 7 156840 48752 1 3143722 1 1168309 2 4 101423 385892 42868 2893851 7 1783109 217499 24 460497 2003214 180135 3503010 131137 2 5240 1621601 2754811 11198 1 1 1105643 1 1671021 3 139611 18268 107229 44582 2211034 1 2880152747163 231008 262504 1 257760 1 1 52992 804418 2 2 4811272 1772250 3 1796530 1918647 1 1934549 1 100550 3448657 1681262 3 604526 320865 1901079 556908 2794800 2472000 637735 123663 1 3213187 118199 2553610 1 1750628 2563806 1 1670872 1 999609 50200 654831 1 164612 2865759 1841739 9 3744159 1331395 3202501 1 7 1 1 239868 1 1 581984 112413 401 1 29656 359367 74532 27226 51752 2583 1 645443 1559731 1 114195 1 85473 229474 111353 1 1521653 1 2568733 444398 2593568 18546 1 158085 1211147 1020006 23407 42514941388799 158442 1 1660358 5 34874 1594789 1551270 386464 502417 32280 170606 1954278 72486 3406066 11 52896 345631 4010742 33307 1951926 1441325 1886066 1 3 402778 3089364 351 28028 4301364 1 431569 5 3054030 375986 404966 1 449317 1230292 1 7 763949 1 2 3197443 1537806 335317 2 1 161263 1 1959902 1664530 139136 447570 1 1 50 158825 222939 1842131 11252 1680094 1017889 71 144808 1 53679 1 41278 1226724 1 1 2 10 2 1 112451 42133 1406662 1 112593 2 2832116 1544488 3579017 3029492 2752014 6 255091 731329 540861 1 426725 440330 212602 202358 173553 4 1189793 11031 84073 2084554 3963 1473295 1 642570 1 1423688 34509 75056 163273 490193 3200250 451777 157797 4156542 2386299 2794795 2735308 1332758 1193296 1131014 1001570 414257 4415511 4 3 1 3499595 536583 16731 93839 92382 1 45890 1 17695 8 867246 18 1607123 3197052 5 40009 1 329895 3497309 2416600 2316390 11 118179 2166659 2 136426 76762 2 14 2 3632525 214889 6 3900942 270409 230143 120414 417489 16706 1563597 31418 2 73 468763 88585 428274 3537347 2 1 491461 2806485 1 7 2950804 115684 4 1 429002 85771 2480 285541 186486 1 1 2430862 6 9 4 1833423 17143 353689 2568741 408890 2929237 208679 2198380 1 2501053 1933666 180843 1 1 2569886 1 17035 3449472 71357 246257 217898 1 47601 589824 401679 362878 13178 34464 1076419 1 554417 1 21248 2136449 1068 23029 8 766649 4 302879 274751 19 1 390259 1899931 233910 1392272 184492 2 2752059 55813 1 6 64674 205205 595508 1714309 582492 4821971 63973 1708726 189200 4548446 479425 2866037 1 1 1 2139319 1 1 3 1572621 2086152 2341038 1 619612 1 78942 772466 18932 1404368 936790 2263929 230200 3009227 251065 835010 88225 642856 824193 5559048 1 36348 2338046 481447 108132 2728223 3539009 1 197164 181408 171634 2172263 2317332 1598340 1318829 1746303 7 59657 1 1415452 122924 915828 1063890 40339 430186 4 2165185 2250922 704568 85138 4417453 255 326360 33541 3 49759 72127 912537 599665 1 29169 168741 349838 996835 1548193 2 28449 803521 4 2 2 3359043 3243259 1 491574 1675000 186105 3203018 11 39127 959876 334480 873131 70262 137080 1076591 1 2155613 74804 893022 2473922 1 1 269835 5 2407308 3 55200 905207 1 1 1245609 65934 7 1372126 530582 1383562 1 1 2718341 1 3947638 4 76837 412551 11 1 1 1208080 3024670 277 46485 1 9 562183 46 2985858 3379885 67816 1896527 1 105478 2035453 3026415 1 189256 2992616 2098002 1099666 775250 5913 13 406948 166773 1 322250 41919 480047 64950 17435 2147428 2336270 3330243 352709 86029 1398723 106236 312951 1 408211 252689 847088 2 17 34088 13128 187366 2 1559482 2349010 1651122 2371088 401005 1715445 1 29483921 1464444 50228 2365851 1651636 768715 226704 23677 83501 1 252623 444628 34 3640316 3602127 45369 1 1 1978261 1 3019189 1 25411 2177552 192839 191146 293712 3840622 182598 4069200 175757 1 2250458 4 1 7 2740824 2753005 1 2836428 1 12 19 2 1788326 3302198122211 3386546 1176663 20847 28 1194294 794665 2630378 13624 722012 2273872 1549353 1 3 1735700 1668388 416 970581 258382 295427 1 121571 3193610 3764806 1 368985 20436 89411 3 16130 2 241879 1 2996216 136958 2382095 510146 1762872 1372194 4215387 346915 4423 1 904153 2004500 248495 836598 3529163 27 2547535 1424181 1885308 1 1056747 289743 176929 2299073 170473 1 1 839941 12382 51457 608526 1684239 4843522 34550 929855 2767014 2979286 1 340808 184830 131077 57298 63854 381689 201998 1715328 118687 69190 123466 1 2 69392 159797 382756 1513430 2506318 457 1
Geometric mean score: 10983.8 in 31214 seconds

Ben g ++ / MinGW ve 3 konuya geçtim.
GNU tarafından oluşturulan kod, Microsoft'un iki katından daha hızlı.
Hiç şüphe yok, korkunç STL uygulaması ile ne.

teleporters

Teleporter etkisi yüksek pozisyona bağlıdır. Şimdiye kadar bir telsizi ya her zaman iyi (boş alan olarak görülüyor) ya da her zaman kötüydü (duvar gibi göründü, böylece hiçbir kemirgen almazdı) düşündüm.

Bu çok kaba bir model.
Belirli bir ışınlayıcı, hedeften birkaç hücreye kadar bir sıçan ileriye doğru itebilir, ancak bir kez aynı ışınlayıcı sıçanı tahtadan kaldırabilir.
Böyle bir teleporter, büyük olasılıkla pasif olarak kabul edilecektir (aynı x konumuna "yürürken" zindelikten daha hızlı bir şekilde artması nedeniyle), baskın genomun bir parçası haline gelir ve neredeyse "her zaman güvenli" olarak güvenen tüm fareleri öldürür.
Sıçanların X pozisyonlarını bilmenin bir yolu olmadığından, bu hain telsizleri tespit etmek için tek çözüm, mevcut olan bağlamsal verilere, yani 5x5 renk ızgarasına dayanarak bunlara basıp basmamaya karar vermektir.

Bunu yapmak için 4 tip renk geni tanımladım:

  • tehlike kapanı dedektörü
  • boş yolda her yerde fena
  • Blok yolda herhangi bir yerde yasak
  • çevreye bağlı olarak boş veya blok olarak görülen kiriş

Buradaki düşünce, bir 8 telsizi hemen 8 komşusuna bakarak ayırt etmeye çalışmaktır. Belirli bir yerde 8 aynı komşuya sahip olma olasılığı çok düşük olduğundan, bu, her teleporter için benzersiz bir örnek tanımlamaya izin vermelidir.

Komşu 8 renk, labirentteki konumuna göre değişmeyen yerel bir imza oluşturmak için birleştirilebilir. Ne yazık ki, 8 komşu sadece 3x3 görüş alanı iç karesinde yer alan hücreler için görülebilir, bu nedenle imzalar görüş alanı sınırında yanlış olacaktır.
Bununla birlikte, bu bize yakın çevrede sürekli bir bağlamsal bilgi verecektir;

ışın genleri 2 bit değişken alana sahiptir.
Belirli bir teleporter yerel imzası için dörde ışın hücresinin geçilmez sayılacağı bir ihtimal var . Alanın her değeri bu dört olasılıktan birini seçer.
Sonuç olarak, bu 2 bit üzerindeki bir ışın geni mutasyonu, rengin olası 4 bağlamsal anlamı boyunca dönecektir.

Ayrıca, tahmin edilmesi gereken en önemli renkler hala duvarlar ve tuzaklar. Bu, teleporter saptamasına yalnızca duvarların ve tuzakların nerede olduğunu öğrendikten sonra izin vermemiz gerektiği anlamına gelir .

Bu, yerel imzaları sadece seyrek olarak güncelleyerek yapılır. Yerel bir imzanın güncellenmesi için mevcut kriter potansiyel bir teleporter olarak tanımlanan bir rengin mahremiyetinde olmalıdır.

Kodlama, renk geni başına 5 bit kullanır ve 0..7 değerini kodlamak için daha az önemli 3 bit serbest bırakmak için türlerini gruplandırır:

  • 4 tehlike
  • 4 boş
  • 4 blok
  • 4 ışın

Her ışın geni, bir blok olarak düşünülebilen 1/4 şansa ve boş olarak kabul edilmek üzere 3/4 şansa sahiptir, bu nedenle 4 ışın ortalama 1 blok ve 3 boş olarak temsil edilir.

Bu nedenle, 16 rengin rastgele yayılmasıyla temsil edilen ortalama oran:

  • 4 tehlike
  • 7 boş
  • 5 blok

Bu karışım şu ana kadarki en iyi sonuçları veriyor gibi gözüküyor, ancak düzenlemeyi tamamlamadım.

Gen değişkenliği

Kesin olan bir şey var: gen türlerini temsil etmek için seçilen kod değerleri kritik. İki değerin tersine çevrilmesi 2000 puana veya daha fazlasına mal olabilir.

İşte yine neden benim matematik dışındadır.

Tahminim, bir tipten diğerine mutasyon olasılığının dengelenmesi gerektiği veya bir Markow matrisinde olduğu gibi, kümülatif olasılıkların, gelen en yüksek geçiş olasılıklarına sahip olan alt kümedeki değerleri kısıtlama eğiliminde olduğu yönündedir.

Kurtarmaya Pathing

Yazma, ziyaret edilen hücrelerin sayısını önemli ölçüde azaltacak ve yalnızca hedefe ulaşması en muhtemel olanı test edebilecek. Bu nedenle, sadece sık sık ölü uçlardan kaçınılmaz, ancak yanlış renk kodlarının da daha önceden keşfedilmesi daha olasıdır.
Sonuç olarak, yakınsama süresi kuvvetle azalır.

Bununla birlikte, bu, genomun pistin uygun bir gösterimini üretemediği haritaları çözmeye yardımcı olmaz.

Moronlarla ne yapmalı?

Piste görsel olarak baktıktan sonra, önündeki duvarlardan başka hiçbir şey yok gibi görünse bile ilerlemeye çalışan varsayılan bir stratejinin neden geri çekilmekten daha iyi olduğunu anladım.
"duvarlar" gerçekte o kadar çok talihsiz sonuç üreten teleporcular olabilir, genomun onları asla bağlanmayacak şekilde engeller olarak eşler, ancak nadir durumlarda bu yaramaz teleporter'ın belirli bir örneğinin pozitif (veya en azından öldürücü olmayan) bir etkisi olabilir bu nedenle geri gitmek yerine onu almak, zafere giden yolu bulma şansını arttırır.

Erken yakınsama

Bana öyle geliyor ki mutasyon oranı biraz düşük (kemirgenlerim için).

Mevcut 0.01 ayarı, bir DNA mutasyon sürecinin bozulmadan hayatta kalması için% 37 şans verir. Parametrenin 0.0227 olarak değiştirilmesi bu olasılığı yaklaşık% 10'a düşürür.

Gizemli formül P1 bit mutasyonu = 1-P bütün genomu bozulmadan 1/100 , 100 genom bit uzunluğudur.

Örneğin,% 10 olasılık için, P 1 bit mutasyonu = 1 - 0,1 1/100 = 0,0277
% 5 olasılık için, P = 1 - 0,05 / 100 = 0,0295 Formülü
ters çevirerek , 0,01'in % 37 olma şansını verdiğini tespit ettik. mutasyon ile değişmedi.

% 10 olasılık ile aynı testi (sabit bir rastgele tohum dizisi kullanarak) tekrar yaptım.
Birçok haritada, önceki başarısızlıklar (sınırlı) başarılara dönüştü. Öte yandan, muazzam nüfus patlaması daha azdı (bu, hesaplamayı çok hızlandırmanın ilginç yan etkisine sahipti).
Çok yüksek puanlar (bir milyon +) daha az yaygın olsa da, daha başarılı çalışmaların sayısı telafi etmek için yeterliydi.
Sonunda, ortalama 1400'den 2000'e yükseldi.

Aksine, P'yi% 5'e ayarlamak, yaklaşık olarak 600'lük bir ortalama üretti
. Mutasyon oranının o kadar yüksek olduğunu varsayalım, kazanma sıçanlarının genomunun daha az verimli varyantlara çok sık geliştiğini düşünüyorum.

Bu nasıl çalışır?

Teleporter dedektörleri eklendiğinde, başarısız oyunların sayısı (<<10 puan) önemli ölçüde düştü.
2000 çalışma denemesinde, yalnızca 1 / 3'ünde başarısızlık oldu.
Geometrik ortalama yalnızca 2900'den 3300'e yükseldi, ancak bu sayı iyileşmeyi yansıtmıyor.

Boş renkler sıklıkla kiriş ve tehlike olarak tahmin edilir (genellikle 2 ila 5). Genom, bu renkleri farelerin başını belaya sokacak yolları engellemek için kullanır.

Genom, tuzakları tahmin etmede oldukça iyidir (yani fareler hedefe ulaşabilince, gerçek tuzak dedektörlerini temsil eden renklerin zamanın yaklaşık% 90'ı olduğu tahmin edilmektedir).
Ayrıca, nadiren olsa da, ışınlayıcılar için yeni ışın kodlarını kullanır (muhtemelen "haince" ışınlayıcıların tuzaklardan daha az yaygın olması ve diğer ışın / tehlike renkleri bu hainlerin son örneklerine giden yolu tıkamak için evrimleştiği için).

Kazanan bir genomun 5000 tur veya daha fazla bir süre sonra ortaya çıktığı oyunların sayısına bakılırsa, bu yeni türün artan mutasyon oranından büyük ölçüde fayda sağlayacağını tahmin ediyorum.


Eşit sayıda tuzak, boş, duvar ve telet olduğundan, oranları doğru bir şekilde saklamak için sadece 3 bit gerekir (tuzakları == duvarlar düşünseniz bile). Ayrıca, anti-duvar patlamada kullanılmamış tuzak ofset bitlerinin kullanılması fikrini düşündünüz / atdınız mı? Buradaki amaç ebeveynlerden miras almamak olduğundan, aslında duvar karşıtlığı konusundaki bütün bitleri kullanabilirsiniz . Onların eşsiz olmaları için bir sebep yok sanmıyorum.
Mooing Duck

1
@MooingDuck Ofset bitlerini yeniden kullanma fikrinizi test ettim, ancak başarısız oldu. Korktuğum gibi, bir bilgiyi iki farklı amaç için tekrar kullanmak işe yaramıyor. Örneğin, verilen bir rengin ofset bitlerinin belirli bir yoldaki uygun dikey yönü seçmesi için bir genomun gerekli olduğunu varsayalım, bu renk aynı veriye bağlı yolu yok etmeden artık anlamlı bir tuzağı temsil edemez. 6 bit kullanmaya da çalıştım, ancak korktuğum gibi geriye kalan 4 duvarcı çok yetersizdi.

1
Bilmek güzel, ama orada iki fikir önerdim, biri tüm bitleri kullanmak (bazılarını yeniden kullanmak), diğeri ise kullanılmayan tuzak ofset bitlerini duvarlar / boş için kullanmaktı. İkisini de denedin mi? (Denemek istemiyorsanız tamamen anlıyorum, istemiyorsanız denemeniz gerekmiyor)
Mooing Duck

1
İkisini de denedim ve ikisi de başarısız oldu. Tuzak ofsetleri, bir gen onları kullanmadığında bile önemlidir, çünkü bu gen yine de bir tuzak rengine dönüşebilir, bu durumda tuzak ofseti, hangi bağlam bitlerine en karlı olursa olsun mutasyona uğrayacak ve ofset olarak anlamını yitirecektir. . Şimdi karlı ofset değerine geri dönecek ve ona bağlamsal göstergeler olarak bağlı sıçanların yollarını yok edecektir. Grafik aracımla böyle bir salınım vakasını gördüm, ancak bu sorunun net bir örneğini göstermek kolay değil.

16

ColorScorePlayer, ön puan ≈ 22

Bu, GIF'te iş başında gördüğünüz bottur.

Bu geliştirme aşaması boyunca test botumuzdu. Genomu, 16 rengin her biri için bir kalite puanı depolamak için kullanır. Sonra onu en iyi skorla renge hareket ettiren ileri hareketini yapar (ve asla üzerine ilerlemez -1). Bir bağlanma durumunda, bağlayan hücreler arasında rastgele bir hareket toplanır.

Bu oynatıcıyı tüm denetleyici dillerine taşıdık, bu yüzden nasıl kullanılacağına örnek olarak davranıyor:

piton

class ColorScorePlayer(Player):
    def __init__(self):
        Player.__init__(self)
        self.coords = [Coordinate( 1, 0),
                       Coordinate( 1,-1),
                       Coordinate( 1, 1)]
        self.n_moves = len(self.coords)

    def turn(self):
        max_score = max([self.bit_chunk(6*self.vision_at(c.x, c.y), 6) for c in self.coords if self.vision_at(c.x, c.y)>=0])
        restricted_coords = [c for c in self.coords if self.vision_at(c.x, c.y)>=0 and self.bit_chunk(6*self.vision_at(c.x,c.y), 6) == max_score]

        return random.choice(restricted_coords)

Yakut

class ColorScorePlayer < Player
    def initialize(rng)
        super(rng)
        @coords = [Vector2D.new( 1,-1),
                   Vector2D.new( 1, 0),
                   Vector2D.new( 1, 1)]
    end

    def vision_at(vec2d)
        @vision[vec2d.x+2][vec2d.y+2]
    end

    def turn
        max_score = @coords.map { |c|
            color = vision_at(c)
            color < 0 ? -1 : bit_chunk(6*color, 6)
        }.max

        restricted_coords = @coords.select { |c|
            color = vision_at(c)
            color >= 0 && bit_chunk(6*color, 6) == max_score
        }

        restricted_coords.sample(random: @rng)
    end
end

C ++

coord_t colorScorePlayer(dna_t d, view_t v) {
    const int chunklen = DNA_BITS / N_COLORS;
    int ymax[3], nmax, smax = -1;
    for(int y = -1; y <= 1; y++) {
        if(v(1, y) == OUT_OF_BOUNDS) continue;
        int score = dnarange(d, v(1, y)*chunklen, chunklen);
        if(score > smax) {
            smax = score;
            nmax = 0;
        }
        if(score == smax) ymax[nmax++] = y;
    }
    return {1, ymax[v.rng.rint(nmax)]};
}

C #

public static void ColorScorePlayer(GameLogic.IView v, GameLogic.IGenome g, Random rnd, out int ox, out int oy)
{
    ox = 0;
    oy = 0;

    var max_score = cspcoords.Where(c => v[c.x, c.y] > -1).Select(c => g.cutOutInt(6 * v[c.x, c.y], 6)).Max();
    var restrictedCoords = cspcoords.Where(c => v[c.x, c.y] > -1 && g.cutOutInt(6 * v[c.x, c.y], 6) == max_score).ToArray();

    Coord res = restrictedCoords[rnd.Next(restrictedCoords.Length)];

    ox = res.x;
    oy = res.y; 
}

Java

package game.players;

import java.awt.*;
import java.util.Map;

public class ColorScorePlayer extends Player{
    private static final Point[] possibleMoves = {new Point(1, 0), new Point(1, -1), new Point(1, 1)};

    @Override
    public Point takeTurn(String genome, Map<Point, Integer> vision) {
        int chunkLength = genome.length()/16;
        int maxSum = -1;
        Point maxSumMove = possibleMoves[0];
        for (Point move: possibleMoves){
            if (vision.get(move) == -1){
                continue;
            }
            int initialPoint = chunkLength*vision.get(move);
            int sum = 0;
            for (int i = initialPoint; i < initialPoint + chunkLength; i++){
                sum = (sum<<1)+Integer.parseInt(genome.charAt(i)+"");
            }
            if (sum > maxSum){
                maxSum = sum;
                maxSumMove = move;
            }
        }
        return maxSumMove;
    }
}

Oyuncu oldukça tutarsızca gol atar. İşte 50 rastgele koşu:

Scores: 1 1 1132581 3 43542 1 15 67 57 1 11 8 623162 1 1 1 134347 93198 6 1 2 1 1 245 3 1 1 27 1 31495 65897 9 5 1 2 20 2 117715 1 1 1 20 64616 5 38 1 2 1 2 12

12

ColorFarSeeker, C ++ ≈ 74.7

Eğer denerseniz, bu zorluk gerçekten oldukça eğlenceli ve basittir.

Uzun açıklama ile ertelenme.
GitHub'ı ziyaret edin ve her şeyi kontrol edin… her şey çok daha net olacak! :)

C ++ simülatörü hızı için şiddetle tavsiye edilir. Python programımı C ++ 'a çevirmeyi bitirdikten sonra bile, python simülasyonu hala durmadı.

Bu ColorScorePlayer'ın geliştirilmiş bir çeşididir. 5x5 görüşünden en iyi şekilde yararlanmak için, ağırlıklı bir işlev kullanarak 2 adım hareket ettiğini düşünür. Önünde 1 adım ilerlerse, hayatta kalma üzerinde daha hızlı bir etkiye sahip oldukları için daha fazla ağırlık verilir. 2 adım önde ilerletmek için daha düşük ağırlık verilir.

İlerlemeye çalışır, ancak güvenli bir hareket görmezse ... o zaman yana doğru çalışır ... ve diğerleri başarısız olursa, rasgele geriye doğru hareket eder.

coord_t colorFarSeeker(dna_t d, view_t v) {
#define s(w,x,y) (v(x,y)>-1?((b+dnarange(d,l+m+n*v(x,y),n))*w):0)
#define max2(a,b) (((a)>(b))?(a):(b))
#define max3(a,b,c) (max2(a,max2(b,c)))
#define push(vec,maxScore,score,x,y) if(score==maxScore&&v(x,y)>-1)vec.push_back({x,y});
#define tryReturn() if(vec.size()){return vec[v.rng.rint((int)vec.size())];}vec.clear();

    // Some constants to tweak
    int k = 4;
    int l = 3;
    int m = dnarange(d, 0, l);
    int n = 4;
    int b = dnarange(d, l, k) + 10;

    std::vector<coord_t> vec;

    // Looks forward for good moves...
    int upRightScore = s(1,0,-2) + s(1,1,-2) + s(1,2,-2) + s(5,1,-1);
    int forwardScore = s(1,2,-1) + s(1,2,0) + s(1,2,1) + s(5,1,0);
    int downRightScore = s(1,0,2) + s(1,1,2) + s(1,2,2) + s(5,1,1);
    int maxForwardScore = max3(upRightScore,forwardScore,downRightScore);
    push(vec,maxForwardScore,upRightScore,1,-1);
    push(vec,maxForwardScore,forwardScore,1,0);
    push(vec,maxForwardScore,downRightScore,1,1);
    tryReturn();

    // Looks sideways for good moves...
    int upScore = s(1,-1,-2) + s(1,0,-2) + s(1,1,-2) + s(5,0,-1);
    int downScore = s(1,-1,2) + s(1,0,2) + s(1,1,2) + s(5,0,1);
    int maxSideScore = max2(upScore,downScore);
    push(vec,maxSideScore,upScore,0,-1);
    push(vec,maxSideScore,downScore,0,1);
    tryReturn();

    // If all else fails, move backwards randomly.
    // I have tried considering the scores of backmoves,
    // but it seems worse than just randomly moving backwards. 
    vec.push_back({-1,-1});
    vec.push_back({-1,0});
    vec.push_back({-1,1});
    return vec[v.rng.rint((int)vec.size())];

}

Puan:

Konsolun birbiri ardına 1 yaydığını görünce ... ... biraz iç karartıcı olabilir. Yaşam için gerekli olan ama ilerlemiş sıçan medeniyetlerinin belirtileri olmayan bir gezegen gibi ...
O zaman ara sıra ani. :)

Hmm ... görünüşe göre 300'den fazla bir geometrik elde ettiğim ilk parti koşum için şanslıydım. Skorlar gerçekten biraz dalgalanıyor. Ama yine de, simülatörün daha fazla çalışmasıyla, muhtemelen ≈ 74'e yakındır.

Koşulardan elde ettiğim puanlar: 6 6 53 1 5 101223 89684 17 2 303418 4 85730 24752 1 1 1 3482515 39752 1 59259 47530 13 554321 1 563794 1 1770329 1 57376 1 123870 4 1 1 79092 69931 594057 1 69664 59 1 6807 597 ... 2 1 51704 1 254006 4 24749 1 117987 49591 220151 26 4292194 23 57616 72 67 1 4 308039 1 1 103 89258 1 286032 1 5 3 1 5 114851 46 143712 5 15 9 80 7425 1 1 7 1 108379 70122 97238 1 1 5 2 23 104794 1 10476 59245 1 204 1 1 12 1 29641 1 314894 18785 13 1 3 1 1 1 2 526001 1 1 1 27559 29285 3 3 128708 70386 30 2 2 1 208531 331 1 2 1 61 114993 1 15 51997 1 2 1 146191 1 31 4 3 1 161422 207 1 64 1 1 1 68594 145434 87763 150187 169 185518 1 1 1 1 24208 2570 1 1 537 1 1 462284 1 2 55 1 1 1 214365 1 40147 2 213952 1 29 3 1 2144435 5 4502444 72111 1 1 1 1 1 774547


1
1000 oyun, iyi bir iş ile geometrik bir ortalama 74.7 aldım.
Ocak'ta 15:15

8

Piskopos - Python, ön puan 1.901

Piskopos her zaman çapraz olarak hareket eder, böylece tahtanın yarısı pist boyunca belirli bir trekte erişilemez, ancak bu kodlamak için daha az potansiyel hareket anlamına gelir, böylece genomun her bir biti bir hareketi temsil eder (Piskopos asla geri çekilmez). Hangi bitin atılacağına, numunenin önündeki (sağda) 3x3 kareler bloğuna dayanarak karar verilir. Belirli bir durum için en iyi hamle, sadece bir tek uzak mutasyon.

Bu bot ilk başta hızlı bir şekilde öğrenir, ancak daha sonra genellikle aşağıdaki iki problemden birinin meydana geldiği durumlarda bitişe ulaşmadan önce tavana vurur:

  • Tahtanın iki veya daha fazla kısmı aynı bit ile eşleşir ancak farklı hamleler gerektirir.
  • Bazı kartlar, yalnızca çapraz hareketler kullanılarak geçirilemez.

kod

class BishopPlayer(Player):
    def __init__(self):
        Player.__init__(self)
        self.coords = [Coordinate(1,-1),
                       Coordinate(1, 1),
                       ]
        self.inputs = [(x,y) for x in (0,1,2) for y in (-1,0,1)]

    def turn(self):
        # Move away from out of bounds areas
        if self.vision_at(0,-1) == -1:
            return self.coords[1]
        if self.vision_at(0,1) == -1:
            return self.coords[0]

        # Move right, and either up or down based on one bit of the genome
        bit_to_use = sum(self.vision_at(self.inputs[i][0],
                                        self.inputs[i][1]
                                        ) * (16 ** i) for i in range(9)
                         ) % 100
        return self.coords[self.bit_at(bit_to_use)]

Bu sınırlamalara rağmen, nadir durumlarda Piskopos iyi yapıyor, bireysel numuneler her birinin birkaç turunu tamamlıyor. Belirli bir turda bir numunenin tahtanın sadece yarısına hareket edebileceğini düşünmüştüm (sadece siyah karelere veya sadece satranç tahtasındaki beyaz karelere eşdeğerdir). Bununla birlikte, Martin Büttner'ın belirttiği gibi, bir telsizci bir numuneyi siyah bir kareden beyaz bir kareye ya da tam tersine taşıyabilir, böylece çoğu panoda kısıtlanmayacaktır.

(İki çift eşlenmiş teleporter türü vardır ve her birinin, bir örneği siyah ve beyaz karelerin diğer yarısına taşıyan bir ofset olma olasılığı 0,5'tir. Yani, bir örneği yalnızca bir tane ile sınırlayan teleporörleri olan bir panelin olasılığı tur başına tahtanın yarısı sadece 0,25

Skorlar, arada sırada gerçekleşen zaferlerin, bitirme süresinin kısalmasıyla uzun süren serpiştirmelerle dolduğunu göstermektedir:

Sonuçlar: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 11 1 2 1 1 1 1 1 6 1 8 1 10 15 1 1 12.544 1 2 1 1 1 1 3 7554 1 1 1 1 1


8

Run-bonus oyuncusu: Geometrik ortalama 50,35 (5000 oyun testi)

Bu bot, renk skoru oynatıcısı gibi 6 bitlik bir DNA bölümüne dayanarak, ancak farklı bir sayı sistemiyle, kendi renklerine göre kareleri puanlıyor. Bu bot, bitlerden birinin puan değerini 32 ile değiştirdiğini, diğerinin ise sadece 1 yaptığını belirten keyfi olduğunu düşünerek motive edildi. N (n + 1) / 2 değerini koşuya atar. n ardışık 1 bit. Ek olarak, takılmayı önlemek amacıyla rastgele bir mekanizma ekler. 30'luk bir şansla rastgele ileri hamle yapacak.

Karşılaştırma için, birkaç 1000 oyun testinde renk skoru oyuncusu 30 - 35 puan aldı. İlginçtir ki, renk skoru oyuncunun maksimum oyunu skoru 3-5 milyon aralığında iken run-bonus 'maksimum 200 bin idi. Sıfır olmayan bir puan daha tutarlı alarak Run-bonus logaritmik ortalama puanlama sisteminden yararlanır.

5000 oyun çalıştırmak, C ++ denetleyicisindeki 6 iş parçacığıyla yaklaşık 20 dakika sürdü.

coord_t runbonus(dna_t d, view_t v) {
    int ymax[3], nmax, smax = -1;
    if(!v.rng.rint(30)) {
        int y;
        while(!~v(1, y = v.rng.rint(-1, 1)));
        return {1, y};
    }
    for(int y = -1; y <= 1; y++) {
        if(v(1, y) == OUT_OF_BOUNDS) continue;
        int score = 0;
        int streak = 0;
        for(int i = 0; i < 6; i++) {
            if(d[6*v(1,y) + i])
                score += ++streak;
            else
                streak = 0;
        }
        if(score > smax) {
            smax = score;
            nmax = 0;
        }
        if(score == smax) ymax[nmax++] = y;
    }
    return {1, ymax[v.rng.rint(nmax)]};
}

Sadece meraktan, 5000 parça testi ne kadar sürdü? Farelerimin 1000 parçayı tamamlamak için bir saatten daha fazla zamana ihtiyacı var, bu yüzden bilgisayarın tüm gece çalışmasını sağlamak zorundayım.

@kuroineko Sorunuza cevap zaten benim cevabımdaydı.
feersum,

Ayy üzgünüm. Donanımı hız farkında hangi parçanın oynadığını görmek için kodumu bilgisayarımda deneyeceğim. Ve belki de MSVC yerine gcc kullanmayı deneyin. Birkaç hesaplama ağırlıklı kod parçasında MSVC'ye göre% 30 performans artışı fark ettim.

Kodunuz i3-2100@3.1GHz'de 4 parçalı 1000 parça için 20 dakikadan biraz fazla sürdü. Skor yaklaşık 56 idi . Bilgisayarımın sizinkinden 5 kat daha yavaş olduğu ve kodumun belirli bir makinede yaklaşık 6 kat daha yavaş olduğu anlamına geliyor (ancak daha iyi bir puana sahip olmak daha uzun bir hesaplama süresi anlamına gelir). Yeni bir bilgisayar almak için fazla kırıldığımdan beri, biraz optimizasyon zamanı geldi ...

8

StarPlayer | C ++ | Puan: 162 (500 oyun çalıştırmaya göre)

Bu oyuncu, en iyi yolu bulmak için A * kullanmaya çalışır. ColorScorePlayer ile aynı şekilde ağırlıklar atar ve görünümün sağ köşesine doğru yol bulmaya çalışır. Uygulama şimdiye kadar yaptığım en güzel şey değil, ama en azından çok yavaş değil.

#include <utility>

#define IDX(a,b) a[VIEW_DIST + b.x][VIEW_DIST + b.y]

std::pair<coord_t,int> planAhead(int weights[N_COLORS], view_t &v, coord_t target) {
    bool open[VIEW_DIST*2+1][VIEW_DIST*2+1] = {false};
    bool closed[VIEW_DIST*2+1][VIEW_DIST*2+1] = {false};
    int f_score[VIEW_DIST*2+1][VIEW_DIST*2+1] = {0};
    int g_score[VIEW_DIST*2+1][VIEW_DIST*2+1] = {0};
    coord_t came_from[VIEW_DIST*2+1][VIEW_DIST*2+1] = {{0,0}};
    open[VIEW_DIST][VIEW_DIST] = true;
    g_score[VIEW_DIST][VIEW_DIST] = v.rng.rint(5);
    f_score[VIEW_DIST][VIEW_DIST] = (abs(target.x) + abs(target.y)) * 10;
    for (;;) {
        coord_t current{VIEW_DIST+1,0};
        for (int x = 0; x < (VIEW_DIST*2+1); x++)
            for (int y = 0; y < (VIEW_DIST*2+1); y++)
                if (open[x][y] && (current.x > VIEW_DIST || f_score[x][y] < IDX(f_score,current)))
                    current = {x - VIEW_DIST, y - VIEW_DIST};
        if (current.x > VIEW_DIST)
            return {{1,0}, 1000000};
        if (current.x == target.x && current.y == target.y)
            break;
        IDX(open,current) = false;
        IDX(closed,current) = true;
        for (int dx = -1; dx <= 1; dx++) for (int dy = -1; dy <= 1; dy++) {
            if (dx == 0 && dy == 0)
                continue;
            coord_t tentative{current.x + dx, current.y + dy};
            if (abs(tentative.x) > VIEW_DIST || abs(tentative.y) > VIEW_DIST)
                continue;
            if (IDX(closed,tentative))
                continue;
            auto color = v(tentative.x, tentative.y);
            if (color == OUT_OF_BOUNDS)
                continue;
            auto tentative_g = IDX(g_score,current) + weights[color];
            if (!IDX(open,tentative) || tentative_g < IDX(g_score,tentative)) {
                IDX(came_from,tentative) = current;
                auto distance = abs(tentative.x - target.x) + abs(tentative.y - target.y);
                IDX(f_score,tentative) = tentative_g + distance * 10;
                IDX(g_score,tentative) = tentative_g;
                IDX(open,tentative) = true;
            }
        }
    }
    auto prev = target, current = target;
    while (current.x != 0 || current.y != 0)
        prev = current, current = IDX(came_from,current);
    return {prev, IDX(g_score,target)};
}

coord_t starPlayer(dna_t d, view_t v) {
    const int chunklen = DNA_BITS / N_COLORS;
    int weights[N_COLORS];
    for (int i = 0; i < N_COLORS; i++)
        weights[i] = dnarange(d, i*chunklen, chunklen);
    std::pair<coord_t,int> choice{{1,0}, 1000000};
    for (int y = -VIEW_DIST; y <= VIEW_DIST; y++) {
        auto plan = planAhead(weights, v, {VIEW_DIST, y});
        if (plan.second < choice.second)
            choice = plan;
    }
    return choice.first;
}

Örnek puanlar:

4 92078 1 10 1 1 3 2 2862314 5 24925 1 3 2 126502 1 24 1097182 39 1 1 1 47728 227625 137944 15 1 30061 1 1 1 3171790 19646 10 345866 1 1 1 829756 425 6699 22 8 1 1 6 6 104889 125608 1


1
1000 maçta 133.2 puan aldım, hoş.
feersum

7

WallGuesser - 1000 oyun testinde 113.266 sayı kazandı

Kodlama

Gerçekten basit bir 6 bit / renk kodlaması yaptım. Rengin kodunu çözmek için [n]

  • Genomdaki her bir bitin 96'ya kadarını topla
  • Toplam puan> = 4 ise, bu karenin engellenmiş olduğunu söyleyin.
  • Eğer toplam puan <= 4 ise, final puanı toplam puanın 2 ^ 'sidir.

Bitleri genom boyunca bir renk için yayarak, her iki ebeveynden bitlerin her renk için kullanılma şansını arttırıyorum.

hareket

Sağ kenarlı karelerden herhangi birine giden en düşük maliyetli yolu aramak için A * tabanlı bir arama yapıyorum (çok etkili olmadığından eminim). Bir renk "engellendi" olarak eşlenirse, arama tarafından hiçbir zaman girilmez. Eğer arama bir yol bulamazsa, bu farenin çoğaltmaya uygun olmadığını varsayar ve sola hareket ettirerek sona erdirmeye çalışır.

Uygun olmayan sıçanların sayısının azaltılması

Genomum hangi karelerin duvar ya da geri olduğu hakkında etkili bir tahminde bulunabildiğinden, hiçbir tahminde bulunmayan fareler (eşleştirilecek haritanın renkleri yok) çok uygun değildir. Hiçbir renk engellenmiş olarak işaretlenmezse bu sıçanları denemek ve kaldırmak için HER renk engellenmiş olarak işaretlenir ve sıçan her zaman bir tane sola hareket eder.

YAPMAK

Şu anda davranışta rastlantısallık yoktur, bu nedenle farelerin sıkışması kolaydır.

#include "./gamelogic.cpp"

#include <algorithm>
#include <set>
#include <map>
#include <climits>

bool operator< (const coord_t &a, const coord_t &b){
    if(a.x != b.x){ return a.x < b.x; }
    else if (a.y != b.y){ return a.y < b.y; }
    else{ return false; }
}

bool operator== (const coord_t &a, const coord_t &b){
    return (a.x == b.x) && (a.y == b.y);
}

int coordDistance(const coord_t &a, const coord_t &b){
    int xDif = abs(a.x - b.x);
    int yDif = abs(a.y - b.y);
    return xDif > yDif ? xDif : yDif;
}

int coordMinSetDistance(const coord_t &a, const std::set<coord_t> &ends){
    int min = INT_MAX;
    for (auto i : ends){
        int cur = coordDistance(a, i);
        if (cur < min){
            min = cur;
        }
    }
    return min;
}


class ColorMap{
public:
    view_t *v;
    int colors[16] = {};
    const int Blocked = -1;

    ColorMap(dna_t &d, view_t *v){
        this->v = v;

        //Decode the genome
        for (int i = 0; i <= (16*6); i++){
            if (d.at(i) == true){
                colors[i % 16]++;
            }
        }

        //Encode the result
        bool guessedWalls = false;
        for (int i = 0; i < 16; i++){
            if (colors[i] >= 4){
                colors[i] = Blocked;
                guessedWalls = true;
            }
            else{
                colors[i] = pow(2, colors[i]);
            }
        }

        if (guessedWalls == false){
            for (auto i : colors){
                i = Blocked;
            }
        }
    }

    int operator() (coord_t pos){
        if (abs(pos.x) > VIEW_DIST || abs(pos.y) > VIEW_DIST){
            return Blocked;
        }

        int value = (*v)(pos.x, pos.y);
        if (value == OUT_OF_BOUNDS){
            return Blocked;
        }
        else{
            return colors[value];
        }
    }

    void print(){
        int lower = -1 * VIEW_DIST;
        int upper = VIEW_DIST;
        for (int y = lower; y <= upper; y++){
            for (int x = lower; x <= upper; x++){
                std::cout << std::setw(3) << this->operator()({ x, y });
            }
            std::cout << std::endl;
        }
    }
};

class node{
public:
    coord_t pos;
    coord_t cameFrom;
    int gScore;
    int minDistance;

    node(coord_t pos, coord_t cameFrom, int gScore, int minDistance){
        this->pos = pos;
        this->cameFrom = cameFrom;
        this->gScore = gScore;
        this->minDistance = minDistance;
    }

    int fScore() const{ return gScore + minDistance; };

    bool operator< (const node &rhs) const{ return fScore() < rhs.fScore(); }
};

class EditablePriorityQueue{
private:
    //This is reversed so smallest are on top
    struct lesser{
        bool operator()(node *a, node *b) const{
            return (*b) < (*a);
        }
    };

    std::vector<node*> queue; // Use heap functions to maintain the priority queue ourself
    std::map<coord_t, node*> members;

public:
    EditablePriorityQueue(){};

    ~EditablePriorityQueue(){
        for (auto &m : members){
            delete m.second;
        }
    }

    bool empty(){ return members.empty(); }

    node *top(){
        auto top = this->queue.front();
        std::pop_heap(queue.begin(), queue.end(), lesser());
        queue.pop_back();
        members.erase(top->pos);
        return top;
    }

    void set(coord_t target, coord_t cameFrom, int gScore, int minDistance){
        auto targetLocation = members.find(target);

        //If the target isn't a member add it
        if (targetLocation == members.end()){
            auto *newNode = new node(target, cameFrom, gScore, minDistance);
            queue.push_back(newNode);
            std::push_heap(queue.begin(), queue.end(), lesser());
            members[target] = newNode;
        }
        //The target must be updated
        else{
            auto currentNode = targetLocation->second;
            if (currentNode->gScore > gScore){
                currentNode->gScore = gScore;
                currentNode->cameFrom = cameFrom;
                std::make_heap(queue.begin(), queue.end()); //More efficient way to do this?
            }
        }
    }
};

std::pair<coord_t, int> pathCost(ColorMap &m, coord_t start, const std::set<coord_t> &ends){
    EditablePriorityQueue openSet;
    std::set<coord_t> closedSet;
    std::map<coord_t, coord_t> cameFrom;

    openSet.set(start, start, 0, coordMinSetDistance(start, ends));
    while (openSet.empty() == false){
        auto current = openSet.top();
        closedSet.insert(current->pos);
        cameFrom[current->pos] = current->cameFrom;

        //Check if we're done
        if (ends.count(current->pos) != 0){
            //Recover the path
            coord_t path = current->pos;
            int finalScore = current->gScore;
            delete current;
            while (!(cameFrom[path] == start)){
                path = cameFrom[path];
            }

            return{ path, finalScore };
        }               

        //Examine current's neighbours
        for (int x = -1; x <= 1; x++) for (int y = -1; y <= 1; y++){
            coord_t neighbour = { current->pos.x + x, current->pos.y + y };

            if (x == 0 && y == 0){ continue; }

            closedSet.count(neighbour);
            if (closedSet.count(neighbour) != 0){ continue; }

            int neighbourScore = m(neighbour);
            if (neighbourScore == m.Blocked){ continue; }

            int tentativeScore = current->gScore + neighbourScore;
            openSet.set(neighbour, current->pos, tentativeScore, coordMinSetDistance(neighbour, ends));

        }
        delete current;
    }

    return{ { -1, 0 }, INT_MAX }; //Try to end it
}

coord_t myPlayer(dna_t d, view_t v) {
    auto ourMap = ColorMap(d, &v);

    std::set<coord_t> edges;
    for (coord_t edge = { VIEW_DIST, -1 * VIEW_DIST }; edge.y <= VIEW_DIST; edge.y++){
        edges.insert(edge);
    }

    //Move to the neighbor closest to a square on the right
    auto result = pathCost(ourMap, { 0, 0 }, edges);
    auto minMove = result.first;

    return minMove;
}

int main() {
    slog << "Geometric mean score: " << runsimulation(myPlayer) << std::endl;
}

Hm, bu benim için derlenmiyor g++ -std=c++11 .\wallguesser.cpp -O2 -o .\wallguesser.exe. Çok fazla hata alıyorum ama ilki.\wallguesser.cpp:47:19: error: 'dna_t' has no member named 'at' if (d.at(i) == true){
Martin Ender

Sorun değil, sadece değişen atiçin []bunu düzeltir.
feersum

7

FITTEST - Geometrik ortalama puan: ~ 922 (2K çalışır)

Benim yaklaşımım şudur:

  1. Türleri neyin öldürdüğünü öğrenin ve istenen davranışı tanımlayın (işlevsel)
  2. İstenen davranışın kodda uygulanması (teknik)
  3. Ona öncelik ver . İstenilen diğer davranışlardan daha önemli veya daha az önemli midir?
  4. Çözümlerin parametrelerini ayarlayarak Geometrik ortalama puanını optimize edin.

Aynı 50 çekirdekli 2000'den fazla parametre setini test ettim. En umut verici setler seçildi ve 250 özdeş tohum kullanılarak skorlandı ve en yüksek dereceye sahip olanlar bir sonraki test turuna girdi. Bu yüzden mbomb007 kullanıcısı tarafından önerildiği gibi bu problem için en uygun genetik algoritmayı bulmak için genetik bir algoritma yaratmayı başardım .

İstenilen davranış:

  1. Türler hangi renklerin güvenli , hangilerinin kötü olduğunu öğrenmelidir .
  2. Türler esas olarak, öndeki 3 hücreye dayanarak nereye taşınacaklarına odaklanmalıdır, ancak iyi hamleler mevcut değilse, dikey veya geriye doğru hamleler dikkate alınmalıdır.
  3. Türler ayrıca etrafındaki 8 hücrenin ötesinde olana bakmalı ve bunu karar vermede bilgide kullanmalıdır.
  4. Türler tuzakları tanımlamayı öğrenmelidir .
  5. Bazı türler yanlış bir şekilde duvarların iyi olduğunu varsayıyor ve her zaman onlara taşınmaya çalışıyor ve bu nedenle duvarların önünde sıkışıp kalıyorlar. Eğer o anda en yüksek puana sahip türlerse , duvar hakkındaki yanlış varsayımla DNA'ları birçok kez yenidoğanlara kopyalanır . Bir süre sonra, bütün türler duvarların önünde kalır ve hiçbiri puan kazanma hedefine ulaşmaz. Moronlar nasıl durdurulur?

Veri saklama yöntemleri:

Türlerin bir şeyler öğrenmesini, çevresine uyum sağlamasını, en uygun hale gelmesini istiyoruz. Kaçınılmaz olarak, bu sadece, öğrenmenin bir şekilde saklanabilmesi durumunda işe yarar. Öğrenme, 100 DNA bitinde 'saklanır'. Bu garip bir saklama şeklidir, çünkü DNA'mızın değerini değiştiremeyiz . Bu nedenle , DNA'nın zaten kötü ve iyi hamlelerin bilgisini sakladığını varsayıyoruz . Belli bir tür için doğru bilgi DNA'sında depolanırsa hızlı ileri gider ve DNA'sı ile birçok yeni tür üretir.

Geometrik ortalama puanının bilgilerin nasıl saklandığına duyarlı olduğunu öğrendim. 100 bit DNA'nın ilk 4 bitini okuduğumuzu ve bunu bir tamsayı değişkeninde saklamak istediğimizi varsayalım. Bunu birkaç yolla yapabiliriz:

  1. ondalık veri depolama: 'built-in' dnarangeişlevini kullanarak, örnek: 4bits 1011`1x2 ^ 3 + 0x2 ^ 2 + 1x2 ^ 1 + 1x2 ^ 0 = 15 olur. Olası değerler (4 bit için): [0, 1 , 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
  2. çizgiler, veri depolama: kullanılarak dnaStreakRange(aşağıda tanımlanan) fonksiyonu, örneğin: 4bit 1011 olacaktır 1x1 + 0x1 + 1x1+ 1x2 = 4. Olası değerler (4 bit için): [0, 1, 2, 3, 6, 10]
int dnaStreakRange(dna_t &d, int start, int chunklen) {
    int score = 0;
    int streak = 0;
    for(int i = 0; i < chunklen; i++) {
        if(d[start + i])
            score += ++streak;
        else
            streak = 0;
    };  
    return score;
}
  1. Bitsum veri depolama: kullanılarak dnaCountRange(aşağıda tanımlanan) fonksiyonu, örneğin: 4bit 1011 olacaktır 1x1 + 0x1 + 1x1 + 1x1 = 3. Olası değerler (4 bit için): [0, 1, 2, 3, 4]
int dnaCountRange(dna_t &d, int start, int chunklen) {
    int score = 0;
    for(int i = 0; i < chunklen; i++) {
        if(d[start + i])
            score ++;
    };  
    return score;
}

Depolama yöntemleri arasındaki fark:

  • Ondalık depolama yöntemi, DNA'daki tek bir bit değişimine karşı savunmasızdır . Bit değeri 1011'den 0011'e değiştiğinde, değeri 3'ten 2'ye değişir ki bu küçük bir değişikliktir.
  • Ondalık depolama yöntemi homojendir . Olası değerlerin her biri gerçekleşmek üzere aynı değişikliğe sahiptir. 4 bitlik bir bellek belleği bloğundan 15 değerini okuma şansı 1/16 =% 6'dır. Çizgi depolama yöntemi homojen değildir . 4 bitlik bir çizgi değerinin 6'ya (15-3) / 16 = 81% (0111,1110,111 hariç tüm 16 kombinasyon) eşit veya daha az olması ihtimali. Dağılım şeklini gösteren bir görselin altında. Mavi okta görebileceğiniz gibi 4 bitlik bir çizginin 6'ya eşit veya daha az olması şansı% 81'dir: 4,5 ve 6 bit uzunluğundaki ikili sayılar için ondalık, çizgi ve bit depolanma türlerinin dağılımının görselleştirilmesi

Çözümlere öncelik verin.

ColorScorePlayer, aynı puanlara sahip iki ileri hamle belirlediğinde, keyfi bir seçim yapılır. IMHO, asla rasgele fonksiyon v.rng.rint()fonksiyonunu kullanmamalısınız . Bunun yerine, ikinci derece etkilerin çözümlerini değerlendirmek için bu eşit puan fırsatını bir kanca olarak kullanmalısınız.

İlk sipariş efekti en yüksek önceliğe sahip. Eşit puanlara ulaşılması halinde, öncelik 2 ile olan çözüm geçerli olur. Bir çözümün parametrelerini ayarlayarak eşit puanların ortaya çıkma şansını etkileyebilir ve bu şekilde öncelik 1 ve öncelik 2 çözümlerinin ağırlığını değiştirirsiniz.

İstenilen davranışın uygulanması

Hangi renklerin güvenli olduğunu öğrenin:

  • 16 rengin% 33'ü kötüdür ve bu nedenle bir hareketin skoru 63/3'ün altında olduğunda harekete izin verilmez. Bu nedenle threshold = 63/3=21, 63, 6 bit ve% 33 = 1/3 için maksimum puandır (yukarıdaki grafikte gösterilebilir).

İyi hamle yoksa, dikey veya geriye doğru hareket ettirin:

  • Hiçbir ileri harekete izin verilmediğinde, dikey hareketler aynı şekilde birbirleriyle karşılaştırılır. Ayrıca dikey hareketlere izin verilmezse, geriye doğru hareketler sıralanır. Bu weightMovedeğişken aracılığıyla elde edilir .

Neyin ötesinde olduğuna bakın:

  • 2 ya da 3 hareket aynı puanları olduğunda, bu hareket yaklaşık 3x3 kutusunda (yoluyla belirler x2ve y2döngüler) (ne yoluyla en iyi seçenektir mainSubScoredeğişken). Bu 3x3 kutusundaki en sağ sütun önde gidiyor.
coord_t adjustedColorPlayer(dna_t d, view_t v) {
    const int chunklen = 6,threshold = 63/3;
    int xBestScore=0, yBestScore=0;
    long bestScore=-1, weightMove, weightMove2, mainScore;
    for(int x = -1; x <= 1; x++) {
        if (x < 0) weightMove = 1000; // moving backward
        if (x== 0) weightMove = 10000; //moving vertical
        if (x > 0) weightMove = 100000; //moving forward
        for(int y = -1; y <= 1; y++) {
            if(v(x, y) == OUT_OF_BOUNDS || (x==0&&y==0) ) continue;
            mainScore = dnarange(d,v(x,y)*chunklen,chunklen);
            if (mainScore<threshold+1) {
                mainScore =  0; //not a suitable move because too low score
            }else{
                mainScore*= weightMove;
                // when equal score, use sub score by examining 5x5 box to rank moves
                for(int x2 = x-1; x2 <= x+1; x2++){     
                    if (x2 < x) weightMove2 = 1; // moving backward
                    if (x2== x) weightMove2 = 10; //moving vertical
                    if (x2 > x) weightMove2 = 100; //moving forward
                    for(int y2 = x-1; y2 <= y+1; y2++){     
                        if(v(x2, y2) != OUT_OF_BOUNDS){
                            long mainSubScore = dnarange(d,v(x2,y2)*chunklen,chunklen);
                            if (mainSubScore>=threshold+1) mainScore+=mainSubScore*weightMove2;
                        }
                    }
                 }
            }
            if(mainScore > bestScore) {
                bestScore = mainScore;              
                xBestScore = x;
                yBestScore = y;
            }
        }
    }
    return{xBestScore,yBestScore};
}

Skor: 123 (2K çalışır)

İlk 50 Skor (18 maç sadece 1 puan aldı):

1 10 1 79947 3 1 11 125 7333287 23701 310869 53744 1 2 2 2 2 1 1 57556 2 688438 60 1 2 2636261 26306 1 125369 1 1 1 61895 27 1 36 1 91100 87636 1 2 47497 53 16 1 11 222384 1 1 1 1 1 1 1 1

Tuzakları tanımla:

Bir bitsum4 depolaması kullanılarak keyfi bir oyun sona erdiğinde en yüksek skoru olan türlerin DNA'sını inceledim (bu nedenle renk puanı [0,4]):

  • 0 attı: Teleport geriye, her iki duvar, 1x güvenli
  • 1 attı: Tuzak geriye (çok zararsız), Teleport geriye, 1 kat güvenli
  • 2 attı: tuzak ileri (çok tehlikeli), 1x güvenli
  • 3 attı: Teleport ileri, 5x güvenli
  • 4 attı: Teleport ileri, 1x güvenli

Bundan duvarlar ve teleportların doğru bir puan aldığı sonucuna varılabilir. Tuzaklar tanımlanmamıştır çünkü yönüne ve başlangıçtaki renklerine bağlı olduklarından, puanlama varış yerinin rengine göre yapılır. Bu nedenle, menşe rengine ilişkin veri depolamaya da ihtiyaç vardır, öyleyse v(0,0). İdeal bir dünyada 16 renk x 8 yön x 3 bit = 384 bit için bilgi depolamak istiyoruz.

Ne yazık ki, sadece 100 bit var ve hepsini kullanamayız, çünkü yukarıda açıklanan çözüm için biraz hafızaya ihtiyacımız var. Bu nedenle 4 renk kutusu yapacağız:

  • 0: renk 0 - renk 3,
  • 1: renk 4 - renk 7,
  • 2: renk 8 - renk 11,
  • 3: renk 12 - renk 16

ve 4 hareketli yön kutusu

  • 0: dikey veya geriye doğru hareket et,
  • 1: ileri hareket et,
  • 2: ileri gitmek
  • 3: ileri aşağı hareket

Ondalık puan 4 veya daha yüksek olduğunda (100,101,110,111), bir tuzağın bu hücreyle ilişkili olduğu varsayılır, sonuç olarak bu hareket eşit puanlar alındığında alınmaz. Bu yüzden tuzak tanımlaması ikinci dereceden bir etkidir ve “neyin ötesinde olduğuna bak” üçüncü öncelikli bir çözüm olacaktır.

int dnaLookup2(dna_t &d, int start, int chunklen, int storageMethod) {
    // Definition of storageMethod: 0=decimal, 1=streak, 2=bitsum
    int score = 0, streak = 0;
    for(int i = start; i < start+chunklen; i++) {
        int value = d[i];
        if (storageMethod==0) {
            score = (score << 1) |value;
        }else{
            if (storageMethod==1){
                if(value) score += ++streak; else streak = 0;
            }else{
                if(value) score ++;         
            }
        }
    };  
    return score;
}

coord_t theTrapFighter(dna_t d, view_t v) {
    // Definition of storageMethod: 0=decimal, 1=streak, 2=bitsum
    const int colorMemStorageMethod = 1, colorMemBlockSize = 3;
    const int trapMemStorageMethod = 0, trapMemBlockSize = 3;
    const int trapMemTopThreshold = 4, nDirBins = 4, nColorBins = 4;

    int xBestScore=0, yBestScore=0;
    long bestScore=-1, weightMove, weightMove2, mainScore;
  for(int x = -1; x <= 1; x++) {
        if (x < 0) weightMove = 1000; // moving backward
        if (x== 0) weightMove = 10000; //moving vertical
        if (x > 0) weightMove = 100000; //moving forward
        for(int y = -1; y <= 1; y++) {          
            int color = v(x, y);
            if(color == OUT_OF_BOUNDS || (x==0&&y==0) ) continue;
            mainScore = dnaLookup2(d,color*colorMemBlockSize,
             colorMemBlockSize,colorMemStorageMethod);
            if (mainScore==0) {
                //not a suitable move because too low score
            }else{
                mainScore*= weightMove;
                //lookup trap likelihood
                int directionBin = 0;
                if (nDirBins==3) directionBin = x>0?y+1:-1;
                if (nDirBins==4) directionBin = x>0?y+2:0;
                // put 16 colors in nColorBins bins
                int colorBin = v(0,0)*nColorBins/N_COLORS; 
                colorBin = colorBin>(nColorBins-1)?(nColorBins-1):colorBin;
                if (directionBin >= 0 &&
                 dnaLookup2(
                   d,
                   colorMemBlockSize*16
                    +trapMemBlockSize*(nColorBins*directionBin+colorBin),
                   trapMemBlockSize,
                   trapMemStorageMethod
                 ) >=trapMemTopThreshold){
                  //suspect a trap therefore no sub score is added                  
                 }else{
                    // when equal score, use sub score by examining 5x5 box to rank moves
                    for(int x2 = x-1; x2 <= x+1; x2++){     
                        if (x2 < x) weightMove2 = 1; // moving backward
                        if (x2== x) weightMove2 = 10; //moving vertical
                        if (x2 > x) weightMove2 = 100; //moving forward
                        for(int y2 = x-1; y2 <= y+1; y2++){     
                            int color2 = v(x2, y2);
                            if(color2 != OUT_OF_BOUNDS){
                                mainScore+=weightMove2 * dnaLookup2(d,color2*colorMemBlockSize,
                                 colorMemBlockSize,colorMemStorageMethod);
                            }
                        }
                    }               
                 }
            }
            if(mainScore > bestScore) {
                bestScore = mainScore;              
                xBestScore = x;
                yBestScore = y;
            }
        }
    }
    return{xBestScore,yBestScore};
}

Puan: 580 (2K çalışır)

İlk 50 Skor (13 maç sadece 1 puan aldı):

28,044 14,189 1 2,265,670 2,275,942 3 122,769 109,183 401,366 61,643 205,949 47,563 138,680 1 107,199 85,666 31 2 29 1 89,519 22 100,908 14,794 1 3,198,300 21,601 14,408,278 1

Duvar hakkındaki yanlış varsayım çoğu zaman yenidoğanlara moronlar tarafından çoğaltılır:

Bazı türler yanlış bir şekilde duvarların iyi olduğunu varsayıyor ve her zaman onlara taşınmaya çalışıyor ve bu nedenle duvarların önünde sıkışıp kalıyorlar. Ayrıca, sonsuz teleposter döngülerinde sıkışıp kalabilirler. Etki her iki durumda da aynıdır.

Asıl sorun, birkaç yüz yinelemeden sonra bazı genlerin çok baskın hale gelmesidir . Bunlar 'doğru' genler ise, çok yüksek puanlar alabilirsiniz (> 1 milyon puan). Bunlar yanlışsa, sıkışmışsınızdır, çünkü 'doğru' genleri bulmak için çeşitliliğe ihtiyacınız vardır.

Savaşta moronlar: Çözüm 1: renk inversiyonu

Denedim ilk çözüm, hala çok çeşitli olan kullanılmayan hafızanın bir kısmını kullanmak için bir çaba oldu. Renkli belleğinize 84 bit ayırdığınızı ve yakalama hafızasını yakaladığınızı varsayalım. Kalan 16 bit, çok çeşitli olacaktır. [0,255] aralığında değerleri olan 2 ondalık 8 değişkeni doldurabiliriz ve bunlar homojendir, yani her değerin 1/256 şansı vardır. Değişkenler inInverseve çağrılacak inReverse.

Eğer inInverse255 (1/256 şans) eşittir, o zaman olacak renk puanlarının yorumlanması ters . Bu nedenle, moronun yüksek olduğu için güvende olduğunu varsaydığı duvar düşük puan alır ve bu nedenle kötü bir hareket olur. Dezavantajı, bunun aynı zamanda 'haklar' genlerini de etkileyeceği, dolayısıyla daha düşük puanlara sahip olacağımızdır. Ayrıca, bu inInversetürün kendisini yeniden üretmesi gerekecek ve çocukları da baskın DNA'nın bir kısmını elde edecek. En önemli kısmı çeşitliliği geri getirmesidir.

Eğer inReverse255 (1/256 şans) eşittir, o zaman olacak renk puanlarının depolama konumlarının sırasını tersine çevirmek . Böylece renk 0'dan önce 0-3 bit olarak saklandı. Şimdi renk 15 bu konumda saklanacaktır. inInverseYaklaşımdaki fark inReverseşu ana kadar yapılan işi geri alacağıdır. İlk kareye döndük. Oyunun başladığı zamanki gibi benzer genleri olan bir tür yarattık (tuzak bulma hafızası hariç)

Kullanmak akıllıca olup olmadığını optimizasyonu Via test edilir inInverseve inReverseaynı anda. Optimizasyondan sonra puan artmadı. Sorun şu ki, daha çeşitli gen popülasyonumuz var, ancak bu aynı zamanda 'doğru DNA'yı da etkiliyor. Başka bir çözüme ihtiyacımız var.

Savaşta moronlar: Çözüm 2: karma kod

Türlerin 15 olası başlangıç ​​pozisyonu vardır ve şu anda aynı başlangıç ​​pozisyonunda başlarsa, tam olarak aynı yolu takip etmesi için çok büyük bir şans vardır. Eğer duvarları seven bir moron ise, aynı duvarda tekrar tekrar sıkışıp kalacak. Şans eseri çok ileri bir duvara ulaşmayı başarırsa, yanlış varsayımlarıyla DNA havuzuna hakim olmaya başlayacak. İhtiyacımız olan, yavrularının biraz daha farklı bir yol izleyeceğidir (çünkü onun için zaten çok geç) ve ilerideki duvara değil, daha yakındaki bir duvara takılıp kalmayacak . Bu, bir karma kod ekleyerek elde edilebilir .

Bir kod , panodaki mevcut konumu benzersiz bir şekilde tanımlama ve etiketleme amacına sahip olmalıdır. Amaç, (x, y) pozisyonunun ne olduğunu bulmak değil, atalarımın daha önce bu konumda bulundukları soruları yanıtlamak mı?

Tam tahtanın önünüzde olduğunu ve her 5 ila 5 hücreden oluşan bir jpg yapabileceğini varsayalım. (53-5) x (15-5) = 380 görüntüyle bitirdiniz. 1'den 380'e kadar olan bu görüntü numaralarını verelim. Hash kodumuz bir kimlik olarak görülmeli, farklı olanlarda 1'den 330'a kadar çalışmaz ancak eksik IDS'leri vardır, yani 563, 3424, 9424, 21245, vb.

unsigned long hashCode=17;
for(int x = -2; x <= 2; x++) {
    for(int y = -2; y <= 2; y++) {
        int color = v(x, y)+2;
        hashCode = hashCode*31+color;
    }
}       

Asal sayılar 17ve 31başlangıçta eklenen bilginin kaybolmasını önlemek için oradalar. Daha sonra hashcode'umuzu programın geri kalanına nasıl entegre edeceğiniz konusunda daha fazla bilgi .

"Altında bak" alt puanlama mekanizmasını başka bir alt puanlama mekanizmasıyla değiştirelim. İki ya da üç hücre eşit ana puana sahip olduğunda,% 50 şans, ilk hücrelerin seçilme şansı, alt hücrelerin seçilme şansı% 50 ve orta hücrenin seçilme şansı% 0 olacaktır. Şans tesadüfi jeneratör tarafından belirlenmeyecek, ancak bellekten gelen bitler tarafından belirlenecektir , çünkü bu şekilde aynı durumda aynı seçeneğin yapıldığından emin oluruz.

İdeal bir dünyada (sonsuz miktarda belleğe sahip olduğumuz yerde), mevcut durumumuz için benzersiz bir hashcode hesaplardık , örn. 25881 ve 25881 bellek konumuna gidersek (eğer üst veya alt hücreyi seçmemiz gerekiyorsa orada okurduk) eşit bir puandır). Bu şekilde aynı durumda olacağız (örneğin, tahtayı ikinci kez gezip aynı pozisyonda başladığımızda) aynı kararları alırdık. Biz sonsuz hafıza olmadığı için biz modulo uygulayacaktır için kullanılabilir bellek boyutu karma kodu . Geçerli karma kod , modulo işleminden sonraki dağılımın homojen olması anlamında iyidir.

Yavrular hafifçe değiştirilmiş DNA ile aynı tahtayı seyahat ettiğinde çoğu durumda (>% 99) aynı kararı verir. Ancak o kadar ileri gelirse, şans dolgusu atalarınınkinden farklı olma ihtimali artar. Bu kadar ilerideki bu duvara takılma şansı küçük. Atası ile aynı duvarda sıkışıp kalırken nispeten büyük, ancak bu çok kötü değil, çünkü çok fazla yavru üretmeyecek. Karma kod yaklaşımı olmadan, yakındaki ve uzaktaki duvara takılma şansı neredeyse aynıdır

Optimizasyon

Optimizasyondan sonra, tuzak tanımlama tablosunun gerekli olmadığı ve renk başına 2 bitin yeterli olduğu sonucuna varıldı. Hafızanın geri kalan kısmı 100-2x16 = 68 bit, karma kodunu saklamak için kullanılır. Karma kod mekanizması tuzaklardan kaçınabiliyor gibi görünüyor .

15 parametre için optimize ettim. Bu kod en iyi ayarlanmış parametre setini içeriyordu (şimdiye kadar):

int dnaLookup(dna_t &d, int start, int chunklen, int storageMethod,int inInverse) {
    // Definition of storageMethod: 0=decimal, 1=streak, 2=bitsum
    int score = 0;
    int streak = 0;
    for(int i = start; i < start+chunklen; i++) {
        int value = d[i];
        if (inInverse) value = (1-d[i]);            
        if (storageMethod==0) {
            score = (score << 1) |value;
        }else{
            if (storageMethod==1){
                if(value) score += ++streak; else streak = 0;
            }else{
                if(value) score ++;         
            }
        }
    };  
    return score;
}

coord_t theFittest(dna_t d, view_t v) {
    // Definition of storageMethod: 0=decimal, 1=streak, 2=bitsum
    const int colorMemStorageMethod = 2, colorMemBlockSize = 2, colorMemZeroThreshold = 0;
    const int useTrapMem = 0, trapMemStorageMethod = -1, trapMemBlockSize = -1;
    const int trapMemTopThreshold = -1, nDirBins = -1, nColorBins = -1;
    const int reorderMemStorageMethod = -1, reorderMemReverseThreshold = -1;
    const int reorderMemInverseThreshold = -1;
    // Definition of hashPrority: -1: no hash, 0:hash when 'look beyond' scores equal,
    // 1: hash replaces 'look beyond', 2: hash replaces 'trap finder' and 'look beyond'
    // 3: hash replaces everything ('color finder', 'trap finder' and 'look beyond')
    const int hashPrority = 2;
    int inReverse = reorderMemReverseThreshold != -1 && 
     (dnaLookup(d,92,8,reorderMemStorageMethod,0) >= reorderMemReverseThreshold);
    int inInverse = reorderMemInverseThreshold != -1 && 
     (dnaLookup(d,84,8,reorderMemStorageMethod,0) >= reorderMemInverseThreshold);
    int trapMemStart=N_COLORS*colorMemBlockSize;
    unsigned long hashCode=17;
    int moveUp=0;
    if (hashPrority>0){
        for(int x = -2; x <= 2; x++) {
            for(int y = -2; y <= 2; y++) {
                int color = v(x, y)+2;
                hashCode = hashCode*31+color;
            }
        }       
        unsigned long hashMemStart=N_COLORS*colorMemBlockSize;
        if (useTrapMem==1 && hashPrority<=1) hashMemStart+=nDirBins*nColorBins*trapMemBlockSize;
        if (hashPrority==3) hashMemStart=0;
        int hashMemPos = hashCode % (DNA_BITS-hashMemStart);
        moveUp = dnaLookup(d,hashMemStart+hashMemPos,1,0,inInverse);
    }

    int xBestScore=0, yBestScore=0;
    long bestScore=-1, weightMove, weightMove2, mainScore;
    for(int x = -1; x <= 1; x++) {
        if (x < 0) weightMove = 1000; // moving backward
        if (x== 0) weightMove = 10000; //moving vertical
        if (x > 0) weightMove = 100000; //moving forward
        for(int y = -1; y <= 1; y++) {          
            int color = v(x, y);
            if (inReverse) color = 15-v(x, y);
            if(color == OUT_OF_BOUNDS || (x==0&&y==0) ) continue;
            //when MoveUp=1 -> give move with highest y most points (hashScore=highest)
            //when MoveUp=0 -> give move with lowest y most points (hashScore=lowest)
            int hashScore = (y+2)*(2*moveUp-1)+4; 
            mainScore = dnaLookup(
              d,
              color*colorMemBlockSize,
              colorMemBlockSize,
              colorMemStorageMethod,
              inInverse
             );
            if (mainScore<colorMemZeroThreshold+1) {
                mainScore =  0; //not a suitable move because too low score
            }else{
                mainScore*= weightMove;
                //lookup trap likelihood
                int directionBin = 0;
                if (nDirBins==3) directionBin = x>0?y+1:-1;
                if (nDirBins==4) directionBin = x>0?y+2:0;
                // put 16 colors in nColorBins bins
                int colorBin = v(0,0)*nColorBins/N_COLORS; 
                if (inReverse) colorBin = (15-v(0,0))*nColorBins/N_COLORS; 
                colorBin = colorBin>(nColorBins-1)?(nColorBins-1):colorBin;
                if (useTrapMem && directionBin >= 0 &&
                 dnaLookup(
                   d,
                   trapMemStart+trapMemBlockSize*(nColorBins*directionBin+colorBin),
                   trapMemBlockSize,
                   trapMemStorageMethod,
                   0
                 )>=trapMemTopThreshold){
                  //suspect a trap therefore no sub score is added                  
                 }else{
                    if (hashPrority>=1){
                        mainScore+=hashScore;
                    } else{
                        // when equal score, use sub score by examining 5x5 box to rank moves
                        for(int x2 = x-1; x2 <= x+1; x2++){     
                            if (x2 < x) weightMove2 = 1; // moving backward
                            if (x2== x) weightMove2 = 10; //moving vertical
                            if (x2 > x) weightMove2 = 100; //moving forward
                            for(int y2 = x-1; y2 <= y+1; y2++){     
                                int color2 = v(x2, y2);
                                if (inReverse) color2 = 15-v(x2, y2);
                                if(color2 != OUT_OF_BOUNDS){
                                    long mainSubScore = dnaLookup(
                                      d,
                                      color2*colorMemBlockSize,
                                      colorMemBlockSize,
                                      colorMemStorageMethod,
                                      inInverse
                                    );
                                    if (mainSubScore>=colorMemZeroThreshold+1){
                                        mainScore+=mainSubScore*weightMove2;
                                    }
                                }
                            }
                        }
                    }               
                 }
            }
            if (hashPrority==2 || (useTrapMem<=0 && hashPrority>=1)) mainScore+=hashScore*10;
            if (hashPrority==3) mainScore=hashScore*weightMove;         

            if(mainScore > bestScore) {
                bestScore = mainScore;              
                xBestScore = x;
                yBestScore = y;
            }
        }
    }
    return{xBestScore,yBestScore};
}   

Puan: 922 (2K çalışır)

İlk 50 Skor (9 maç sadece 1 puan aldı):

112.747 3 1 1.876.965 8 57 214.921 218.707 2.512.937 114.389 336.941 1 6.915 2 219.471 74.289 31 116 133.162 1 5 633.066 166.473 515.204 1 86.744 17.360 2 190.697 1 6 122 126.399 399.045 1 4.172.168 1 169.119 4.990 77.432 236.669 3 30.542 1 6 2.398.027 5 1 2 8

Bu benim ilk C ++ programım. Gnome analizinde artık çoğunuzun geçmişi var. Bu konuda çalışmaktan gerçekten zevk aldığım için organizatörlere teşekkür etmek istiyorum.

Herhangi bir geri bildiriminiz varsa, lütfen aşağıda bir yorum bırakın. Uzun metinler için özür dilerim.


Tuzak analizini oldukça ilginç buluyorum.

Örneğin, 12.5 16 bit kelime olarak görülen 25 renk değerini xormek ve bir modulo almak gibi başka bir karma işlevi denediniz mi? Asal sayı uyumu daha iyi bir homojenlik verdiğine ikna olmadım, ama ben büyük bir matematikçi değilim.

Ayrıca bir yama algoritması eklemeyi düşündünüz mü? Genomdan bağımsız olarak büyük bir gelişme faktörü gibi görünmektedir çünkü genomun kabiliyetini yalnızca kazanan bir pozisyona götürme olasılığı daha yüksek olan patikalar boyunca test edenlere hamleleri sınırlayacaktır.

kuroi, Geri bildiriminiz için teşekkür ederiz. Xoring'i denemedim, çünkü c ++ 'da ikili işlemler ile familar olmadığım için. Sanırım 12,5 8 bit kelime mi demek istiyorsun? Xoring kullanıyor musunuz?
Ruut

Ne tür bir karma işlevi kullandığımı görmek için "inançlılar" koduma bakabilirsiniz. Temelde iz bırakmayan hücreleri atlıyorum ve izlenen renkleri 16 bitlik bir kelimenin yüksek ve düşük sıralı parçaları olarak kabul ediyorum. Tüm bu kelimeler XOR'larla, daha sonra karma tablo boyutuna bölünen bir kayıt defterinde toplanır. Maksimum değer (65535) tablo boyutundan (<100) çok daha yüksek olduğu sürece, modulo iyi bir yayılma gücüne sahiptir. Bunu rastgele oluşturulmuş geniş bir ızgara kümesi üzerinde test ettim ve iyi bir homojenliğe sahip görünüyor.

6

Pathfinder, C ++, ön puan 35.8504 (50 tur)

Tamamen revizyon! Algoritmamı C ++ 'a taşıdım ve biraz çimdikledim, ancak skor hala çok yüksek değildi, çünkü muhtemelen fareler kafalarını duvara vurmaya devam ediyordu. Bunu geliştirmeye çalışmaktan yoruldum, bu yüzden şimdilik olmasına izin vereceğim.


int dnarange(dna_t &d, int start, int len) {
    int res = 0;
    for(int i = start; i < start+len; i++) {
        res = (res << 1) | d[i];
    }
    return res;
}

int dnasum(dna_t &d, int start, int len) {
    int res = 0;
    for(int i = start; i < start+len; i++) {
        res += d[i];
    }
    return res;
}

int dnaweight(dna_t &d, int start) {
    return d[start] + d[start+1] + 2*d[start+2] + 2*d[start+3] + 3*d[start+4];
}

int trap_d [16] = {1,0,1,1,0,1,-1,1,-1,0,-1,-1,0,-1,1,-1}; //immutable
int nhood [10] = {1,0,1,1,1,-1,0,1,0,-1}; //immutable

coord_t pathfinder(dna_t d, view_t v) {
  int is_trap[16] = {0};
  int pos_or_weight[16] = {0};
  int u_weight = dnaweight(d, 80);
  for (int i = 0; i < 16; i++) {
    int status = dnarange(d, 5*i, 2);
    if (status == 1) {
      is_trap[i] = 1;
      pos_or_weight[i] = dnarange(d, 5*i + 2, 3);
    } else {
      pos_or_weight[i] = dnaweight(d, 5*i);
    }
  }
  int w_area[7][4] = {0};
  for (int j = 0; j < 7; j++) {
    w_area[j][3] = u_weight;
  }
  for (int i = 0; i < 3; i++) {
    w_area[0][i] = u_weight;
    w_area[6][i] = u_weight;
  }
  int d_coeff = dnaweight(d, 85);
  for (int i = 0; i < 3; i++) {
    for (int j = 1; j < 6; j++) {
      int p_or_w, color = v(i, j-3);
      if (color != OUT_OF_BOUNDS) {
    p_or_w = pos_or_weight[color];
      } else {
    p_or_w = 1000;
      }
      if (color != OUT_OF_BOUNDS && is_trap[color] && i+trap_d[2*p_or_w] >= 0) {
    w_area[j + trap_d[2*p_or_w + 1]][i + trap_d[2*p_or_w]] += d_coeff;
      } else {
    w_area[j][i] += p_or_w;
      }
    }
  }
  for (int i = 3; i >= 0; i--) {
    for (int j = 0; j < 7; j++) {
      int min_w = 1000;
      for (int k = std::max(0, j-1); k <= std::min(6, j+1); k++) {
    min_w = std::min(min_w, w_area[k][i + 1]);
      }
      w_area[j][i] += min_w;
    }
  }
  int speed = dnasum(d, 90, 5);
  w_area[2][0] += 2 + speed;
  w_area[4][0] += 2 + speed;
  int goal = dnaweight(d, 95);
  int min_w = 10000;
  int sec_w = 10000;
  int min_x, min_y, sec_x, sec_y, w;
  for (int i = 0; i < 5; i++) {
    w = w_area[nhood[2*i + 1] + 3][nhood[2*i]];
    if (w < min_w) {
      sec_w = min_w;
      sec_x = min_x;
      sec_y = min_y;
      min_w = w;
      min_x = nhood[2*i];
      min_y = nhood[2*i + 1];
    } else if (w < sec_w) {
      sec_w = w;
      sec_x = nhood[2*i];
      sec_y = nhood[2*i + 1];
    }
  }
  if (min_w > goal) {
    int r = v.rng.rint(5);
    return {nhood[2*r], nhood[2*r+1]};
  } else if (sec_w <= goal && v.rng.rint(100) < 2*speed) {
    return {sec_x, sec_y};
  }
  return {min_x, min_y};
}

açıklama

Genel fikir, her bir rengi bir tuzak olsun ya da olmasın olarak sınıflandırmak, daha sonra tuzaklar ve ağırlıklar tuzak olmayanlara yön vermek ve görme ızgarasının sağ kenarına asgari ağırlık yolunu izlemeye çalışmaktır.

Genomun ilk 80 bitinde, her renk 5 bit kullanılarak sınıflandırılır abcde. Eğer ab = 01renk bir tuzaktır ve cdeyönünü kodlar (sekiz olasılık). Eğer ab ≠ 01renk bir tuzak değil ve ağırlığıdır a + b + 2*(c + d + e).

Daha sonra, "bilinmeyen" renklerle dolgulu, farenin sağındaki görüş alanını temsil eden 3x7'lik bir ızgara başlattık. Bitler 80-84, bilinmeyen hücrelerin ağırlığını tuzak olmayan renklere benzer şekilde kodlar ve 85-89 bitleri, tuzaklar için ortak bir ağırlığı kodlar. Izgarayı ağırlıklar ile doldururuz, en kısa yolları hesaplarız ve yan durmayı engellemek için sıçanın hemen üstündeki ve altındaki hücrelere (90-95 bitlerinde kodlanmış) ekstra ağırlık ekleriz. 95-99 bitleri bir hedef ağırlığı kodlar. Bir yolun asgari ağırlığı, altında ise, sıçan muhtemelen bir yere sıkışmış ve rasgele hareket eder (ancak geri dönüş yapmaz). Aksi takdirde, minimum ağırlık yolunu izler. Yanal önleyici ağırlığa bağlı olarak küçük bir olasılıkla, sıçan bunun yerine ikinci-minimum ağırlık yolunu seçer. Bu, duvarlara yapışmayı önlemek içindir (ancak şu anda çok iyi çalışmıyor gibi görünüyor).


Uygulamamı bilgisayarımda çalıştırdım. Birkaç saat sürdü. Ortalama 7.848433940863856 puan elde ediyor. pastebin.com/d50GcwnK
Jakube

@Jakube Çok teşekkürler! Beklediğimden çok daha kötü, ama şimdi tekrar koda baktım, birkaç hata ve başka tuhaflıklar görüyorum. Bunu daha sonra C ++ 'a taşımaya çalışacağım, böylece kendim analiz edebilirim.
Zgarb

5

LookAheadPlayer C ++ ≈ 89.904

Asıl düşüncem, aradığım renge uygun 4 bit aramak ve aşağıdaki birkaç bit'i puan olarak kullanmaktı. Bu mutasyonlar nedeniyle, muhtemelen korkunç bir fikir olduğu ortaya çıktı.

Bu yüzden, mutasyonlara ve geçitlere karşı korumanın yollarını düşündüm ve bana QR kod çözme konusunda yaptığım çalışmaları hatırlattı. QR kodlarında, veriler belirli bir veri bölümünü çok fazla tahrip etmekten kaçınmak için veriler bloklara bölünür ve dizilir.

Bu nedenle, ColorScorePlayer gibi, DNA'yı 16 parçaya böldüm ve verilen puan olarak kullandım. Ancak, skorlar çizgilidir, böylece her bir puanın bireysel bitleri bitişik değildir. Daha sonra hem mevcut olası hamlelerin hem de sonraki potansiyel hamlelerin puanlarını toplarım ve yapılacak en iyi hamleyi seçerim.

Not: Bu, MinGW'de kodlandı / test edildi. Optimizasyonlarla veya çoklu okuma ile derlenmez. Bunların çalışacağı bir derleyiciyi kullanmak için kullanışlı bir Linux kurulumum veya Visual Studio'm yok. Yarın sabah hızlıca test edeceğim, ancak herhangi bir sorunla karşılaşırsanız lütfen bana bildirin.

// get striped color score, 6 bits per color. should be
// resistant to getting erased by a crossover
void mapColorsBitwise(dna_t &d, int* color_array) {
    for (int i=0; i<N_COLORS; i++) {
        int score = 0;
        for (int j=0; j<6; j++) {
            score = (score<<1) | d[ j*N_COLORS + i ];
        }
        color_array[i] = score;
    }
}

// label for the lookup tables
enum direction_lut {
    UP_RIGHT=0, RIGHT, DOWN_RIGHT
};

// movement coord_t's to correspond to a direction
static const coord_t direction_lut[3] = {
    { 1, -1 }, { 1, 0 }, { 1, 1 }
};

// indexes into the arrays to denote what should be summed
// for each direction.
static const int sum_lut[3][6] = {
    { 3, 4, 8, 8, 9, 14 }, { 9, 13, 13, 14, 14, 19 },
    { 14, 18, 18, 19, 23, 24 }
};

coord_t lookAheadPlayer(dna_t d, view_t v) {
    int scoreArray[25] = { 0 };
    int colorScores[N_COLORS] = { };

    // Get color mapping for this iteration
    mapColorsBitwise(d, colorScores);

    for (int y=-2; y<=2; y++) {
        for (int x=0; x<=2; x++) {
            // Get the scores for our whole field of view
            color_t color = v(x,y);
            if (color != OUT_OF_BOUNDS)
                scoreArray[ (x+2)+((y+2)*5) ] += colorScores[color];
        }
    }

    // get the best move by summing all of the array indices for a particular
    // direction
    int best = RIGHT;
    int bestScore = 0;
    for (int dir=UP_RIGHT; dir<=DOWN_RIGHT; dir++) {
        if (v(direction_lut[dir].x, direction_lut[dir].y) == OUT_OF_BOUNDS)
            continue;

        int score = 0;
        for (int i=0; i<6; i++) {
            score += scoreArray[ sum_lut[dir][i] ];
        }

        if (score > bestScore) {
            bestScore = score;
            best = dir;
        }
    }

    return direction_lut[best];
}

5

SlowAndSteady C ++ (puan 9,7)

Genomun parçalarını sayı olarak yorumlamaya güvenemeyiz, çünkü tek bir bit çevirme, pozisyonuna bağlı olarak radikal biçimde farklı etkilere sahip olabilir. Bu yüzden sadece 16 6-bit segment kullanıyorum ve onları 1s sayısına göre puanlandırıyorum. Başlangıçta 111111iyiydi ve 000000kötüydü ve uzun vadede (genom tamamen geliştikten sonra) önemli olmamakla birlikte, DNA'nın ilk konfigürasyonunda bölümlerin çoğunun 2-4 tanesi vardı, bu yüzden 9 - (#1 - 3)^2puanlama için kullanmaya başladım. İlk turlarda çok daha fazla hareket özgürlüğü ve daha hızlı evrim sağlar.

Şu anda sadece en yakın 7 komşuya bakıyorum, renk puanına bir yön sapması ekliyorum ve rastgele en yüksek yönlerden birinde hareket ediyorum.

Skorun kendisi çok yüksek olmasa da, kriterlerim bitiş çizgisine ulaşmakta ve vakaların 3 / 4'ünde> 1 puan almaktadır.

coord_t SlowAndSteadyPlayer(dna_t d, view_t v) {
    const int chunklen = 6;
    int color_scores[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    for(int i=0; i<16; i++){ //count ones
        for(int j=0; j<chunklen; j++){
            color_scores[i] += d[i*chunklen + j];
        }
    }

    int moves[7][2] = {
        {-1,1}, {0,1}, {1,1},
                       {1,0},
        {-1,-1},{1,-1},{-1,-1}
    };
    int movescores[7];
    int smax = -1;
    int nmax = 0;
    int best_moves[7];
    for(int m=0; m<7; m++){ //compute the score for each move
        int temp_color = v(moves[m][0], moves[m][1]);
        if(temp_color == OUT_OF_BOUNDS){
            movescores[m] = 0;
            continue;
        }
        int dir_bias[3] = {1,3,6};
        int temp_score = 9-(color_scores[temp_color]-3)*(color_scores[temp_color]-3) + dir_bias[moves[m][0]+1];
        movescores[m] = temp_score;

        if(temp_score > smax) {
            smax = temp_score;
            nmax = 0;
        }
        if(temp_score == smax) best_moves[nmax++] = m;
    }

    int best_chosen = v.rng.rint(nmax);
    return {moves[best_moves[best_chosen]][0], moves[best_moves[best_chosen]][1]};
}

Ve 100 panoda bir puanlama

Scores: 5 4 13028 1 1 101 2 24 1 21 1 4 2 44 1 1 24 8 2 5 1 13 10 71 2 19528 6 1 69 74587 1 1 3 138 8 4 1 1 17 23 1 2 2 50 7 7 710 6 231 1 4 3 263 4 1 6 7 20 24 11 1 25 1 63 14 1 2 2 1 27 9 7 1 7 31 20 2 17 8 176 3 1 10 13 3 142 1 9 768 64 6837 49 1 9 3 15 32 10 42 8

Geometrik ortalama puan: 9.76557


Standart mutasyon oranını veya düzeltilmiş değerinizi kullanarak bir tahta için bahsettiğiniz puan mı?
trichoplax,

"eleştirmenlerim bitiş çizgisine ulaştı ve 3 / 4'de 1'e yükseldi" Puanlama metriğinin ödüllendirilmesini diliyorum
Sparr

5

WeightChooser | C # | Skorlar: 1520 Oyunlarında 220.8262

Olası takip edilen hamlelerin ortalama ağırlığına göre (mavi) olası bir sonraki hareketin (mavi) ağırlığını hesaplar (sarı)

using ppcggacscontroller;
using System.Linq;
using System;

public class WeightChooser
{
    public static ppcggacscontroller.Program.Coord[] cspcoords = new[] {
            new Program.Coord(1, -1),
            new Program.Coord(1, 0),
            new Program.Coord(1, 1),
        };

    const int dnaBits = 4;

    public static void move(GameLogic.IView v, GameLogic.IGenome g, Random rnd, out int ox, out int oy)
    {
        var gcrds = cspcoords.Where(c => viewVal(v, c) > -1)
            .OrderByDescending(p => getBitsSet(g, viewVal(v, p)))
            .ThenByDescending(gt => weight(v, g, gt));

        Program.Coord nextMove = gcrds.First();
        ox = nextMove.x;
        oy = nextMove.y;
    }

    private static uint getBitsSet(GameLogic.IGenome g, int vVal)
    {
        uint i = g.cutOutInt(dnaBits * vVal, dnaBits);
        i = i - ((i >> 1) & 0x55555555);
        i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
        return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
    }

    private static int viewVal(GameLogic.IView v, Program.Coord c)
    {
        return v[c.x, c.y];
    }

    private static double weight(GameLogic.IView v, GameLogic.IGenome g, Program.Coord toGo)
    {
        double w = 0;

        int y = (toGo.y + v.yd) - 1;
        int i = 0;
        for (; i <= 2; i++)
        {
            int field = v[toGo.x + 1, (y + i) - v.yd];
            if (field > -1)
                w += getBitsSet(g, field);
        }

        return w / i;
    }
}

Scores: 32, 56103, 1361, 3351446, 33027, 23618, 22481, 1172713, 1, 3, 1, 1, 1, 2 88584, 106357, 1, 1232, 1, 1651280, 16690, 1, 1, 23732, 207554, 53, 69424, 1, 1,  79361, 1, 1, 51813, 229624, 25099, 2, 1, 234239, 362531, 1, 1, 19, 7295, 1, 7, 2, 196672, 1654208, 73453, 1, 23082, 1, 8, 5, 1685018, 4, 20, 1, 1, 1, 1, 1, 144 671, 122309, 10, 94752, 100895, 1, 54787, 54315, 252911, 79277, 1159, 241927, 94 347, 1, 318372, 37793, 1, 1, 1345310, 18934, 169700, 1, 1, 3, 186740, 83018, 121 758, 1, 358, 1935741, 88, 1, 1, 1, 1, 7, 21, 51144, 2, 1, 267638, 1, 1, 3, 1, 1,  1, 1, 674080, 47211, 8879, 7, 222766, 67214, 2, 89, 21038, 178463, 92846, 3, 14 0836, 1, 1, 111927, 1, 92165, 1, 192394, 1, 1, 2563722, 1, 42648, 1, 16, 1, 1, 2 85665, 1, 212653, 1, 4, 20513, 3, 135118, 13161, 2, 57, 78355, 3, 3, 44674, 8, 1 , 226472, 1, 1, 31588, 19619, 1, 2931870, 60814, 1, 1, 33867, 60740, 20558, 1, 1 5, 3, 5, 1, 1, 1, 60737, 450636, 468362, 1, 1, 347193, 91248, 551642, 1, 427215,  1, 57859, 17, 15, 66577, 24192, 1, 63560, 6568, 40279, 68216, 23098, 180732, 1,  1, 3041253, 1, 253488, 60535, 1, 1, 150838, 7361, 72855, 290699, 104644, 1, 763 01, 378, 1, 89220, 1, 262257, 2, 2, 1, 117, 105478, 33, 1, 65210, 1, 117588, 1, 1, 24320, 12, 3714568, 81152, 1, 1, 10125, 2, 1, 22, 1, 45201, 1, 1, 10518, 1, 1 , 1, 1, 34, 210021, 1, 1, 1, 65641, 6, 72, 1, 7, 2, 161578, 1, 1, 38378, 1, 4113 741, 1, 34450, 244212, 127660, 1, 256885, 46, 2, 1, 1, 103532, 1, 503965, 114774 , 52450, 124165, 73476, 50250, 1, 3, 3755352, 24928, 1, 1, 51, 11, 1, 210580, 1,  62375, 1, 1, 92745, 341232, 167675, 86, 242, 293710, 454841, 1, 49840, 4456758,  121378, 145323, 74904, 5048, 25459, 1, 57, 116999, 1, 1, 76074, 111447, 95706, 1, 1, 52631, 166756, 2159474, 161216, 1, 2, 3, 11904, 1, 22050, 6, 1, 1, 1, 41, 48908, 6, 80878, 28125, 28, 160516, 1, 4, 1, 8, 1, 1, 7, 362724, 1, 397193, 1, 2 5, 1, 59926, 3, 74548, 2320284, 470189, 1, 108, 1, 1, 16, 1, 496013, 1, 1, 1, 1,  107758, 1, 284144, 146728, 1, 70769, 94215, 1, 1, 9961, 97300, 7, 1, 76263, 1, 27, 294046, 40, 8, 2, 1, 57796, 2, 79800, 1043488, 470547, 1, 1, 1, 6, 69666, 8,  1, 1, 344011, 205325, 3963186, 1141527, 61598, 446029, 1, 1, 1, 1, 625247, 1877 92, 136391, 1, 72519, 1, 141168, 412, 98491, 103995, 297052, 1, 1, 1, 1, 3, 17, 9, 62899, 5, 47810, 254, 26789, 2, 1, 1, 3, 10361, 19615, 40430, 17288, 3, 71831 , 41374, 1, 91317, 409526, 1, 184305, 1, 192552, 3, 3587674, 39, 13, 134500, 41,  42, 672, 559835, 9, 39004, 51452, 1, 1, 12293, 11544, 265766, 8590, 1, 8632, 1,  1, 61849, 35155, 1, 74798, 72773, 1, 89, 37, 4, 4405882, 1, 99, 44397, 5, 4, 6,  1, 1, 1, 515818, 78383, 20, 127829, 1824801, 157, 1, 1, 268561, 19, 2, 230922, 1, 103, 98146, 5029789, 304324, 1, 5, 60516, 1, 139, 28982, 7, 20755, 187083, 1,  1, 143811, 37697, 1, 1, 269819, 83, 1, 202860, 13793, 16438, 113432, 1, 1, 2, 5 134384, 29, 84135, 39035, 2, 125, 1, 30, 129771, 41982, 13548, 61, 1, 2, 1, 82, 102, 2, 105581, 210399, 291204, 3012324, 1, 84763, 1, 1, 442067, 2, 1, 1, 1, 116 , 1, 3, 3, 56, 208807, 1, 2, 1, 14, 29, 31286, 1, 1, 162358, 28856, 46898, 1, 16 2698, 1, 1, 1, 65, 1, 1, 234566, 6, 1, 1, 128, 124, 2167692, 181946, 29, 1, 1, 1 , 1, 17, 162550, 179588, 4, 226480, 28, 1, 158512, 35084, 1, 26160, 17566, 1, 81 826, 2, 33, 1, 1, 11, 1, 230113, 1, 1, 1, 24405, 17, 1, 2, 1, 162365, 2, 1, 1, 8 5225, 1, 15016, 51509, 1, 5, 1, 93, 13, 59, 24548, 1, 3, 2, 2, 1, 64424, 1, 1, 4 , 1, 1, 1, 2, 267115, 139478, 52653, 96225, 1, 1, 35768, 3, 1, 1, 3280017, 8, 80 014, 43095, 112102, 1, 1, 1, 79594, 5, 1, 1, 4, 455714, 19, 15, 1, 233760, 55850 5, 2, 2, 1, 63672, 1, 3732951, 1, 135858, 134256, 452456, 151573, 79057, 638215,  88820, 1, 1, 76517, 13, 314006, 5, 1, 17704, 1, 79589, 1, 18371, 530793, 59020,  1, 1, 1, 4, 1, 1, 1, 71735, 1, 1, 1, 1, 1, 37894, 1, 2, 24054, 1, 8, 26471, 34,  1, 48033, 5, 3, 1, 25, 101, 1, 1, 5, 1, 1, 1, 97521, 1, 682817, 286486, 5, 1472 4, 1, 7805226, 6, 1, 1, 1, 7, 2, 1, 1, 1, 25, 233330, 1, 20899, 3417337, 92793, 23, 80821, 1, 1, 115948, 264191, 3, 79809, 1, 2, 59531, 2, 1, 1, 28684, 97, 1, 2 69433, 98769, 1, 76608, 138124, 1, 1, 325554, 122567, 1, 1, 3, 689604, 4, 85823,  66911, 138091, 169416, 21430, 1, 2, 486654, 108446, 93072, 1, 67907, 4, 1, 1, 5 2260, 67867, 210496, 25157, 1, 1, 1, 5477, 2, 2, 11907, 106, 48404, 1, 1, 1, 787 11, 190304, 112025, 1, 9313, 143055, 40189, 315537, 157581, 70714, 6, 180600, 38 594, 103658, 59444, 7, 31575, 1, 1, 581388, 370430, 1, 114446, 1, 1, 2, 3968, 1,  1, 1, 1, 1, 4523411, 1, 1, 270442, 1, 59, 235631, 3, 110196, 9, 1, 93724, 1, 22 917, 1, 6, 1, 2350266, 1, 1, 20, 4686858, 31, 1, 240180, 10, 470592, 3, 61051, 1 45372, 2831, 64052, 10, 120652, 255971, 479239, 1, 387659, 1, 1, 1, 378379, 7, 3 3218, 55914, 1, 1, 1667456, 6, 2, 74428, 3, 2, 1, 121582, 121274, 19651, 59899, 1, 11, 406670, 137835, 100269, 2, 164361, 98762, 44311, 25817, 178053, 31576, 1,  8, 2539307, 121430, 1, 41001, 1, 4, 1, 116258, 91101, 1, 126857, 1, 8, 49503, 1 , 489979, 12, 500332, 1, 52, 4, 8786, 4, 4878652, 12354, 27480, 89115, 87560, 11 793, 5, 1, 4702325, 301188, 1, 1, 1, 1, 1, 416520, 49357, 230103, 24497, 1, 3, 2 , 57366, 183021, 1, 1, 1, 1, 1, 2, 2, 2546229, 1, 2, 38665, 1, 6903, 1, 89519, 9 5119, 64879, 1, 1, 160380, 474336, 3107, 1, 7, 29099, 28667, 3, 196933, 35979, 1 2924, 7, 1, 99885, 6, 1, 1, 1, 7, 1, 1, 1, 1, 65727, 1, 1, 1, 1, 2108110, 3, 107 811, 23818, 701905, 1, 156034, 32, 1, 29, 143548, 1, 67665, 4612762, 1, 3, 20, 1 , 1, 9, 28543, 1, 1, 1, 30978, 9, 1, 19504, 79412, 15375, 763265, 1, 352373, 193 045, 1, 4570217, 9, 1, 6, 29180, 90030, 1, 1, 1, 1, 1, 93, 1, 100889, 1, 1, 37, 15, 17, 1, 81184, 1, 2, 272831, 1, 137, 1, 9, 42874, 679183, 1, 350027, 12, 1, 2 , 1, 26408, 1, 11182, 1, 30, 139590, 7, 3, 1, 1, 34729, 1, 2, 1, 1, 50343, 66873 , 3891, 1, 148952, 1, 1, 22322, 104176, 1, 3, 20549, 140266, 37827, 30504, 17, 6 8588, 120195, 1, 123353, 2, 64301, 11, 1, 109867, 4, 1, 1, 1, 28671, 1, 50963, 5 4584, 1, 1, 1, 33, 1, 381918, 1, 265823, 4771840, 155179, 314, 134086, 1, 1, 30,  1, 2, 1102665, 18, 132243, 3861, 1, 1, 208906, 60112, 1, 1, 1, 31273, 551, 3490 0, 2, 43606, 1, 1, 1, 1, 5, 2, 88342, 2, 1, 19, 3, 1, 1, 1, 1, 28507, 1, 491467,  1, 1, 22, 1, 1, 1, 1, 9345, 9, 18, 84343, 1, 2, 1, 18, 36816, 1, 1, 513028, 287 88, 5037383, 721932, 170292, 108942, 539115, 1, 575676, 20, 1, 31698, 99797, 205 21, 380986, 1, 1, 14, 2, 1, 201100, 30, 1, 119484, 1, 1, 1, 1, 2214252, 3, 4, 18 179, 9, 4, 542150, 1, 6, 157, 3182099, 4, 1, 1, 6140, 3339847, 498283, 52523, 1,  1, 1, 1, 1, 202054, 263324, 1, 6, 2, 1, 2, 72357, 12, 5, 66, 4, 7368, 1, 30706,  61936, 3945270, 138991, 1, 68247, 1, 1, 30482, 35326, 1, 1, 9, 1, 148, 1, 46985 , 1, 4325093, 1, 1, 2880384, 65173, 1, 56581, 179178, 372369, 56187, 3, 12, 8, 4 00743, 3, 28658, 1, 1, 9, 1, 4, 2, 34357, 1, 42596, 68840, 2, 62638, 158027, 617 34, 71263, 1, 1, 9, 1, 6830309, 3, 1, 1, 157253, 129837, 9, 5008187, 48499, 5981 3, 1, 40320, 233893, 5, 1383, 7732178, 16, 1, 13, 5686145, 84554, 1, 79442, 1, 1 , 256812, 127818, 31, 226113, 1, 4, 1, 1, 4506163, 1, 4, 1, 40176, 19107, 205, 2 7, 1, 448999, 1, 1, 2750, 62723, 1, 12, 1, 1, 79881, 1, 48, 13, 4, 1, 28765, 1, 33, 291330, 30817, 2, 1, 1, 1, 4170949, 16, 1, 1, 118781, 10473, 520797, 1, 8, 1 , 80215, 1, 21759, 5143209, 79141, 40229, 1, 17403, 71680, 1115694, 1, 1, 1, 10,  1, 77149, 382712, 1, 11, 84891, 47633, 1, 2, 39037, 1, 213148, 1607280, 127674,  1, 333207, 1, 78901, 1, 16203, 87580, 1, 1565571, 537902, 53000, 15, 1, 2, 1, 2 13127, 1, 338634, 2469990, 469479, 9519, 51083, 1, 42082, 33179, 1, 1, 32444, 3,  1, 201642, 99724, 377, 1, 2, 1, 36919, 1, 322707, 2, 164765, 82516, 1, 5274643,  1, 36421, 1, 8, 1, 117856, 1, 1, 493342, 1, 36289, 7, 1, 62, 2, 1, 38533, 1, 68 , 45754, 9, 102015, 312941, 1, 99 
Final score is 220.826222910756

5

EYLEMTE RATS (bir cevap değil, C ++ botları için bir grafik aracı)

Bu zorluğun başlangıcından beri, farelerin pistte gerçekte ne ile karşılaştığını bulmakta zorluk çekiyordum.
Sonunda denetleyiciyi kırdım ve bir parçanın grafik gösterimini elde etmek için bir yan araç yazdım.
Sonunda biraz daha hackledim ve verilen bir farenin DNA'sının olası yollarının görselleştirmesini ekledim.

Harita son derece karışık ve biraz alışmak gerekiyor, ancak botlarımın nasıl çalıştığını anlamakta oldukça yardımcı oldum.

İşte bir örnek:

örnek parça

Bir şey görmek için muhtemelen yakınlaştırmanız gerekecek, bu yüzden işte sadece ilk yarı:

yarım iz (hedeflenen amaç yok)

İlk başta, sıçanın yollarına bakalım. Her olası başlangıç ​​konumu için bir yol vardır (genellikle 15, bazen biraz daha az). Genellikle birleşme eğilimindedirler, ideal olarak tek bir zafer yerine ulaşırlar.

Yollar büyük düz oklarla gösterilir. Renk sonucu açıklar:

  • yeşil: kazan
  • sarı: sonsuz döngü
  • kahverengi: duvar beceriyor
  • kırmızı: talihsiz kaza

Örnekte, biri sonsuz döngüye, ikisi de yorucu bir ölüme yol açan (göründüğü gibi bir tuzağa iletiliyor) 12 kazanan başlangıç ​​pozisyonumuz var.

Yoldaki süreksizlik, karşılık gelen eğri oklarla takip edebileceğiniz ışınlanmalardan kaynaklanmaktadır.

Şimdi renkli semboller için. 16 rengin anlamını temsil ediyorlar (gri olanlar bir farenin gördüğü şeyi temsil ediyor).

  • duvar: kare
  • teleporter: 4 dallı yıldız
  • tuzak dedektörü: küçük sekizgen

boş renkler ... iyi ... boş.

Teletörler, hedeflerini gösteren giden oklara sahiptir.

Tuzak dedektörleri ayrıca, kırmızı bir daire olarak gösterilen tuzağı gösteren oklara sahiptir.
9'dan bir tanesinde, tuzak, dedektörü ile aynı hücreye yerleştirilmiş, bu durumda küçük dairenin kırmızı dairenin üzerinde olduğunu göreceksiniz.

Bu örnekte soluk sarı renkli bir tuzak için durum böyledir.
Leylak rengi tuzak dedektörlerini belirtilen tuzaklarına doğru aşağıya dönük olarak da görebilirsiniz.

Bazen bir tuzağın kırmızı çemberinin bir duvarın altına gizleneceğine dikkat edin. Her ikisi de öldürücüdür, bu nedenle ışınlanma durumunda sonuç aynıdır.
Ayrıca bir tuzağın bir telsizin üzerine yerleştirilebileceğine dikkat edin, bu durumda teleporter öncelik kazanır (yani, tuzağı etkisiz hale getirmek için tuzağa düşmeden önce sıçan ışınlanır).

Son olarak, gri semboller farelerimin gördüklerini temsil eder (yani, genomlarının renklere atfettiği anlam).

  • duvar: kare
  • tuzak dedektörü: sekizgen
  • tuzak: X

Temel olarak, gri bir kare üzerinde oturan tüm hücreler sıçan tarafından duvarlar olarak kabul edilir.
Büyük X'ler, tuzak olarak kabul edilen hücreleri temsil eder ve karşılık gelen sekizgenler, bunları bildiren dedektörü gösterir.

Bu örnekte, her iki duvar da soluk sarı bir tuzak olduğu gibi tanımlanır (gerçekten ölümcül bir hücreyi gösterir, bu yüzden onu bir duvar olarak temsil eder).
Leylak rengi tuzak dedektörü (gri bir sekizgen üzerine oturur) olarak tanımlanmıştır, ancak tuzak konumu yanlıştır (bazı kırmızı dairelerin altlarında çarpıların olmadığını görebilirsiniz).

4 ışınlayıcıdan 2'si duvar (turkuaz ve tan), 2'si boş hücreler (kırmızımsı ve sarımsı) olarak kabul edilir.

Birkaç boş hücre tuzak dedektörleri veya duvarları olarak kabul edilir. Yakından bakıldığında, bu "hatalı dedektörlerin" gerçekten sıçanı zedeleyecek hücrelere girmeyi yasakladığını görebilirsiniz, bu nedenle gerçek renkleri eşleştiremeseler de kesin bir amaçları vardır.

Kod

Bu bir karmaşa, ama oldukça iyi çalışıyor.

Oyuncunun kodundan bakıldığında, sadece bir arayüz ekledim: verilen bir DNA'nın anlamını bildirmek için kullanılan bir izleme işlevi. Benim durumumda 3 tip kullandım (duvar, tuzak dedektörü ve boş) ancak temel olarak renkle ilgili bir şey (veya genomla ilgili grafik istemiyorsanız hiç bir şey) çıktısını alabilirsiniz.

İzleyiciyi ve renk tanımını, sıçanın DNA'sının "kuru çalışması" ile tüm olası konumlardan harmanlayan büyük bir karakter dizisi oluşturmak için denetleyiciyi hackledim.

Bu, sadece bot rastgele değerler kullanmıyorsa sonuçların gerçekten anlamlı olacağı anlamına gelir. Aksi takdirde, görüntülenen yollar yalnızca bir olası sonucu temsil eder.

Son olarak, tüm bu izler daha sonra grafik çıktısını üreten bir PHP yardımcı programı tarafından okunan büyük bir metin dosyasına konur.

Şu anki versiyonda, sıçan her yeni bir maksimum zindelik seviyesine ulaştıktan sonra (genomun çok fazla anlık görüntü gerektirmeden ilerici bir şekilde arıtıldığını gösteren) ve oyunun sonundaki son bir anlık görüntüsünü (gösteren en başarılı DNA).

Birisi ilgileniyorsa kodu yayınlayabilirim.

Açıkçası bu sadece C ++ botları için işe yarar ve bazı genomlara özgü verileri (benim durumumdaki gri rakamlar) görüntülemek istiyorsanız bir izleme işlevi yazmanız ve PHP kodunu değiştirmeniz gerekecektir .
DNA'ya özgü bilgiler olmadan bile, DNA'nızın izleyeceği yolları çok az bir çaba ile verilen bir haritada görebilirsiniz.

Neden bir ara çıktı?

Öncelikle, C ++ 'nın özellikle MSVC kullanırken konuşacak düzgün bir taşınabilir grafik kütüphanesi yoktur. Win32 genellikle hazır olsa bile, sonradan bir düşünce olarak gelirler ve dış kütüphanelerin, paketlerin ve ihtiyaç duyulan diğer benzeri olmayan nişlerin sayısı, çabuk ve basit bir grafiksel uygulama yazmayı, vücudunun bir bölümünde, dürüstlüğün engellediği korkunç bir acıya dönüştürür. Ben adlandırarak

Ben basit ve hatta hoş bir görev, IMHO C ++ taşınabilir GUI / grafiksel gelişimini kılan tek çevre hakkında Qt (kullanarak kabul - bir mesajlaşma sistemi ekler muhtemelen à la C şiddetle yoksun ++ Objective C ve sınırlayıcı bellek inanılmaz bir iş yok en azından asgari yönetim), ancak bu eldeki görev için fazladan bir öneme sahip gibi görünüyordu (ve kodu kullanmak isteyen herkes, SDK'yı kurmak zorunda kalacaktı - sanıyorum ki zahmete değmezdi).

Portatif bir kütüphaneyi varsayarsak bile, konuşma zorunluluğu yoktur (resim üretmek için bir saniye ya da öylesine büyük ölçüde yeterlidir) ve atasözü sertliği ve içsel dağınıklığı ile C ++ kesinlikle iş için en iyi araç değildir.

Ayrıca, bir ara metin çıktısına sahip olmak çok fazla esneklik sağlar. Veriler orada olduktan sonra, bunları başka amaçlar için kullanabilirsiniz (örneğin botların performansını analiz etmek gibi).

Neden PHP

Dili son derece basit ve uyarlanabilir, prototipleme için çok uygun buluyorum. Aşırı performans gerektirmeyen kod zorlukları için evcil hayvan dilimi yaptım.
Golf için korkunç bir dil olsa da, golf zaten benim çayım değildi.

Sanırım python veya Ruby aynı amaç için kullanmak kadar hoş olurdu, ama onlarla ciddi bir iş yapma fırsatım olmadı ve son zamanlarda web sitelerinde çalışıyordum, yani PHP.

Dili bilmeseniz bile, kodu gereksinimlerinize uyacak şekilde değiştirmek çok zor olmamalıdır. Sadece $değişkenleri önce s unutma , tıpkı eski güzel günler gibi :).


1
Lütfen aletini paylaşır mısın? Cevabınızda ne kod ne de bir bağlantı görüyorum.
Franky

5

SkyWalker - Python - 50 maçta 231'den az puan aldı

Öyleyse önce kod, sonra da bazı açıklamalar. Umarım kopyalanırken hiçbir şey kırılmaz.

class SkyWalker(Player):
    def __init__(self):
        Player.__init__(self)
        self.coords = [#Coordinate(-1,-1),
                       #Coordinate( 0,-1),
                       Coordinate( 1, 0),
                       Coordinate( 1,-1),
                       #Coordinate(-1, 0),
                       #Coordinate( 0, 0),
                       #Coordinate(-1, 1),
                       #Coordinate( 0, 1),
                       Coordinate( 1, 1)]

        self.n_moves = len(self.coords)

    def visionToMove(self, x, y):
        x = x - 2
        y = y - 2

        return (x, y)

    def trapToMove(self, x, y, offx, offy):
        x = x - 2 + (offx % 3) - 1
        y = y - 2 + (offy % 3) - 1
        return (x, y)

    def isNeighbour(self, x1, y1, x2, y2):
        if (x1 == x2) or (x1+1 == x2) or (x2+1 == x1):
            if (y1 == y2) or (y1+1 == y2) or (y2+1 == y1):
                return True
        return False

    def calcMove(self, donots, never, up):
        forwards = {(1, 0): 0, (1, 1): 0, (1, -1): 0, (0, 1): 10, (0, -1): 10}

        for key in forwards:
            if key in never:
                forwards[key] = 100
            for x in donots:
                if (key[0] == x[0]) and (key[1] == x[1]):
                    forwards[key] = 20

        min_value = min(forwards.itervalues())
        min_keys = [k for k in forwards if forwards[k] == min_value]

        return random.choice(min_keys)

    def turn(self):
        trap1 = self.bit_chunk(0, 4)
        trap1_offsetx = self.bit_chunk(4, 2)
        trap1_offsety = self.bit_chunk(6, 2)
        trap2 = self.bit_chunk(8, 4)
        trap2_offsetx = self.bit_chunk(12, 2)
        trap2_offsety = self.bit_chunk(14, 2)
        wall1 = self.bit_chunk(16, 4)
        wall2 = self.bit_chunk(20, 4)
        tel1 = self.bit_chunk(24, 4)
        tel1_good = self.bit_chunk(28, 3)
        tel2 = self.bit_chunk(31, 4)
        tel2_good = self.bit_chunk(35, 3)
        tel3 = self.bit_chunk(38, 4)
        tel3_good = self.bit_chunk(42, 3)
        tel4 = self.bit_chunk(45, 4)
        tel4_good = self.bit_chunk(49, 3)
        up = self.bit_at(100)

        donots = []
        never = []

        for y in range(0, 5):
            for x in range(0, 5):
                c = self.vision[y][x]
                if (c == -1):
                    never += self.visionToMove(x, y),
                elif (c == trap1):
                    donots += self.trapToMove(x, y, trap1_offsetx, trap1_offsety),
                elif (c == trap2):
                    donots += self.trapToMove(x, y, trap2_offsetx, trap2_offsety),
                elif (c == wall1):
                    donots += self.visionToMove(x, y),
                elif (c == wall2):
                    donots += self.visionToMove(x, y),
                elif (c == tel1):
                    if (tel1_good > 3):
                        donots += self.visionToMove(x, y),
                elif (c == tel2):
                    if (tel2_good > 3):
                        donots += self.visionToMove(x, y),
                elif (c == tel3):
                    if (tel3_good > 3):
                        donots += self.visionToMove(x, y),
                elif (c == tel4):
                    if (tel4_good > 3):
                        donots += self.visionToMove(x, y),

        coord = self.calcMove(donots, never, up)

        return Coordinate(coord[0], coord[1])

Bazı açıklama

Bence temel fark, her rengi kodlamamam. Bunun yerine, önemli olan renklerin sayısını kaydetmeye çalışıyorum. Bence bu renkler, tuzaklar, duvarlar ve teleporterler. Numunenin iyi bir hücrenin rengini bilmesine gerek yoktur. Bu nedenle genomum şu şekilde yapılandırılmıştır.

  • Tuzaklar için 2 x 8 bit, ilk 4 bit renk numarası, diğer 4 ofset
  • Duvarlar için 2 x 4 bit, sadece renk
  • Teleporter için 4 x 7 bit, yine renk için 4 bit, 3'ün iyi veya kötü olduğuna karar vermek için

Bu kullanılan toplam 52 bit yapar. Ancak, 3 teleporter kararının yalnızca ilk bitini kullanıyorum (sayının 3 olup olmadığını kontrol ediyorum). Bu nedenle, diğer 2 tanesi beni 44 bit kullanılan bırakarak silinebilirdi.

Her dönüşte vizyonumun her alanını kötü renklerden biri olup olmadığını (+ tahta dışı -1) kontrol ediyorum ve onu numunenin taşımak istemediği alanların listesine ekleyin. Bir tuzak durumunda, bu tuzak rengi için kaydedilen uzaklıktaki alanı eklerim.

Bu hatalı alanların listesine göre bir sonraki hareket hesaplanır. Tercih edilen alanların sırası:

  1. ileri, ileriye doğru
  2. yukarı veya aşağı
  3. geriye ya da aşağı
  4. geriye doğru

Bir kategorinin iki alanı uygulanabilirse, rastgele bir tanesi seçilir.

Sonuçlar

Individual scores: [192, 53116, 5, 1649, 49, 2737, 35, 5836, 3, 10173, 4604, 22456, 21331, 445, 419, 2, 1, 90, 25842, 2, 712, 4, 1, 14, 35159, 13, 5938, 670, 78, 455, 45, 18, 6, 20095, 1784, 2, 11, 307853, 58171, 348, 2, 4, 190, 7, 29392, 15, 1158, 24549, 7409, 1]
On average, your bot got 231.34522696 points

Düşünceler

  • Hiç bir fikrim yok, 50 pistte şanslıysam veya stratejimde bir miktar bilgelik varsa.

  • Koşularım asla kaçmayacak ve süper yüksek puanlar almayacak gibi gözüküyor, ancak golü en az birkaç kez bulma eğilimindeler

  • Bazı küçük rastgelelikler, bazı yarışların bitimine yakın yerlerde bir tuzağa sıkışmamaktan iyidir.

  • Özel olmayan renklerin hiçbir zaman kötü olmadığını düşünüyorum. Bununla birlikte, bir tuzağın ofsetindeyken, onların örnekleri kötü olabilir. Bu nedenle, eğer tuzak, duvar veya kötü ışınlayıcı değilse, kötü bir rengi etiketlemek mantıklı olmaz.

  • Duvarlar en büyük düşmandır

İyileştirmeler

İlk olarak, siyah karelerin hedefe yaklaşıp gitmediğini görmeyi özleyeceğim halde, daha fazla test yapmak ve daha anlamlı bir sonuç elde etmek için bir C ++ portu gerekli.

Başlıca sorunlardan biri, sıçan önünde kötü hücreler (veya numunenin kötü olduğunu düşünenleri) varsa, dairelerde kolayca yukarı ve aşağı hareket etmeye başlamasıdır. Bu gibi durumlarda 2 hamle ileriye bakılarak durdurulabilir veya azaltılabilir ve tekrar geri döneceği bir alana gitmesini önleyebilirsiniz.

Genellikle, iyi genlere sahip bir sıçan hedefe ulaşıp genleri yaymaya başlayana kadar zaman alır. Belki bu durumlarda çeşitliliği artırmak için bir stratejiye ihtiyacım var.

Teleportörlerin hesaplanması zor olduğu için, belki de popülasyonu riskli olanlara bölmeli ve her zaman iyi telekomünikasyon sahiplerini ve daha fazla endişeli olanları almalı ve sadece başka bir seçenek yoksa onları almalıyım.

Genomumun ikinci yarısını bir şekilde kullanmalıyım.


Ayrıca renkleri saklamaya çalışıyorum ama sonuçta işe yaramadığı sonucuna vardım çünkü iki katına çıkacaksınız. Örneğin eğer self.bit_chunk(16, 4)ve self.bit_chunk(20, 4)değerini her ikisine de sahip 0010etkili yalnızca iki tuzakları biri hakkında bilgi depolamış.
Ruut

Bunun çalışmasını sağlamak için bir satıra girintiler eklemeliydim - sanırım kopyalama ve yapıştırma sırasında kayboldu. Şimdi buraya da kodunuza ekledim.
trichoplax

Bu çalıştırmak isteyen herkesten için: Bu piton 2 çalışır ve tek oluşumunu değiştirerek piton 3 çalıştırılabilir itervaluesiçin values.
trichoplax

Aşağıdaki sonuçları aldım: [6155, 133, 21, 12194, 8824, 3, 3171, 112, 111425, 3026, 1303, 9130, 2680, 212, 28, 753, 2923, 1, 1, 4140, 107, 1256 90, 11, 104, 1538, 63, 917, 8, 1, 709, 11, 304, 212, 2, 43, 5, 4, 206, 8259, 75, 28, 7, 1, 11, 5, 1 , 1244, 1398, 13] Geometrik ortalama 122.9220309940335
trichoplax

Güvenilir bir skor elde etmek için 50'den fazla oyun çalıştırmamız gerekecek gibi görünüyor.
trichoplax

3

Python, KomşularYeni Komşular, Puan = 259.84395 100'den fazla oyun

Bu ColorScorePlayer'daki bir varyasyondur. Her 6 bit, bir kare için kalite puanı depolar. Bot hamle yaparken, 3 ileri karenin her birini - çapraz yukarı, ileri ve çapraz aşağı - puanlar. Skor, karenin kalitesi ve sonraki 3 karenin ortalama kalitesinin yarısıdır. Bu, botun ilk karenin kalitesini etkilemeden ileriye dönük bir görünüm verir. Algoritma, bu çözümü yazmadan önce görmediğim LookAheadPlayer'a benzer.

class NeighborsOfNeighbors(Player):
  def __init__(self):
    Player.__init__(self)
    self.coords = [ Coordinate( 1, 0),
                    Coordinate( 1,-1),
                    Coordinate( 1, 1)
                    ]

  def turn(self):
    scores=[self.score(c.x,c.y)+0.5*self.adjacentScore(c.x,c.y) if self.vision_at(c.x,c.y)>-1 else None for c in self.coords ]
    max_score = max(scores)
    return random.choice( [c for s,c in zip(scores,self.coords) if s==max_score] )

  def adjacentScore(self,x,y):
    adjacent = [(x+1,y)]
    if self.vision_at(x,y+1)>-1:
      adjacent+=[(x+1,y+1)]
    if self.vision_at(x,y-1)>-1:
      adjacent+=[(x+1,y-1)]
    adjscores=[self.score(a,b) for a,b in adjacent]
    return sum(adjscores)/float(len(adjscores))

  def score(self,x,y):
    return -1 if self.vision_at(x,y) == -1 else self.bit_chunk(6*self.vision_at(x,y),6)

Bir satırda eksik olan girintiler vardı. Sanırım yapıştırırken kayboldu. Onu ekledim.
trichoplax

Python 3'te çalıştırmak, maks (puan) hesaplarken Yok'u karşılaştırmaktan şikayet etti. Bu yüzden değişti else Noneiçin else 0puanınızı hesaplamak için önceki satırda. Umarım bu mantığınızı değiştirmez (SE'de kaybolan girintiye eklemek dışında kodunuzda hiçbir değişiklik yapmadım).
trichoplax

Python 3'te çalışırken bu cevap için şu puanları aldım: [1, 13085, 360102, 1, 73713, 1, 189, 1, 1, 193613, 34, 195718, 199, 8, 1, 1, 60006, 66453, 2, 2, 53, 425206, 1, 4, 1, 1, 16, 153556, 1, 18134, 35655, 1, 4211684, 2, 1, 26451, 8, 1, 724635, 69242, 38469, 796553, 111340, 1, 25, 40017, 76064, 66478, 209365, 3925393]
trichoplax

428.3750848244933
trichoplax'ın

2

ROUS (Olağandışı Büyüklükte Kemirgen), Java, Puan = 0

Bu, nereye gidileceğine karar vermek için çevreyi birleştirir. Java denetleyicisi çalışmadığı için bunun için puanım yok. Bu, ancak yardım edecek birkaç telsiz bulduğunda çok uzağa gidecektir.Bu, nesli tükenme ve denetleyiciyi arada bir çarpma eğilimindedir. Bu muhtemelen doğal ortamın Ateş Bataklığı olması nedeniyledir.

import java.awt.*;
import java.util.Map;

public class ROUS extends Player{

    private static final int NUMBER_OF_GENES = 33;
    private static final int GENE_SIZE = 3;
    private static final Point[] coords = new Point[]{
        new Point(-1, -1),
        new Point(-1, 0),
        new Point(-1, 1),
        new Point(0, -1),
        new Point(0, 1),
        new Point(1, -1),
        new Point(1, 0),
        new Point(1, 1)
    };

    public Point takeTurn(String dna, Map<Point, Integer> vision){
        Point[] table = decode(dna);
        int hash = hash(vision);
        return table[hash];
    }

    private int hash(Map<Point, Integer> surroundings) {
        return Math.abs(surroundings.hashCode()) % NUMBER_OF_GENES;
    }

    private Point[] decode(String dna) {
        Point[] result = new Point[NUMBER_OF_GENES];

        for (int i = 0; i < NUMBER_OF_GENES; i++){
            int p = Integer.parseInt(dna.substring(i * GENE_SIZE, (i + 1) * GENE_SIZE), 2);
            int x;
            int y;

            result[i] = coords[p];
        }
        return result;
    }
}

1
Java denetleyicisi şimdi çalışıyor.
Martin Ender

3
İlk başta, eski Rusya’ya saygı duyduğunuzu sanıyordum, fakat görünüşe göre Rob Reiner’a.

Mümkün olan en düşük puan 1
trichoplax

@trichoplax ... denetleyiciye çarp ...
TheNumberOne

Oh anlıyorum - yani bu sık sık olur bir koşunun sonuna ulaşamıyorum?
trichoplax

2

Gri Renkli Görünüş (C ++, ~ 1.35)

Bu ortalama olarak çok iyi değil, ancak nadir durumlarda zekice yapar. Ne yazık ki, geometrik ortalamada (1.35) puanlanıyoruz, maksimum puanda değil (20077).

Bu algoritma, her rengin puanını -2 ile 2 arasında bir yere ([-1.1] aralığında bir önyargıya sahip olacak şekilde) eşlemek için yalnızca 4 bit gri kodları kullanarak çalışır ve her hareketin döşemesinin ve sonraki hareketlerinin puanını hesaplar. . Ayrıca, döşemenin kendisinin çarpanını ve sağa hareket etmek için bastırma faktörünü belirlemek için 2 bit gri kod kullanır. (Gray kodları mutasyonlar nedeniyle büyük sıçramalara karşı çok daha az hassastır, ancak orta kod noktası geçişi için hiçbir iyilik yapmıyorlar ...)

Ayrıca, tuzakları özel olarak ele almaya çalışmak kesinlikle hiçbir şey yapmıyor ve düşüşün olabileceğinden şüpheleniyorum (bu teoriyi test etmek için kontrol cihazına herhangi bir araç eklememiş olmama rağmen).

Her olası hamle için bir puan belirler ve tüm hamlelerin arasından en yüksek puana sahip olanları rastgele seçer.

coord_t colorTileRanker(dna_t d, view_t v) {
    const int COLOR_OFFSET = 0; // scores for each color (4 bits each)
    const int SELF_MUL_OFFSET = 96; // 2 bits for self-color multiplier
    const int MOVE_MUL_OFFSET = 98; // 2 bits for move-forward multiplier

    static const int gray2[4] = {0, 1, 3, 2};
    static const int gray3[8] = {0, 1, 3, 2, 7, 6, 4, 5};

    // bias factor table
    const int factorTable[4] = {0, 1, 2, 1};

    const int selfMul = factorTable[gray2[dnaRange(d, SELF_MUL_OFFSET, 2)]]*2 + 9;
    const int moveMul = factorTable[gray2[dnaRange(d, MOVE_MUL_OFFSET, 2)]] + 1;

    // scoring table for the color scores
    static const int scoreValue[8] = {0, 1, 2, 3, 4, 3, 2, 1};

    std::vector<coord_t> bestMoves;
    int bestScore = 0;

    for (int x = -1; x <= 1; x++) {
        for (int y = -1; y <= -1; y++) {
            const int color = v(x, y);
            if ((x || y) && (color >= 0)) {
                int score = 0;

                // score for the square itself
                score += selfMul*(scoreValue[gray3[dnaRange(d, COLOR_OFFSET + color*3, 3)]] - 2);

                // score for making forward progress;
                score += moveMul*(x + 1);

                // score for the resulting square's surrounding tiles
                for (int a = -1; a <= 1; a++) {
                    for (int b = -1; b <= 1; b++) {
                        const int color2 = v(x + a, y + b);
                        if (color2 >= 0) {
                            score += scoreValue[gray3[dnaRange(d, COLOR_OFFSET + color2*3, 3)]] - 2;
                        }
                    }
                }

                if (score > bestScore) {
                    bestMoves.clear();
                    bestScore = score;
                }
                if (score >= bestScore) {
                    bestMoves.push_back({x, y});
                }
            }
        }
    }

    if (bestMoves.empty()) {
        return {v.rng.rint(2), v.rng.rint(3) - 1};
    }
    return bestMoves[v.rng.rint(bestMoves.size())];
}

En son koşumda, puanlarımı aldım: 1 1 1 1 1 1 1 1 46 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 20077 1 1 1 2 1 1 1 1 1

Keşke 20077'lerden ve 1'lerden daha azını alabilseydim. :)


1
Gray kodunu kullanmak grayt fikridir! ;)
matovitch

1
Gray kodları için +1. Bununla birlikte, tamamen mutasyona dirençli bir genom, çeşitliliğe biraz zarar verecektir. Ve Btw, 20.000'lik bir puanla elde edebileceğiniz maksimum seviyeye bile yakın değil. Bazı sıçanlar parkuru olası herhangi bir başlangıç ​​konumundan çalıştırabiliyorsa, ölümsüzleşir ve çok büyük bir zindelik puanı kazanır. Genomu hızla baskındır ve yaklaşık 50K sıçan popülasyonuna ve birkaç milyonun skoruna neden olur.

2

C ++, TripleScore, Puan: 100 ~ 400

Her şeyden önce, puanım çok sayıda koşuya göre büyük ölçüde değişiyor (özellikle 1 sayısı nedeniyle).

Çekirdek, 5 yöndeki puanı hesaplar: yukarı, aşağı, ileri-ileri, ileri ve ileri-aşağı. İlk önce yukarı ve aşağı skorları hesaplanır, sonuçlar yerinde kalmanın değeriyle karşılaştırılır. Yerinde kalmak yukarı veya aşağı hareket etmekten daha iyiyse, bu yönler seçilmeyecektir (bu nedenle ileri gitmelidir). Bu, 2 nokta arasında sıçramayı (yukarı, aşağı, yukarı, aşağı, ...) önlemek içindir.

Şimdi diğer 3 yöne puanlandı: ileri, doğrudan ileri ve aşağı. İncelenen tüm yönlerden en yüksek puana sahip olanlar tutulur ve bunlardan 1'i rastgele seçilir.

Bir yöne puanlama: TripleScore, 3 alt puan kullanarak bir hareketin puanını hesaplar:

  • Hedefin renginin puanı (dna, colorScorePlayer'daki gibi) bağlıdır
  • İlerleme skoru (DNA'ya bağlıdır)
  • Hedeften ileriye doğru bir hamle yapmanın maksimum puanı (DNA'da saklanan bir faktörle çarpılır)

Diğer cevaplarda olduğu gibi, puan büyük ölçüde iade edilen 1 puan sayısına bağlıdır.

#define CHUNKSIZE 5 //We have 20 values so 5 bits/value
#define MAXVALUE 32 //2^CHUNKSIZE
#define AVGVALUE MAXVALUE/2

#define DNASEGMENT(dna, i) dnarange(dna, i*CHUNKSIZE, CHUNKSIZE)
#define DNA_COLOR 0
#define DNA_FORWARD 16
#define DNA_LOOKAHEAD 17

//Get the score for a specific move
int calcscore(dna_t dna, view_t view, int x, int y, bool final){
  if (view(x,y) == OUT_OF_BOUNDS){
    //We cant go there
    return -MAXVALUE;
  }
  //The score of the color
  int s = DNASEGMENT(dna, DNA_COLOR+view(x,y))-AVGVALUE;
  //The score of going forward
  s += x*DNASEGMENT(dna, DNA_FORWARD);

  //Get the children or not
  if (!final){
    int max=-MAXVALUE;
    int v;
    //Get the maximum score of the children
    for (int i=-1; i<2; ++i){
        v = calcscore(dna, view, x+1, y+i, true);
        if (v>max){
            max=v;
        }
    }
    //Apply dna factor to the childs score
    s += (max * DNASEGMENT(dna, DNA_LOOKAHEAD))/AVGVALUE;
  }
  return s;
}

coord_t TripleScore(dna_t dna, view_t view) {
  int maxscore = -100;
  int score;
  coord_t choices[5]; //Maximum 5 possible movements
  int maxchoices = 0;
  int zeroscore = calcscore(dna, view, 0, 0, false);

  //Go over all possible moves and keep a list of the highest scores
  for (int x=0; x<2; ++x){
    for (int y=-1; y<2; ++y){
        if (x | y){
            score = calcscore(dna, view, x, y, false);
            if (score > maxscore){
                maxscore = score;
                choices[0] = {x, y};
                maxchoices = 1;
            }else if (score == maxscore){
                choices[maxchoices++] = {x, y};
            }
        }
    }
    if (!x && maxscore <= zeroscore){
        //I will NOT bounce!
        maxscore = -100;
    }
  }

  return choices[view.rng.rint(maxchoices)];
}

2

Ruby - ProbabilisticScorePlayer

class ProbabilisticScorePlayer < Player
    Here = Vector2D.new( 0, 0)
    Forward = Vector2D.new( 1, 0)
    Right = Vector2D.new( 0, 1)
    Left = Vector2D.new( 0,-1)

    def vision_at(vec2d)
        v = @vision[vec2d.x+2][vec2d.y+2]
        v==-1?nil:v
    end

    def turn
        coords = [Forward]
        [Here,Forward].each{|x|
            [Here,Right,Left].each{|y|
                c = x+y
                if x!=y && vision_at c > -1
                  coords.push c if bit_at(vision_at c)==1
                  coords.push c if bit_at(vision_at(c+Forward)+16)==1
                  coords.push c if bit_at(vision_at(c+Right)+32)==1
                  coords.push c if bit_at(vision_at(c+Left)+48)==1
                  coords.push c if bit_at(vision_at(c+Forward+Right)+64)==1
                  coords.push c if bit_at(vision_at(c+Forward+Left)+80)==1
                end
            }
        }
        coords.sample(random: @rng)
    end
end

Bu oldukça deterministik olmayan sıçan, mahallesinde bir alana çıkma olasılığını hesaplar. Genomdaki ilk 16 slot, 16 rengi temsil eder. Bir yuvadaki 1, renk üzerine basmanın iyi, 0 ise kötü demektir. Sonraki 16, hedefinizin önündeki alan için aynı tutar.

Olasılıksal yaklaşımın temel avantajı, bir duvarın arkasında uzun süre sıkışıp kalmanın neredeyse imkansız olmasıdır. Dezavantajı, neredeyse hiçbir zaman neredeyse mükemmel bir sıçan elde edemeyeceğinizdir.


Özgünlük için +1. Ne tür bir puan aldınız?

Asla henüz test etmedi ...
MegaTom

cİlk değeri vermeyi unuttun mu? İlk kullandığınızda tanımlanmış gibi görünmüyor if.
Martin Ender

@ MartinBüttner evet unuttum. Şimdi düzelteceğim.
MegaTom

Ruby'yi o kadar iyi tanımıyorum, ancak kodunuz Ruby2.1.5 altında çalışmıyor. coordsbir liste değildir, parantez &&yerine kullanır andve unutursunuz ve tüm bunları düzelttikten sonra bile RNG değerlerini bağlamazsınız, böylece boş bir yöne dönersiniz. Bu sözde kod mu, yoksa bir tür Ruby lehçesiyle çalıştırılacak bir şey mi?

2

Java, RunningStar, Puan = 1817.050970291959 1000'den fazla oyun

Bu bot, Run-Bonus'un StarPlayer tekniğiyle renk kodlamasını kullanıyor .

Güncelleme: Sabit java denetleyicisi.

Scores: 6, 81533, 1648026, 14, 5, 38841, 1, 76023, 115162, 3355130, 65759, 59, 4, 235023, 1, 1, 1, 3, 2, 1, 1, 14, 50, 1, 306429, 68, 3, 35140, 2, 1, 196719, 162703, 1, 1, 50, 78233, 5, 5, 5209, 1, 2, 60237, 1, 14, 19710, 1528620, 79680, 33441, 58, 1, 4, 45, 105227, 11, 4, 40797, 2, 22594, 9, 2192458, 1954, 294950, 2793185, 4, 1, 1, 112900, 30864, 23839, 19330, 134178, 107920, 5, 122894, 1, 1, 2721770, 8, 175694, 25235, 1, 3109568, 4, 11529, 1, 8766, 319753, 5949, 1, 1856027, 19752, 3, 99071, 67, 198153, 18, 332175, 8, 1524511, 1, 159124, 1, 1917181, 2, 1, 10, 276248, 1, 15, 1, 52, 1159005, 43251, 1, 536150, 75864, 509655, 1126347, 250730, 1548383, 17, 194687, 27301, 2, 1, 207930, 621863, 6065, 443547, 1, 6, 1, 1, 1, 1, 556555, 436634, 25394, 2, 61335, 98076, 1, 190958, 2, 18, 67981, 3, 8, 119447, 1, 1, 1, 19, 28803, 23, 33, 60281, 613151, 1, 65, 20341, 799766, 476273, 105018, 357868, 3, 92325, 2062793, 18, 72097, 30229, 1, 1, 3, 610392, 1, 202149, 887122, 56571, 1, 77788, 61580, 4, 72535, 381846, 148682, 26676, 1, 210, 3556343, 212550, 650316, 33491, 180366, 1, 295685, 46255, 43295, 1006367, 63606, 1, 1, 1, 1, 3094617, 21, 10, 3, 1, 1, 14730, 1585801, 102, 2, 410353, 1570, 1, 17423, 1, 1849366, 5, 1, 357670, 1, 1, 1, 1, 89936, 349048, 15, 7, 6, 2, 121654, 1852897, 19, 1, 103275, 1, 1, 771797, 23, 19, 6700, 1, 135844, 2966847, 3, 2356708, 101515, 1, 17, 1, 996641, 22, 16, 657783, 171744, 9604, 1, 1335166, 1739537, 2365309, 1, 3378711, 11332, 3980, 182951, 609339, 8, 10, 1746504, 61895, 386319, 24216, 331130, 12193, 1, 284, 1, 2, 50369, 38, 8, 1, 1238898, 177435, 124552, 22370, 1418184, 20132, 6, 2, 730842, 1, 1341094, 141638, 534983, 1551260, 31508, 96196, 434312, 3012, 715155, 1, 276172, 214255, 1, 208948, 4, 1631942, 512293, 37, 64474, 1342713, 1, 132634, 13, 2, 61876, 1081704, 160301, 2, 488156, 2414109, 1809831, 5, 74904, 6, 11, 5, 1, 79856, 96, 35421, 229858, 238507, 3838897, 18, 44, 1, 1659126, 9, 33708, 12, 1, 758381, 162742, 256046, 3, 15, 142673, 70953, 58559, 6, 2, 1, 984066, 290404, 1072226, 66415, 4465, 924279, 48133, 319765, 519401, 1, 1, 1201037, 418362, 17022, 68, 213072, 37, 1039025, 1, 2, 6, 4, 45769, 1, 5, 1061838, 54614, 21436, 7149, 1, 1, 1, 35950, 2199045, 1, 379742, 3, 2008330, 238692, 181, 7, 140483, 92278, 214409, 5179081, 1, 1, 334436, 2, 107481, 1142028, 1, 31146, 225284, 1, 14533, 4, 3963305, 173084, 102, 1, 4732, 14, 1, 25, 11032, 224336, 2, 131110, 175764, 81, 5630317, 1, 42, 1, 89532, 621825, 2291593, 210421, 8, 44281, 4, 303126, 2895661, 2672876, 3, 436915, 21025, 1, 4, 49227, 1, 39, 3, 1, 103531, 256423, 2, 1600922, 15, 1, 2, 58933, 1114987, 1, 4, 3, 1, 1544880, 285673, 240, 2, 128, 214387, 3, 1327822, 558121, 5, 2718, 4, 1258135, 7, 37418, 2729691, 1, 346813, 385282, 2, 35674, 513070, 13, 1930635, 117343, 1929415, 52822, 203219, 1, 52407, 1, 1, 1, 3, 2, 37121, 175148, 136893, 2510439, 2140016, 437281, 53089, 40647, 37663, 2579170, 83294, 1597164, 206059, 1, 9, 75843, 773677, 50188, 12, 1, 1067679, 105216, 2452993, 1813467, 3279553, 280025, 121774, 62, 5, 113, 182135, 1, 16, 71853, 4, 557139, 37803, 228249, 6, 32420, 8, 410034, 73889, 1, 2, 96706, 48515, 1, 3, 1314561, 137, 966719, 692314, 80040, 85147, 75291, 1, 1, 30, 38119, 182723, 42267, 3836110, 22, 986685, 2, 37, 1, 3, 26, 43389, 2679689, 1, 1, 57365, 1, 2662599, 2, 72055, 1, 141247, 1, 1, 1122312, 1, 1080672, 4, 266211, 1, 34163, 1490610, 256341, 1, 627753, 32110, 1, 42468, 1, 10746, 1, 9, 1, 46, 1714133, 5, 117, 1, 104340, 218338, 151958, 122407, 211637, 223307, 57018, 74768, 582232, 2, 621279, 4, 1, 11, 196094, 1839877, 167117, 8, 42991, 2199269, 124676, 1, 1, 1, 5, 1, 1, 698083, 1, 76361, 1564154, 67345, 1398411, 9, 11, 105726, 1197879, 1, 2, 62740, 39, 2, 397236, 17057, 267647, 13, 57509, 22954, 1, 12, 747361, 4325650, 21425, 2160603, 144738, 1, 204054, 3113425, 6, 3019210, 30, 3359, 1, 89117, 489245, 1, 218068, 1, 1, 14718, 222722, 1, 1, 216041, 72252, 279874, 183, 89224, 170218, 1549362, 2, 1, 953626, 32, 130355, 30460, 121028, 20, 159273, 5, 2, 30, 1, 76215, 1654742, 2326439, 1, 53836, 1, 6, 4, 72327, 9, 285883, 1, 908254, 698872, 47779, 3, 2293485, 265788, 3766, 1, 1, 83151, 36431, 307577, 256891, 29, 1, 1, 1093544, 145213, 5, 2, 581319, 2911699, 1, 213061, 1359700, 2, 1, 343110, 1, 157592, 1708730, 1, 22703, 32075, 1, 1, 87720, 159221, 2313143, 10, 2266815, 2106917, 1345560, 3146014, 4, 551632, 1066905, 550313, 4069794, 1, 1406178, 38981, 1, 3, 1, 3039372, 241545, 35, 63325, 85804, 1365794, 2, 2143204, 48, 1, 99, 3225633, 7, 4074564, 1023899, 3209940, 2054326, 70880, 2, 1, 284192, 1944519, 84682, 2, 867681, 90022, 378115, 1, 15, 602743, 1337444, 131, 1, 229, 161445, 3, 2, 5591616, 195977, 92415, 637936, 142928, 1, 2310569, 923, 1, 230288, 1300519, 398529, 2233, 100261, 4323269, 81362, 37300, 1, 233775, 32277, 434139, 323797, 19214, 782633, 2881473, 1, 1, 9, 337016, 1, 515612, 44637, 17, 1, 25, 67758, 1737819, 16454, 30613, 692963, 62216, 222062, 344596, 3, 33782, 19, 180441, 23552, 20462, 70740, 10298, 109691, 1, 1729427, 33714, 1770930, 1, 1, 1, 1, 290766, 136688, 688231, 3250223, 30703, 1985963, 527128, 3, 226340, 195576, 30, 1, 3, 1, 793085, 5527, 5, 1, 2188429, 1327399, 5, 6192537, 1445186, 2478313, 2, 16892, 3, 1, 1, 15, 12, 1361157, 4, 1241684, 1, 45008, 1, 505095, 4037314, 14, 8, 1, 16740, 69906, 45, 1, 240949, 3975533, 212705, 2617552, 278884, 1, 24966, 958059, 231886, 22929, 4052071, 51259, 67791, 78739, 1, 165787, 67, 518191, 86923, 437, 1271004, 135941, 244766, 1, 1, 1, 1152745, 1, 3, 406365, 3847357, 476636, 135097, 304368, 8, 1578276, 1, 1, 375, 1, 1, 1298206, 1860743, 2, 35311, 834516, 421428, 2, 66629, 1, 309845, 398756, 33, 907277, 384475, 2267460, 1, 269300, 124525, 34399, 93584, 362186, 811260, 426109, 1, 1009323, 109986, 122181, 1, 1, 3626487, 11452, 1092410, 57233, 6, 2009226, 1, 83333, 4, 1338631, 79114, 2140249, 51813, 1118986, 43514, 1529365, 1, 101, 1, 1,
package game.players;

import java.awt.Point;
import java.util.*;

public class RunningStar extends Player{

    @Override
    public Point takeTurn(String genome, Map<Point, Integer> vision) {
        Map<Integer, Integer> squareCosts = decode(genome);
        Path path = astar(vision, squareCosts);
        return path.get(1);
    }

    private Path astar(Map<Point, Integer> vision, Map<Integer, Integer> squareCosts) {
        Set<Path> closed = new HashSet<>();
        PriorityQueue<Path> open = new PriorityQueue<>();
        open.add(new Path(new Point(0, 0), 0));
        while (!open.isEmpty()){
            Path best = open.remove();
            if (best.head().x == 2 || (best.head().x > 0 && (best.head().y == 2 || best.head().y == -2))){
                return best;
            }
            for (Path path : pathsAround(best, vision, squareCosts)){
                if (!closed.contains(path) && !open.contains(path)){
                    open.add(path);
                }
            }
            closed.add(best);
        }

        Path p = new Path(new Point(0,0), 0);
        return p.add(new Point((int)(random.nextDouble() * 3 - 1), (int)(random.nextDouble() * 3 - 1)), 0);
    }

    private List<Path> pathsAround(Path path, Map<Point, Integer> vision, Map<Integer, Integer> costs) {
        Point head = path.head();
        List<Path> results = new ArrayList<>();
        for (int i = -1; i <= 1; i++){
            for (int j = -1; j <= 1; j++){
                if (i == 0 && j == 0){
                    continue;
                }
                Point p = new Point(head.x + i, head.y + j);
                if (!vision.containsKey(p) || vision.get(p) == -1){
                    continue;
                }
                results.add(path.add(p, costs.get(vision.get(p))));
            }
        }
        return results;
    }

    private Map<Integer, Integer> decode(String genome) {
        int chunkLength = genome.length()/16;
        Map<Integer, Integer> costs = new HashMap<>();
        for (int i = 0; i < 16; i++){
            int runSize = 0;
            int cost = 0;
            for (int j = i * chunkLength; j < (i + 1) * chunkLength; j++){
                switch (genome.charAt(j)){
                    case '0':
                        runSize = 0;
                        break;
                    case '1':
                        cost += ++runSize;
                }
            }
            costs.put(i, cost);
        }
        return costs;
    }

    private class Path implements Comparable<Path>{

        Point head;
        Path parent;
        int length;
        int totalCost;

        private Path(){}

        public Path(Point point, int cost) {
            length = 1;
            totalCost = cost;
            head = point;
            parent = null;
        }

        public Point get(int index) {
            if (index >= length || index < 0){
                throw new IllegalArgumentException(index + "");
            }
            if (index == length - 1){
                return head;
            }
            return parent.get(index);
        }

        public Point head() {
            return head;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            Path path = (Path) o;

            if (!head.equals(path.head)) return false;

            return true;
        }

        @Override
        public int hashCode() {
            return head.hashCode();
        }

        @Override
        public int compareTo(Path o) {
            return totalCost - o.totalCost;

        }

        public Path add(Point point, int cost) {
            Path p = new Path();
            p.head = point;
            p.totalCost = totalCost + cost;
            p.length = length + 1;
            p.parent = this;
            return p;
        }
    }
}

2

Sıçramak, Python 2

Özellikle çığır açan değil, ancak tamam-ish yaptı benim tek girişimi.

class LeapForward(Player):
  def __init__(self):
    Player.__init__(self)
    self.coords = [Coordinate( 1, 0),
                   Coordinate( 1,-1),
                   Coordinate( 1, 1)]
    self.n_moves = len(self.coords)

  def turn(self):
    notOKColors = [self.bit_chunk(4*n,4) for n in range(4,8)]
    notOKMap = [Coordinate(x-2,y-2) for x in range(0,5) for y in range(0,5) if self.vision[y][x] not in notOKColors]
    goTo = [c for c in self.coords if c in notOKMap]
    if not goTo:
      goTo = [Coordinate(1,0)]
    return random.choice(goTo)

Temel olarak, genomda, önlemek için dört renk (her 4 bit) kodlar. Sonra o listede olmayan bir renge gider. Tüm renkler kötüyse, hala bilinmeyene doğru atlar.


Muhtemelen buna "RedQueen" demeliydim :)
plannapus

1

Java - IAmARobotPlayer - Puan 3.7

Bu robot faresini daha önce yaptığım başka bir programla (şu ana kadar ilginç olmayan) karşılaştırmak için yaptım. Genel olarak iyi puan alamaz ancak bir yere puan verirse, birçok fareye rastlar. Buradaki fikir sadece önündeki üç hücreye bakacağı, her bir hücrenin iyi veya kötü olduğu. Bu ikili bir sayı verir. Daha sonra bu sayıyı genomunda arayacak, ardışık üç biti alacak, aynı zamanda onları bir sayıya çevirecek ve bu sayı altında saklanan eylemi gerçekleştirecektir. Dolayısıyla aynı durumla karşılaştığında her zaman aynı şekilde hareket eder.

package game.players;
import java.awt.*;
import java.util.Map;
public class IAmARobotPlayer extends Player{
    private static final Point[] possibleMoves = {new Point(1,-1), new Point(1,0), new Point(1,1), new Point(0,-1), new Point(0,1), new Point(1,-1), new Point(1,0), new Point(1,1)};
    private int isGood(int pos,Map<Point,Integer> vision, char[] genomeChar){
        int value = vision.get(new Point(1,pos));
        if(value ==-1){
            return 0;
        } else {
            return genomeChar[84+value]-'0';
        }
    }

    @Override
    public Point takeTurn(String genome, Map<Point, Integer> vision) {

        char[] genomeChar = genome.toCharArray();
        int situation = 4*isGood(1,vision,genomeChar)+2*isGood(0,vision,genomeChar)+1*isGood(-1,vision,genomeChar);
        int reaction = 4*(genomeChar[3*situation+0]-'0')+2*(genomeChar[3*situation+1]-'0')+1*(genomeChar[3*situation+2]-'0');
        return possibleMoves[reaction];

    }
}

Sonuç:

Individual scores: 1, 1, 332, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 47560, 15457, 1, 
Your final score is 3.7100115087136234

1

Dikkatli Örnekler - C ++ - 200 koşuda 2030 hakkında puanlar

Bu, Blind Faith'den kodlayan DNA'nın renk kısmını (16x4 bit) kullanır ancak DNA'nın geri kalanını (36 bit) tamamen kullanılmaz halde bırakır.

Bir rengin kodlaması ya:

  • 10XX - güvenli kareler için;
  • 11XX - ölümcül kareler için; ve
  • 0000 - 0111 - 8 tip tuzak kareleri için.

X'in kullanılmayan bitleri gösterdiği yerde. Yalnızca 16 renkten 2 renginin, bitlerinin 4'ünü de kullanacak tuzaklar olduğu düşünülürse (ve yalnızca tuzak ofset olduğunda, ki bu 9'un 9 katı olacak), o zaman genellikle 64 kullanılmamış bit olacak - Teori bu kullanılmayan bitlerin herhangi birini etkileyen mutasyonların genomu bozmayacağı ve kararlılığın kalan bitleri kullanabilen herhangi bir fantezi çözümünden daha iyi olacağıdır.

Örnekler daha sonra bunu, kendileri merkezli 7x7 ızgara içinde (5x5 vizyonu her iki tarafta 1 kare artı ofset tuzaklarına izin vermek için her karede 1 kare) güvenli bir rota planlamak için kullanırlar.

Başlangıçta bazı kontrollerde inşa etmeye başladım, numunenin şu anda üzerinde durduğu rengin ölümcül olmadığından emin olmak ve herhangi bir hatalı rengi UNSURE güvenliğinin kareleri olarak işaretlemek (ve onların bitişik kareleri) - önemli bu kareleri GÜVENLİ olarak işaretlemek ve birkaç örnek daha öldürmekle kıyaslandığında çok az kazanç için komplikasyon. Zamanım olursa buna geri döneceğim.

#include <initializer_list>
#include <vector>

enum class D { SAFE, LETHAL,TRAP_N, TRAP_NE, TRAP_E, TRAP_SE, TRAP_S, TRAP_SW, TRAP_W, TRAP_NW, UNSURE };
enum class X { SAFE, LETHAL, UNSURE };

inline void checkLocation( color_t color, D (&dna)[16], D check )
{
    if ( color != OUT_OF_BOUNDS && dna[color] == check )
        dna[color] = D::UNSURE;
}

inline void updateMapLocation( X (&map)[7][7], unsigned int x, unsigned int y, const X& safety ){
    if (        ( safety == X::LETHAL && map[x][y] != X::LETHAL )
            || ( safety == X::UNSURE && map[x][y] == X::SAFE ) )
        map[x][y] = safety;
}

inline unsigned int isSafePath( X (&map)[7][7], coord_t p )
{
    return map[p.x][p.y] == X::SAFE ? 1 : 0;
}
inline unsigned int isSafePath(X (&map)[7][7],coord_t p,coord_t q,coord_t r){
    if ( isSafePath( map,p ) )
        if ( isSafePath( map, q ) )
            return isSafePath( map, r );
    return 0;
}

inline unsigned int isSafeEast( X (&map)[7][7], coord_t p )
{
    if ( !isSafePath( map, p ) )
        return 0;
    if ( p.x == 6 )
        return 1;
    return isSafeEast(map,{p.x+1,p.y-1})
            +isSafeEast(map,{p.x+1,p.y+0})
            +isSafeEast(map,{p.x+1,p.y+1});
}

template<typename T> inline T max(T a,T b){return a>=b?a:b;}
template<typename T, typename... A> inline T max(T a,T b,A... c){return max(max(a,b),c...); }

coord_t cautiousSpecimins( dna_t d, view_t v ) {
    X map[7][7] = { { X::SAFE } };
    D dna[16] = { D::UNSURE };
    for ( color_t i = 0; i < 16; i++ )
    {
        if ( d[4*i] == 1 )
        {
            dna[i] = d[4*i + 1] == 1 ? D::LETHAL : D::SAFE;
        }
        else
        {
            switch ( dnarange( d, 4*i + 1, 3 ) )
            {
                case 0: dna[i] = D::TRAP_N; break;
                case 1: dna[i] = D::TRAP_NE; break;
                case 2: dna[i] = D::TRAP_E; break;
                case 3: dna[i] = D::TRAP_SE; break;
                case 4: dna[i] = D::TRAP_S; break;
                case 5: dna[i] = D::TRAP_SW; break;
                case 6: dna[i] = D::TRAP_W; break;
                case 7: dna[i] = D::TRAP_NW; break;
                default: dna[i] = D::UNSURE; break;
            }
        }
    }
    if ( v(-1, 0) != OUT_OF_BOUNDS )
        checkLocation( v( 0, 0), dna, D::LETHAL );

    if ( v(-1, 0) != OUT_OF_BOUNDS )
        for ( unsigned int y = 0; y < 7; ++ y )
            map[2][y] = X::LETHAL;

    if ( v(-2, 0) != OUT_OF_BOUNDS )
        for ( unsigned int x = 0; x < 2; ++x )
            for ( unsigned int y = 0; y < 7; ++ y )
                map[x][y] = X::LETHAL;

    if ( v( 0, 1) == OUT_OF_BOUNDS )
        for ( unsigned int x = 0; x < 7; ++x )
                map[x][4] = X::LETHAL;

    if ( v( 0, 2) == OUT_OF_BOUNDS )
        for ( unsigned int x = 0; x < 7; ++x )
            for ( unsigned int y = 5; y < 7; ++ y )
                map[x][y] = X::LETHAL;

    if ( v( 0,-1) == OUT_OF_BOUNDS )
        for ( unsigned int x = 0; x < 7; ++x )
                map[x][2] = X::LETHAL;

    if ( v( 0,-2) == OUT_OF_BOUNDS )
        for ( unsigned int x = 0; x < 7; ++x )
            for ( unsigned int y = 0; y < 2; ++ y )
                map[x][y] = X::LETHAL;

    checkLocation( v( 1, 1), dna, D::TRAP_SW );
    checkLocation( v( 1, 0), dna, D::TRAP_W  );
    checkLocation( v( 1,-1), dna, D::TRAP_NW );
    checkLocation( v( 0,-1), dna, D::TRAP_N  );
    checkLocation( v(-1,-1), dna, D::TRAP_NE );
    checkLocation( v(-1, 0), dna, D::TRAP_E  );
    checkLocation( v(-1, 1), dna, D::TRAP_SE );
    checkLocation( v( 0, 1), dna, D::TRAP_S  );

    for ( int x = 1; x <= 5; ++x )
    {
        for ( int y = 1; y <= 5; ++y )
        {
            switch( dna[v(x-3,y-3)] )
            {
                case D::LETHAL : updateMapLocation( map, x+0, y+0, X::LETHAL ); break;
                case D::TRAP_N : updateMapLocation( map, x+0, y+1, X::LETHAL ); break;
                case D::TRAP_NE: updateMapLocation( map, x+1, y+1, X::LETHAL ); break;
                case D::TRAP_E : updateMapLocation( map, x+1, y+0, X::LETHAL ); break;
                case D::TRAP_SE: updateMapLocation( map, x+1, y-1, X::LETHAL ); break;
                case D::TRAP_S : updateMapLocation( map, x+0, y-1, X::LETHAL ); break;
                case D::TRAP_SW: updateMapLocation( map, x-1, y-1, X::LETHAL ); break;
                case D::TRAP_W : updateMapLocation( map, x-1, y+0, X::LETHAL ); break;
                case D::TRAP_NW: updateMapLocation( map, x-1, y+1, X::LETHAL ); break;
//              case D::UNSURE : updateMapLocation( map, x+0, y+0, X::SAFE );
//                               updateMapLocation( map, x+0, y+1, X::UNSURE );
//                               updateMapLocation( map, x+1, y+1, X::UNSURE );
//                               updateMapLocation( map, x+1, y+0, X::UNSURE );
//                               updateMapLocation( map, x+1, y-1, X::UNSURE );
//                               updateMapLocation( map, x+0, y-1, X::UNSURE );
//                               updateMapLocation( map, x-1, y-1, X::UNSURE );
//                               updateMapLocation( map, x-1, y+0, X::UNSURE );
//                               updateMapLocation( map, x-1, y+1, X::UNSURE );
//                               break;
                default        : break;
            }           
        }
    }

    unsigned int north = isSafeEast(map,{4,4});
    unsigned int east  = isSafeEast(map,{4,3});
    unsigned int south = isSafeEast(map,{4,2});
    unsigned int mx    = max( north, east, south );
    unsigned int sz;
    std::vector<coord_t> dir;
    if ( mx > 0 )
    {
        if ( north == mx ) dir.push_back( {+1,+1} );
        if ( east  == mx ) dir.push_back( {+1,+0} );
        if ( south == mx ) dir.push_back( {+1,-1} );

        return dir[v.rng.rint(dir.size())];
    }


    north = isSafePath(map,{4,4},{5,5},{5,6})
            + isSafePath(map,{4,4},{4,5},{5,6});
    south = isSafePath(map,{4,2},{5,1},{5,0})
            + isSafePath(map,{4,2},{4,1},{5,0});
    mx = max( north, south );
    if ( mx > 0 )
    {
        if ( north == mx ) dir.push_back( {+1,+1} );
        if ( south == mx ) dir.push_back( {+1,-1} );

        return dir[v.rng.rint(dir.size())];
    }

    north = isSafePath(map,{3,4},{4,5},{5,6});
    south = isSafePath(map,{3,2},{4,1},{5,0});
    mx = max( north, south );
    if ( mx > 0 )
    {
        if ( north == mx ) dir.push_back( {+0,+1} );
        if ( south == mx ) dir.push_back( {+0,-1} );

        return dir[v.rng.rint(dir.size())];
    }

    north = 2*isSafePath(map,{4,4},{4,5},{4,6})
            + 1*isSafePath(map,{4,4},{3,5},{4,6});
    south = 2*isSafePath(map,{4,2},{4,1},{4,0})
            + 1*isSafePath(map,{4,2},{3,1},{4,0});
    mx = max( north, south );
    if ( mx > 0 )
    {
        if ( north == mx ) dir.push_back( {+1,+1} );
        if ( south == mx ) dir.push_back( {+1,-1} );

        return dir[v.rng.rint(dir.size())];
    }

    north = isSafePath(map,{3,4},{4,5},{4,6})
            + isSafePath(map,{3,4},{3,5},{4,6});
    south = isSafePath(map,{3,2},{4,1},{4,0})
            + isSafePath(map,{3,2},{3,1},{4,0});
    mx = max( north, south );
    if ( mx > 0 )
    {
        if ( north == mx ) dir.push_back( {+0,+1} );
        if ( south == mx ) dir.push_back( {+0,-1} );

        return dir[v.rng.rint(dir.size())];
    }

    north = isSafePath(map,{2,4},{3,5},{4,6});
    south = isSafePath(map,{2,2},{3,1},{4,0});
    mx = max( north, south );
    if ( mx > 0 )
    {
        if ( north == mx ) dir.push_back( {-1,+1} );
        if ( south == mx ) dir.push_back( {-1,-1} );

        return dir[v.rng.rint(dir.size())];
    }

    north = isSafePath(map,{3,4},{3,5},{3,6})
            + isSafePath(map,{3,4},{2,5},{3,6});
    south = isSafePath(map,{3,2},{3,1},{3,0})
            + isSafePath(map,{3,2},{2,1},{3,0});
    mx = max( north, south );
    if ( mx > 0 )
    {
        if ( north == mx ) dir.push_back( {+0,+1} );
        if ( south == mx ) dir.push_back( {+0,-1} );

        return dir[v.rng.rint(dir.size())];
    }

    north = isSafePath(map,{2,4},{3,5},{4,6});
    south = isSafePath(map,{2,2},{3,1},{4,0});
    mx = max( north, south );
    if ( mx > 0 )
    {
        if ( north == mx ) dir.push_back( {-1,+1} );
        if ( south == mx ) dir.push_back( {-1,-1} );

        return dir[v.rng.rint(dir.size())];
    }

    return {-1,-1};
}

Örnek Puanlar:

Scores: 421155 2 129418 71891 90635 1 211 1111987 29745 7 2200750 41793 50500 45 2012072 2 485698 1 110061 1554720 210308 249336 2 1 262110 17 3 19 1719139 23859 45118 3182784 318 2 1 15572 14 2822954 18 11 2 3 15954 1331392 2296280 135015 1 360826 1 692367 4 244775 4814645 3749144 3 1 660000 1 11 3688002 3920202 3428464 123053 1 243520 86 9 6 289576 195966 549120 220918 9 1 43 71046 5213 118177 150678 54639 3 200839 1 3 6 1978584 1514393 119502 1 1 137695 184889 337956 1 1 441405 133902 991 1 4137428 1 1427115 3340977 1 2 1 55559 11 1 94886 30270 1 6 3 69394 264780 6877 47758 128568 1 116672 130539 163747 96253 1 2654354 1 141 58212 1613661 27 9504 1 2474022 843890 1 59 3110814 2353731 150296 313748 2590241 6 5970407 1434171 2 334715 141277 1 56810 2964306 51544 61973 715590 1 106 900384 50948 2 34652 108096 391006 1 2969764 47625 1 24 30481 44 8 1 18 2094036 106461 3080432 75 620651 16 71730 282145 275031 17 1 8 15 121731 18 2 1 1 495868 3252390 6 1 63712 7 3733149 13380 1 1
Geometric mean score: 2030.17

Test sırasındaki maksimum puan: 8,150,817 kaydedilmiş örnekler.


Şimdi yaptın ... Ben daha sonra yamayı kurtarmak istedim, ama temkinli kemirgenlerini tartışmasız bırakamadım :) Göründüğü gibi, yahni daha verimli bir kodlama ile daha iyi çalışıyor. Yama alanını 7x7'ye genişletme fikriniz de umut verici görünüyor. Bunu kullanıp kullanamayacağımı göreceğim.

Şu anda bunun için 2000 koşuya gidiyorum ... ilk 900'dan sonra ortalama, 600'den uzaklaşıyor gibi görünüyor, ki bu, 2000'den oldukça uzak. 2000'in olup olmadığını görmek için, sonunda tekrardan çeker misiniz? sadece bir şans
Martin Ender
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.