Lab Rat Race: latihan dalam algoritma genetika


113

Ini adalah Tantangan Fortnightly # 3. Tema: Algoritma Genetika

Tantangan ini sedikit percobaan. Kami ingin melihat apa yang bisa kami lakukan, berdasarkan tantangan, dengan algoritma genetika. Tidak semuanya mungkin optimal, tetapi kami mencoba yang terbaik untuk membuatnya dapat diakses. Jika ini berhasil, siapa yang tahu apa yang mungkin kita lihat di masa depan. Mungkin genetik King of the Hill?

Speknya cukup panjang! Kami telah mencoba memisahkan spec ke dalam The Basics - minimum yang perlu Anda ketahui untuk mulai bermain dengan framework dan mengirimkan jawaban - dan The Gory Details - spec lengkap, dengan semua detail tentang controller, berdasarkan mana Anda bisa menulis sendiri
Jika Anda memiliki pertanyaan apa pun, silakan bergabung dengan kami di obrolan!

Anda seorang peneliti dalam psikologi perilaku. Ini Jumat malam dan Anda dan kolega Anda memutuskan untuk bersenang-senang dan menggunakan tikus lab Anda untuk balapan tikus kecil. Faktanya, sebelum kita terlalu terikat secara emosional dengan mereka, mari kita sebut mereka spesimen .

Anda telah menyiapkan trek balap kecil untuk spesimen, dan untuk membuatnya lebih menarik, Anda telah meletakkan beberapa dinding dan perangkap serta teleporter di sepanjang trek. Sekarang, spesimen Anda masih tikus ... mereka tidak tahu apa itu jebakan atau teleporter. Yang mereka lihat adalah beberapa hal dalam berbagai warna. Mereka juga tidak memiliki memori apa pun - yang dapat mereka lakukan hanyalah membuat keputusan berdasarkan lingkungan mereka saat ini. Saya kira seleksi alam akan memilih spesimen yang tahu bagaimana menghindari jebakan dari yang tidak (perlombaan ini akan memakan waktu ...). Biarkan game dimulai!

Contoh gambar papan yang digunakan

† 84.465 spesimen terluka dalam pembuatan tantangan ini.

Dasar

Ini adalah permainan pemain tunggal (Anda dan kolega Anda tidak ingin mencampuradukkan populasi sehingga masing-masing membangun trek balap mereka sendiri). Jalur balap adalah kotak persegi panjang, tinggi 15 sel dan lebar 50 sel. Anda mulai dengan 15 spesimen pada sel acak (tidak harus berbeda) di tepi kiri (di mana x = 0 ). Spesimen Anda harus mencoba mencapai tujuan yang merupakan sel mana pun pada x ≥ 49 dan 0 ≤ y ≤ 14 (spesimen dapat melampaui jejak ke kanan). Setiap kali ini terjadi, Anda mendapat poin. Anda juga memulai permainan dengan 1 poin. Anda harus mencoba memaksimalkan poin Anda setelah 10.000 putaran.

Beberapa spesimen dapat menempati sel yang sama dan tidak akan berinteraksi.

Pada setiap belokan, setiap spesimen melihat kisi 5x5 di sekelilingnya (dengan sendirinya di tengah). Setiap sel grid yang akan berisi warna -1untuk 15. -1mewakili sel yang di luar batas. Spesimen Anda mati jika bergerak di luar batas. Sedangkan untuk warna lain, mereka mewakili sel kosong, perangkap, dinding dan teleporter. Tetapi spesimen Anda tidak tahu warna mana yang mewakili apa dan Anda juga tidak. Namun ada beberapa kendala:

  • 8 warna akan mewakili sel kosong.
  • 4 warna akan mewakili teleporter. Teleporter akan mengirim spesimen ke sel tertentu dalam lingkungan 9x9. Offset ini akan sama untuk semua teleporter dengan warna yang sama.
  • 2 warna akan mewakili dinding. Pindah ke dinding sama dengan berdiri diam.
  • 2 warna akan mewakili jebakan. Jebakan menunjukkan bahwa salah satu dari 9 sel di lingkungan terdekatnya adalah mematikan (tidak harus sel jebakan itu sendiri). Offset ini akan sama untuk semua jebakan dengan warna yang sama.

Sekarang, tentang seleksi alam ... setiap spesimen memiliki genom, yang merupakan angka dengan 100 bit. Spesimen baru akan dibuat dengan mengembangbiakkan dua spesimen yang ada, dan kemudian sedikit bermutasi genom. Semakin sukses suatu spesimen, semakin besar peluangnya untuk bereproduksi.

Jadi, inilah tugas Anda : Anda akan menulis satu fungsi, yang menerima sebagai input kisi warna 5x5 yang dilihat spesimen, serta genomnya. Fungsi Anda akan mengembalikan gerakan (Δx, Δy) untuk spesimen, di mana Δx dan Δy masing-masing akan menjadi satu {-1, 0, 1}. Anda tidak boleh menyimpan data apa pun di antara panggilan fungsi. Ini termasuk menggunakan generator nomor acak Anda sendiri. Fungsi Anda akan dilengkapi dengan RNG yang diunggulkan yang bebas Anda gunakan sesuai keinginan.

Skor kiriman Anda akan menjadi rata - rata geometrik dari jumlah poin di 50 trek acak. Kami telah menemukan bahwa skor ini sedikit berbeda. Karena itu, skor ini akan menjadi permulaan . Setelah tantangan ini mereda, batas waktu akan diumumkan. Pada akhir batas waktu, 100 papan akan dipilih secara acak, dan semua pengiriman akan disimpan kembali di 100 papan ini. Jangan ragu untuk memberikan perkiraan skor pada jawaban Anda, tetapi kami akan menilai sendiri setiap pengiriman untuk memastikan tidak ada yang menipu.

Kami telah menyediakan program pengontrol dalam beberapa bahasa. Saat ini, Anda dapat menulis kiriman Anda dengan Python (2 atau 3), Ruby , C ++ , C # atau Java . Pengontrol menghasilkan papan, menjalankan permainan dan menyediakan kerangka kerja untuk algoritma genetika. Yang harus Anda lakukan adalah menyediakan fungsi bergerak.

Tunggu, jadi apa yang harus saya lakukan dengan genom?

Tantangannya adalah untuk mencari tahu!

Karena spesimen tidak memiliki memori, yang Anda dapatkan pada gilirannya adalah kotak warna 5x5 yang tidak berarti apa-apa bagi Anda. Jadi, Anda harus menggunakan genom untuk mencapai tujuan. Gagasan umum adalah bahwa Anda menggunakan bagian genom untuk menyimpan informasi tentang warna atau tata letak kisi, dan bot Anda mendasarkan keputusannya pada informasi tambahan yang disimpan dalam genom.

Sekarang, tentu saja Anda tidak dapat menyimpan apa pun di sana secara manual. Jadi informasi aktual yang tersimpan di sana pada awalnya akan sepenuhnya acak. Tetapi algoritma genetika akan segera memilih spesimen-spesimen yang genomnya mengandung informasi yang tepat sambil membunuh yang memiliki informasi yang salah. Tujuan Anda adalah menemukan pemetaan dari bit genom dan bidang pandang Anda ke suatu langkah, yang memungkinkan Anda menemukan jalur ke tujuan dengan cepat dan yang secara konsisten berevolusi menjadi strategi kemenangan.

Ini harus menjadi informasi yang cukup untuk memulai. Jika mau, Anda dapat melewati bagian berikutnya, dan pilih pengontrol pilihan Anda dari daftar pengontrol di bagian bawah (yang juga berisi informasi tentang cara menggunakan pengontrol tertentu).

Baca terus jika Anda ingin semua ...

Detail Gory

Spesifikasi ini lengkap. Semua pengendali harus menerapkan aturan ini.

Semua keacakan menggunakan distribusi yang seragam, kecuali dinyatakan sebaliknya.

Pembuatan trek:

  • Lagu tersebut adalah kotak persegi panjang, lebar X = 53 sel dan tinggi Y = 15 sel. Sel dengan x ≥ 49 adalah sel tujuan (di mana x berbasis nol).
  • Setiap sel memiliki warna tunggal dan mungkin atau mungkin tidak mematikan - sel tidak mematikan kecuali ditentukan oleh salah satu jenis sel di bawah ini.
  • Ada 16 warna sel yang berbeda, berlabel dari 0ke 15, yang artinya akan berubah dari satu game ke game lainnya. Selain itu, -1merupakan sel yang berada di luar batas - ini mematikan .
  • Pilih 8 warna acak . Ini akan menjadi sel kosong (yang tidak memiliki efek).
  • Pilih 4 warna lebih acak . Ini adalah teleporter. Untuk dua warna ini, pilih offset non-nol di lingkungan 9x9 (dari (-4, -4) hingga (4,4) kecuali (0,0)). Untuk dua warna lainnya, balikkan offset tersebut. Jika spesimen menginjak teleporter, ia segera dipindahkan oleh offset itu.
  • Pilih 2 warna lebih acak . Ini adalah jebakan. Untuk masing-masing warna ini, pilih offset di lingkungan 3x3 (dari (-1, -1) hingga (1,1)). Jebakan menunjukkan bahwa sel pada offset itu mematikan . Catatan: Sel perangkap itu sendiri belum tentu mematikan.
  • The 2 warna yang tersisa adalah dinding, yang menghambat gerakan. Mencoba untuk pindah ke sel dinding akan mengubah gerakan menjadi diam. Sel-sel dinding sendiri mematikan .
  • Untuk setiap sel non-tujuan dari kisi, pilih warna acak. Untuk setiap sel sasaran pilih warna kosong acak .
  • Untuk setiap sel di tepi kiri lintasan, tentukan apakah tujuan dapat dicapai dalam 100 putaran (sesuai dengan aturan urutan putaran di bawah). Jika demikian, sel ini adalah sel awal yang dapat diterima . Jika kurang dari 10 sel awal, buang trek dan hasilkan yang baru.
  • Buat 15 spesimen, masing-masing dengan genom acak dan usia 0 . Tempatkan setiap spesimen pada sel awal yang acak.

Putar pesanan:

  1. Langkah-langkah berikut akan dilakukan, secara berurutan, untuk setiap spesimen. Spesimen tidak berinteraksi atau melihat satu sama lain, dan dapat menempati sel yang sama.
    1. Jika usia spesimen adalah 100 , ia akan mati. Kalau tidak, tambah umurnya 1.
    2. Spesimen diberi bidang pandang - kotak warna 5x5, berpusat pada spesimen - dan mengembalikan gerakan di lingkungan 3x3. Bergerak di luar rentang ini akan menyebabkan pengontrol berakhir.
    3. Jika sel target adalah dinding, maka bergerak diubah menjadi (0,0).
    4. Jika sel target adalah teleporter, spesimen dipindahkan oleh offset teleporter. Catatan: Langkah ini dilakukan satu kali , bukan secara iteratif.
    5. Jika sel saat ini ditempati oleh spesimen (berpotensi setelah menggunakan satu teleporter) mematikan , spesimen mati. Ini adalah satu - satunya waktu spesimen mati (terlepas dari langkah 1.1. Di atas). Secara khusus, spesimen baru yang memunculkan sel yang mematikan tidak akan langsung mati, tetapi memiliki kesempatan untuk pindah dari sel berbahaya terlebih dahulu.
    6. Jika spesimen menempati sel tujuan, skor poin, pindahkan spesimen ke sel awal acak dan setel ulang umurnya ke 0.
  2. Jika ada kurang dari dua spesimen yang tersisa di papan, permainan berakhir.
  3. Buat 10 spesimen baru dengan usia 0 . Setiap genom ditentukan (secara individu) oleh aturan pemuliaan di bawah ini. Tempatkan setiap spesimen pada sel awal yang acak.

Pembiakan:

  • Ketika spesimen baru dibuat pilih dua orang tua yang berbeda secara acak, dengan bias terhadap spesimen yang telah berkembang lebih jauh ke kanan. Probabilitas spesimen yang akan dipilih sebanding dengan skor kebugaran saat ini . Skor kebugaran spesimen adalah

    1 + x + 50 * berapa kali mencapai tujuan

    di mana x adalah indeks horisontal berbasis 0. Spesimen yang dibuat pada gilirannya yang sama tidak dapat dipilih sebagai orang tua.

  • Dari dua orang tua, pilih satu yang acak untuk mengambil bit genom pertama.

  • Sekarang saat Anda berjalan di sepanjang genom, alihkan orang tua dengan probabilitas 0,05 , dan terus ambil bit dari orang tua yang dihasilkan.
  • Mutasikan genom yang dirakit lengkap: untuk setiap bit, balikkan dengan probabilitas 0,01 .

Mencetak:

  • Satu pertandingan berlangsung 10.000 putaran.
  • Pemain memulai permainan dengan 1 poin (untuk memungkinkan penggunaan mean geometrik).
  • Setiap kali spesimen mencapai tujuan, pemain mendapat skor.
  • Untuk saat ini, pengiriman masing-masing pemain akan dijalankan selama 50 pertandingan, masing-masing dengan trek acak yang berbeda.
  • Pendekatan di atas menghasilkan lebih banyak variasi daripada yang diinginkan. Setelah tantangan ini mereda, batas waktu akan diumumkan. Pada akhir tenggat waktu, 100 papan akan dipilih secara acak, dan semua pengiriman akan disimpan di 100 papan ini.
  • Skor keseluruhan pemain adalah rata - rata geometrik dari skor masing-masing game ini.

Pengendali

Anda dapat memilih salah satu dari pengontrol berikut (karena mereka secara fungsional setara). Kami telah menguji semuanya, tetapi jika Anda menemukan bug, ingin meningkatkan kode atau kinerja, atau menambahkan fitur seperti output grafis, silakan kirim menimbulkan masalah atau mengirim permintaan tarik di GitHub! Anda juga dapat menambahkan pengontrol baru dalam bahasa lain!

Klik nama bahasa untuk setiap pengontrol untuk sampai ke direktori yang benar di GitHub, yang berisi README.mddengan petunjuk penggunaan yang tepat.

Jika Anda tidak terbiasa dengan git dan / atau GitHub, Anda dapat mengunduh seluruh repositori sebagai ZIP dari halaman depan (lihat tombol di bilah sisi).

Python

  • Paling teruji. Ini adalah implementasi referensi kami.
  • Bekerja dengan Python 2.6+ dan Python 3.2+!
  • Sangat lambat. Kami sarankan menjalankannya dengan PyPy untuk mempercepat.
  • Mendukung output grafis menggunakan salah satu pygameatau tkinter.

Rubi

  • Diuji dengan Ruby 2.0.0. Harus bekerja dengan versi yang lebih baru.
  • Ini juga cukup lambat, tetapi Ruby mungkin nyaman untuk membuat prototipe ide untuk pengiriman.

C ++

  • Membutuhkan C ++ 11.
  • Secara opsional mendukung multithreading.
  • Sejauh ini pengontrol tercepat dalam kelompok itu.

C #

  • Menggunakan LINQ, sehingga membutuhkan .NET 3.5.
  • Agak lambat.

Jawa

  • Tidak terlalu lambat. Tidak terlalu cepat.

Papan Awal Pendahuluan

Semua skor bersifat sementara. Namun demikian, jika ada sesuatu yang salah atau kedaluwarsa, beri tahu saya. Pengajuan contoh kami terdaftar untuk perbandingan, tetapi tidak dalam pertentangan.

  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

Kredit

Tantangan ini adalah upaya kolaborasi yang sangat besar:

  • Nathan Merril: Menulis pengontrol Python dan Java. Mengubah konsep tantangan dari King-of-the-Hill menjadi Balap Tikus.
  • trichoplax: Playtesting. Bekerja pada pengontrol Python.
  • feersum: Menulis kontroler C ++.
  • VisualMelon: Menulis kontroler C #.
  • Martin Büttner: Konsep. Menulis pengontrol Ruby. Playtesting. Bekerja pada pengontrol Python.
  • T Abraham: Playtesting. Diuji Python dan ditinjau C # dan C ++ controller.

Semua pengguna di atas (dan mungkin beberapa lagi saya lupa) telah berkontribusi pada keseluruhan desain tantangan.

Pembaruan pengontrol C ++

Jika Anda menggunakan C ++ dengan Visual Studio dan multithreading, Anda harus mendapatkan pembaruan terbaru karena bug dengan seeding generator nomor acak mereka yang memungkinkan papan duplikat untuk diproduksi.


3
Tidak bisakah seseorang membuat algoritma genetika genetika untuk menemukan algoritma genetika yang optimal untuk masalah ini?
mbomb007

1
@ anon3202 Ya, tentu saja itu akan memberi Anda lebih banyak informasi tentang tata letak trek karena Anda dapat mengukur di mana Anda berada. Pada dasarnya, kami ingin menjaga agar antarmuka bot tetap sederhana, dan menjadikannya masalah murni lokal, di mana Anda membutuhkan genom untuk mempelajari solusi lokal mana yang paling bermanfaat bagi kemajuan global Anda.
Martin Ender

1
@matovitch Lihat bagian 5 dari urutan Hidupkan bagian dari Rincian Gory (full spec):'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.'
trichoplax

1
Saya mengubah kode C ++ untuk menunjukkan mean sampel, stddev, stderr, dan 99% conf-interval, (sebelum "geometric" log / exp Anda), dan membuat penemuan yang mengejutkan. Jawaban "Blind Faith" memiliki "Sample Mean of 116529 + - 2.78337e + 010 (99%) stddev = 7.77951e + 010" setelah 50 kali berjalan. "Menurunkan interval kepercayaan hingga 50% tidak terlalu meningkatkan masalah sama sekali. Rata-rata geometris lebih stabil: "Rata-rata 159,458 + - 117262 (99%) stddev = 32,6237" (Sebelum pembaruan 800-skornya)
Mooing Duck

1
Saya melakukan beberapa percobaan dengan tingkat mutasi, dan saya pikir tantangannya akan lebih menarik (dan pengendali akan berjalan jauh lebih cepat) jika probabilitas dinaikkan dari 0,01 menjadi 0,0227, yang memberikan DNA peluang 10% untuk dilalui mutasi tidak berubah, bukan 37% dengan nilai saat ini. Ini menghindari ledakan populasi yang konyol (yang pada gilirannya menghemat banyak waktu perhitungan) dan mencegah banyak kegagalan karena keragaman yang tidak memadai. Skor individu lebih rendah, tetapi karena lebih banyak lari menghasilkan pemenang, rata-rata global cenderung meningkat.

Jawaban:


37

Iman buta - C ++ - tampaknya skor di atas 800 (!) Selama 2000 berjalan

Genom pengkodean warna dengan umpan balik trek misterius dan pencegah pukulan dinding yang efektif

#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";
}

Contoh hasil:

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

Berdasarkan pengujian panjang feersum yang tidak sukarela, saya rasa 2000 run sudah cukup untuk menghasilkan hasil yang cukup stabil.
Karena pengontrol saya yang dimodifikasi menampilkan rata-rata geometrik saat ini setelah setiap putaran, saya mengkonfirmasi secara visual bahwa variasi selama 50 putaran terakhir relatif kecil (+ - 10 poin).

Apa yang membuat makhluk ini berdetak

Alih-alih memberikan prioritas yang sama untuk setiap warna, saya mempertimbangkan nilai-nilai yang mungkin ini:

  1. bagus -> tikus berpikir itu bisa pergi dengan aman ke sana
  2. buruk -> tikus tidak akan pergi ke sana
  3. trap -> tikus akan menganggap posisi perangkap buruk dan sel yang menunjukkan perangkap baik .
    Meskipun saya terlalu malas untuk menamainya kembali, ini lebih merupakan "detektor bahaya" yang menunjukkan lokasi (seharusnya) perangkap yang sebenarnya, sebuah tembok, seorang teleporter yang menunggu untuk mengirim pengembara yang tidak curiga ke tempat yang tidak menyenangkan atau bahkan pintu masuk orang mati -akhir. Singkatnya, tempat di mana tikus bijak lebih suka tidak pergi.

gen yang baik atau buruk hanya mengambil 2 bit untuk menyimpan (misalnya 11dan 10), tapi perangkap memerlukan 4 bit ( 0tttdi mana tttmerupakan salah satu yang mungkin 8 lokasi "berbahaya").

Untuk menjaga setiap gen konsisten (yaitu mempertahankan artinya setelah dicampur ke dalam genom yang sama sekali berbeda, yang mengharuskan setiap gen kode warna berada di lokasi tetap), semua nilai dikodekan pada 4 bit (sehingga baik dikodekan sebagai 11xxdan buruk sebagai 10xx), dengan total 16 * 4 = 64 bit.

36 bit yang tersisa digunakan sebagai "anti-wall-bangers" (lebih lanjut tentang itu nanti). 25 warna di sekitarnya di-hash menjadi indeks 36 bit ini. Setiap bit menunjukkan arah vertikal yang disukai (atas atau bawah), yang digunakan ketika ada pilihan yang mungkin antara dua sel.

Strateginya adalah sebagai berikut:

  • mendekode setiap warna sesuai dengan genom (atau laporan pengontrol langsung untuk sel "buruk" di luar jalur)
  • buat peta lingkungan sekitar (3x3 sel, 8 tetangga yang mungkin)
  • menghitung tanda tangan dari lingkungan (hash dari 25 warna kecuali sel off-track)
  • pilih arah vertikal yang disukai dari tanda tangan (di antara 36 ember hash)
  • mencoba untuk pindah ke tetangga yang diisyaratkan sebagai "baik", dimulai dengan yang terdekat dengan tujuan dan pergi ke arah vertikal yang disukai terlebih dahulu
  • jika tidak ada tetangga yang "baik" dapat ditemukan, cobalah untuk memindahkan satu sel ke belakang (sehingga mungkin menjadi korban kecelakaan yang tidak menguntungkan, dan menghindari untuk meningkatkan kebugaran pada tingkat apapun)

Hai tikus, lihatlah musuh-musuh jenismu

dinding yang ditakuti loop teleportasi

Hal terburuk yang dapat terjadi pada suatu populasi adalah belum menghasilkan pemenang, tetapi banyak tikus yang menempel di dinding atau di dalam lingkaran teleportasi tak terbatas yang cukup dekat dengan tujuan untuk memiliki kesempatan dominan dipilih untuk berkembang biak .
Bertentangan dengan tikus yang terjepit dalam perangkap atau dipindahkan ke dinding, hewan pengerat ini hanya akan dibunuh pada usia lanjut.
Mereka tidak memiliki keunggulan kompetitif atas sepupu mereka yang terjebak 3 sel sejak awal, tetapi mereka akan memiliki cukup waktu untuk membiakkan generasi demi generasi kretin sampai genom mereka menjadi dominan, sehingga merusak keragaman genetik dengan buruk tanpa alasan yang jelas.

Untuk mengurangi fenomena ini, idenya adalah untuk membuat keturunan dari tikus-tikus yang buruk dan jahat ini lebih mungkin untuk dihindari mengikuti langkah-langkah nenek moyang mereka.
Indikasi arah vertikal hanya 1 bit panjang (pada dasarnya mengatakan "coba naik atau turun dulu di lingkungan ini"), dan beberapa bit cenderung memiliki efek pada jalur yang diikuti, sehingga mutasi dan / atau crossover harus memiliki dampak signifikan.
Banyak keturunan akan memiliki perilaku yang berbeda dan tidak akan membenturkan kepala mereka pada dinding yang sama (di antara mayat leluhur mereka yang kelaparan).
Subtelty di sini adalah bahwa indikasi ini bukan faktor dominan dalam perilaku tikus. Interpretasi warna akan tetap berlaku dalam banyak kasus (pilihan naik / turun hanya akan berarti jika memang ada dua "baik"dan apa yang dilihat tikus sebagai warna yang tidak berbahaya bukanlah seorang teleporter yang menunggu untuk melemparkannya ke dinding).

Mengapa ini (tampaknya) berhasil?

Saya masih tidak tahu persis mengapa.

Sentuhan absolut keberuntungan yang tetap menjadi misteri yang belum terpecahkan adalah logika pemetaan perangkap. Tanpa diragukan lagi itu adalah landasan kesuksesan, tetapi ia bekerja dengan cara misteriusnya sendiri.

Dengan pengkodean yang digunakan, genom acak akan menghasilkan 25% pengidentifikasi warna "baik", 25% "buruk" dan 50% "perangkap".
pengidentifikasi "jebakan" pada gilirannya akan menghasilkan estimasi "baik" dan "buruk" berkorelasi dengan lingkungan 5x5.
Akibatnya, tikus di lokasi tertentu akan "melihat" dunia sebagai campuran dari warna "go / no go" yang stabil dan kontekstual.

Seperti yang ditunjukkan oleh mekanisme anti-banging yang cukup berhasil, elemen terburuk di trek adalah dinding yang ditakuti (dan sepupunya loop teleportasi, tapi saya kira ini jauh lebih jarang terjadi).

Kesimpulannya adalah, program yang berhasil harus di atas segalanya berhasil untuk mengembangkan tikus yang mampu mendeteksi posisi yang akan menyebabkan kelaparan lambat tanpa mencapai tujuan.

Bahkan tanpa "menebak" dua warna yang mewakili dinding, warna "perangkap" tampaknya berkontribusi pada penghindaran dinding dengan membiarkan tikus melewati beberapa rintangan bukan karena "melihat" dinding, tetapi karena estimasi "perangkap" mengesampingkan ini. sel-sel dinding tertentu di lingkungan tertentu ini.

Meskipun tikus mencoba bergerak ke arah tujuan (yang mungkin mengarah pada pemikiran bahwa indikator perangkap yang paling "berguna" adalah yang mengindikasikan bahaya di depan), saya pikir semua arah perangkap memiliki pengaruh yang hampir sama: perangkap yang mengindikasikan "bahaya di belakang "Terletak 2 sel di depan tikus memiliki pengaruh yang sama dengan yang menunjukkan" bahaya di depan "ketika tikus berdiri tepat di atasnya.

Sayangnya, mengapa campuran ini memiliki properti untuk membuat genome menyatu dengan sukses adalah jauh melampaui matematika saya, sayangnya.

Saya merasa lebih nyaman dengan alat penangkis-tembok. Ini hanya bekerja sesuai rencana, meskipun jauh di atas harapan saya (skor pada dasarnya dikalikan dengan empat).

Saya meretas controller untuk menampilkan beberapa data. Berikut ini beberapa langkah:

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

Di sini berkembang biak tikus super muncul lebih awal (jalur mungkin diizinkan berjalan dalam garis lurus dan beberapa tikus yang beruntung pada generasi pertama memiliki DNA yang tepat untuk mengambil keuntungan darinya). Jumlah spesimen pada akhirnya adalah sekitar setengah dari max teoritis dari beberapa 100.000 tikus, yang berarti hampir setengah makhluk memperoleh kemampuan untuk bertahan hidup jalur khusus ini tanpa batas (!).
Tentu saja skor yang dihasilkan hanya cabul - seperti waktu perhitungan, omong-omong.

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

Di sini kita bisa melihat perbaikan genom di tempat kerja. Silsilah antara dua genom terakhir muncul dengan jelas. The baik dan buruk evaluasi adalah yang paling signifikan. The perangkap indikasi tampaknya berosilasi sampai mereka menstabilkan ke "berguna" perangkap atau bermutasi menjadi baik atau buruk .

Tampaknya gen warna memiliki beberapa karakteristik bermanfaat:

  • mereka memiliki makna mandiri
    (warna tertentu harus ditangani dengan cara tertentu).
    Setiap pengkodean warna dapat dilemparkan ke dalam genom yang sama sekali berbeda tanpa mengubah perilaku secara dramatis - kecuali jika warna tersebut ternyata merupakan fakta yang menentukan (biasanya dinding atau teleporter yang mengarah ke loop tak terbatas).
    Ini kurang demikian dengan pengkodean prioritas dasar, karena warna yang paling utama adalah satu-satunya informasi yang digunakan untuk memutuskan ke mana harus pindah. Di sini semua warna "baik" sama, sehingga warna yang diberikan ditambahkan ke daftar "baik" akan memiliki dampak yang lebih kecil.
  • mereka relatif tangguh terhadap mutasi
    , pengkodean baik / buruk hanya memiliki 2 bit signifikan dari 4, dan lokasi perangkap mungkin berubah sebagian besar waktu tanpa mengubah perilaku tikus secara signifikan.
  • mereka kecil (4 bit) sehingga probabilitas untuk dihancurkan oleh crossover sangat rendah.
  • mutasi menghasilkan perubahan berbahaya yang tidak berbahaya
    . Gen yang bermutasi menjadi "baik" akan memiliki sedikit efek (jika misalnya sesuai dengan sel kosong, itu mungkin memungkinkan untuk menemukan jalur baru yang lebih pendek, tetapi itu juga bisa mengarahkan tikus langsung ke perangkap), atau yang dramatis (jika warnanya mewakili dinding, tikus yang baru kemungkinan besar akan terjebak di suatu tempat).
    Gen yang beralih ke "perangkap" akan menghilangkan tikus dari warna esensial atau tidak memiliki efek nyata.
    Mutasi lokasi jebakan hanya akan berarti jika memang ada jebakan (atau sesuatu yang berbahaya) di depan, yang memiliki probabilitas yang relatif kecil (saya akan mengatakan sekitar 1/3).

Terakhir, saya kira 36 bit terakhir berkontribusi tidak hanya untuk menghindari tikus terjebak, tetapi juga untuk menyebarkan tikus lebih merata di trek, sehingga menjaga keragaman genetik sampai genom pemenang muncul dan menjadi dominan melalui bagian kode warna.

Pekerjaan selanjutnya

Saya harus mengatakan saya menemukan makhluk kecil ini menarik.
Sekali lagi terima kasih kepada semua kontributor untuk tantangan luar biasa ini.

Saya berpikir untuk membantai controller lebih jauh untuk menampilkan data yang lebih signifikan, seperti nenek moyang tikus yang sukses.

Saya juga sangat ingin melihat tikus-tikus ini beraksi, tetapi bahasa C ++ b ** ch ini membuat membuat - apalagi menjiwai - gambar (di antara banyak hal lain) tugas yang berantakan.

Pada akhirnya, saya ingin menghasilkan setidaknya penjelasan tentang sistem perangkap, dan mungkin memperbaikinya.

Peretasan pengontrol

Jika seseorang tertarik, saya dapat mempublikasikan modifikasi yang saya buat ke controller.
Mereka kotor dan murah, tetapi mereka melakukan pekerjaan itu.

Saya bukan ahli GitHub, jadi itu harus melalui posting belaka.


16
Mendapat skor 208,14 dengan 10.000 pertandingan. Saya mencoba untuk menguji 1000, tetapi saya tidak pernah menyadari saya telah mengetik 0 ekstra, jadi butuh lebih dari 7 jam.
feersum

LOL terima kasih semuanya. Dibandingkan dengan dua 1000 run saya, sepertinya sekitar 2000 run mungkin menghasilkan hasil yang stabil.

Apa ^^v^vvv^^^vv^^v^vvv^v^^vvvv^^^^^^^^^makna Anda ? Sisanya bisa saya tebak, tetapi saya mengalami masalah dengan bagian itu?
Mooing Duck

Saya sedang merenungkan membuat pengendali "debug" yang terpisah, yang menjalankan satu tikus pada satu waktu, dan setiap kali tikus baru dihasilkan, itu menunjukkan DNA dari kedua orang tua dan anak (melalui beberapa fungsi yang dapat disesuaikan). Itu akan membuatnya jauh lebih mudah untuk memeriksa bagaimana tikus itu bekerja.
Mooing Duck

2
yang mewakili indikator 36 "naik / turun", tetapi dalam contoh-contoh ini DNA pemenang telah menjadi dominan sehingga tidak banyak berubah.

18

Percaya keras - C ++ - (teleporter yang ditingkatkan): 10.000+ untuk 2000 run

(ini adalah evolusi dari keyakinan Buta , jadi Anda mungkin ingin memanjat dinding teks lain sebelum ini)

#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";
}

Episode IV: mendapatkan posisi kita di grid

Hasil

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

Saya beralih ke g ++ / MinGW dan 3 utas.
Kode yang dihasilkan oleh GNU lebih dari dua kali lebih cepat dari Microsoft.
Tidak heran, ada apa dengan implementasi STL mereka yang mengerikan.

Teleporter

Efek teleporter sangat tergantung pada posisi. Sampai sekarang saya senang menganggap teleporter sebagai selalu baik (dilihat sebagai ruang kosong) atau selalu buruk (dilihat sebagai dinding sehingga tidak ada hewan pengerat yang mau menerimanya).

Ini model yang terlalu kasar.
Teleporter yang diberikan dapat mendorong tikus ke depan sampai beberapa sel dari gawang, tetapi begitu ada teleporter yang sama dapat membuang tikus dari papan.
Teleporter seperti itu kemungkinan besar akan diakui sebagai lumayan (karena ia meningkatkan kebugaran lebih cepat daripada ketika "berjalan" ke lokasi x yang sama), menjadi bagian dari genom dominan dan membunuh hampir semua tikus yang mempercayainya sebagai "selalu aman".
Karena tikus tidak memiliki cara untuk mengetahui posisi X mereka, satu-satunya solusi untuk mendeteksi teleporter berbahaya ini adalah memutuskan apakah akan menginjaknya berdasarkan satu-satunya data kontekstual yang tersedia, yaitu kotak warna 5x5.

Untuk melakukannya, saya mendefinisikan 4 jenis gen warna:

  • detektor perangkap bahaya
  • kosong lumayan di mana saja di trek
  • blokir terlarang di mana saja di lintasan
  • balok dilihat sebagai kosong atau blok tergantung pada sekitarnya

Idenya adalah untuk mencoba membedakan teleporter dengan melihat 8 tetangga terdekatnya. Karena kemungkinan memiliki 8 tetangga yang identik di lokasi yang diberikan sangat rendah, yang seharusnya memungkinkan untuk mengidentifikasi contoh unik dari setiap teleporter.

8 warna tetangga dapat dikombinasikan untuk membentuk tanda tangan lokal, yang masing-masing berbeda dengan posisi di labirin. Sayangnya, 8 tetangga hanya terlihat untuk sel yang terletak di dalam bidang penglihatan 3x3 bidang batin, sehingga tanda tangan akan tidak akurat pada tepi bidang penglihatan.
Namun demikian, ini akan memberi kita informasi kontekstual yang konstan di lingkungan terdekat, yang cukup untuk meningkatkan kemungkinan menavigasi teleporter dengan sukses.

gen balok memiliki bidang variabel 2 bit.
Untuk tanda tangan lokal teleporter yang diberikan, ada satu kesempatan dalam empat bahwa sel balok akan dianggap tidak bisa dilewati. Setiap nilai bidang memilih satu dari empat kemungkinan ini.
Akibatnya, mutasi gen berkas pada 2 bit ini akan berputar melalui 4 kemungkinan signifikansi kontekstual dari warna.

Selain itu, warna yang paling penting untuk ditebak adalah dinding dan jebakan. Ini berarti kita harus mengizinkan deteksi teleporter hanya setelah tikus mengetahui di mana dinding dan jebakan berada.

Ini dilakukan dengan memperbarui tanda tangan lokal hanya sesekali. Kriteria saat ini untuk memperbarui tanda tangan lokal adalah berada di dekat warna yang diidentifikasi sebagai teleporter potensial.

Pengkodean menggunakan 5 bit per gen warna dan tipe grup untuk membebaskan 3 bit yang kurang signifikan untuk mengkodekan nilai 0,7:

  • 4 bahaya
  • 4 kosong
  • 4 blok
  • 4 balok

Setiap gen balok memiliki 1/4 peluang untuk dianggap sebagai blok dan 3/4 peluang dianggap kosong, sehingga 4 balok mewakili rata-rata 1 blok dan 3 kosong.

Proporsi rata-rata yang diwakili oleh sebaran acak 16 warna adalah sebagai berikut:

  • 4 bahaya
  • 7 kosong
  • 5 blok

Campuran ini tampaknya memberikan hasil terbaik sejauh ini, tetapi saya belum selesai mengubah-ubahnya.

Mutabilitas gen

Satu hal yang pasti: nilai kode yang dipilih untuk mewakili jenis gen sangat penting. Membalikkan dua nilai dapat menelan biaya 2000 poin atau lebih.

Sekali lagi di sini alasan mengapa di luar matematika saya.

Dugaan saya adalah bahwa probabilitas mutasi dari satu jenis ke yang lain harus seimbang, atau yang lain, seperti dalam matriks Markow, probabilitas kumulatif cenderung membatasi nilai pada subset yang memiliki probabilitas transisi masuk tertinggi.

Menuju penyelamatan

Pathing akan mengurangi jumlah sel yang dikunjungi secara dramatis, memungkinkan untuk menguji hanya yang paling mungkin mengarah ke tujuan. Dengan demikian, tidak hanya jalan buntu yang sering dihindari, tetapi kode warna yang salah juga jauh lebih mungkin ditemukan sebelumnya.
Akibatnya, waktu konvergensi sangat menurun.

Namun, ini tidak membantu menyelesaikan peta di mana genom tidak dapat menghasilkan representasi trek yang tepat.

Apa yang harus dilakukan dengan orang bodoh?

Setelah melihat secara visual di trek, saya mengerti mengapa strategi default yang mencoba untuk bergerak maju bahkan ketika tampaknya tidak ada apa-apa selain dinding di depan memang lebih baik daripada menahan.
"Dinding" sebenarnya bisa menjadi teleporter yang menghasilkan begitu banyak hasil yang tidak menguntungkan sehingga genom memetakannya sebagai hambatan yang tidak pernah dapat diinjak, tetapi pada kesempatan yang jarang terjadi, teleporter nakal ini dapat memiliki efek positif (atau setidaknya tidak mematikan). , jadi mengambil alih-alih kembali meningkatkan kemungkinan menemukan jalan menuju kemenangan.

Konvergensi awal

Menurut saya tingkat mutasi agak sedikit terlalu rendah (setidaknya untuk tikus saya).

Pengaturan 0,01 saat ini memberikan DNA 37% peluang untuk selamat dari proses mutasi secara utuh. Mengubah parameter menjadi 0,0227 menurunkan probabilitas ini menjadi sekitar 10%

Rumus misteriusnya adalah mutasi bit P1 = 1-P seluruh genom utuh 1/100 , 100 menjadi panjang bit genom.

Misalnya untuk probabilitas 10%, mutasi P 1 bit = 1 - 0,1 1/100 = 0,0277
Untuk probabilitas 5%, P = 1 - 0,05 1/100 = 0,0295
Membalik rumus, kami menemukan bahwa 0,01 memberikan peluang 37% untuk menjadi tidak berubah oleh mutasi.

Saya menjalankan kembali tes yang sama persis (menggunakan urutan tetap biji acak) dengan probabilitas 10%.
Pada banyak peta, kegagalan sebelumnya berubah menjadi keberhasilan (terbatas). Di sisi lain, ledakan populasi yang besar lebih sedikit (yang memiliki efek samping yang menarik untuk mempercepat komputasi).
Meskipun skor yang sangat tinggi (satu juta +) kurang umum, jumlah lari yang lebih sukses lebih dari cukup untuk mengimbangi.
Pada akhirnya, rata-rata naik dari 1400+ menjadi sekitar 2000.

Pengaturan P hingga 5%, sebaliknya, menghasilkan rata-rata sekitar 600.
Saya berasumsi tingkat mutasi begitu tinggi sehingga genom tikus yang menang terlalu sering berpindah ke varian yang kurang efisien.

Bagaimana cara kerjanya?

Dengan detektor teleporter yang ditambahkan, jumlah game yang gagal (skor <10) turun secara signifikan.
Pada uji coba 2000 berjalan, hanya ada 1/3 kegagalan.
Rata-rata geometrik hanya naik dari 2900 menjadi 3300, tetapi angka ini gagal mencerminkan peningkatan.

Warna kosong sering ditebak sebagai balok dan bahaya (biasanya 2 hingga 5). Genom "menggunakan" warna-warna ini untuk memblokir jalur yang akan membuat tikus kesulitan.

Genom cukup bagus dalam menebak perangkap (yaitu begitu tikus menjadi mampu mencapai tujuan, warna yang mewakili detektor perangkap aktual ditebak sekitar 90% dari waktu).
Itu juga memanfaatkan kode balok baru untuk para teleporter, meskipun lebih jarang (mungkin karena teleporter "berbahaya" lebih jarang daripada perangkap, dan warna balok / bahaya lainnya berevolusi untuk memblokir jalan ke contoh terakhir dari pengkhianat ini).

Menilai dari jumlah permainan di mana genom pemenang muncul setelah 5.000 putaran atau lebih, saya rasa jenis baru ini akan mendapat banyak manfaat dari peningkatan tingkat mutasi.


Karena ada jumlah genap, kosong, dinding, dan teleport, Anda hanya perlu 3 bit untuk menyimpan proporsi secara akurat (bahkan jika Anda mempertimbangkan perangkap == dinding). Juga, apakah Anda mempertimbangkan / membuang ide untuk menggunakan bit offset perangkap yang tidak digunakan dalam anti-wallbanging? Karena tujuannya adalah untuk tidak mewarisi dari orang tua, Anda sebenarnya bisa menggunakan semua bit dalam anti-wallbanging. Tidak ada alasan bagi mereka untuk menjadi unik, saya tidak akan berpikir.
Mooing Duck

1
@ MoingDuck Saya menguji ide Anda untuk menggunakan bit offset, tetapi gagal. Seperti yang saya khawatirkan, menggunakan kembali informasi untuk dua tujuan berbeda tampaknya tidak berhasil. Asumsikan misalnya bit offset warna yang diberikan diperlukan untuk genom untuk memilih arah vertikal yang tepat dalam jalur yang diberikan, warna ini tidak dapat mewakili jebakan yang berarti lagi tanpa menghancurkan jalur yang tergantung pada data yang sama. Saya juga mencoba menggunakan 6 bit, tetapi karena saya khawatir juga 4 pembentur anti dinding yang tersisa kekurangan pasokan.

1
Baik untuk diketahui, tetapi saya menyarankan dua ide di sana, satu adalah menggunakan semua bit (menggunakan kembali beberapa), dan yang lainnya adalah menggunakan bit offset perangkap yang tidak digunakan untuk dinding / kosong. Apakah Anda mencoba keduanya? (Saya benar-benar mengerti jika Anda tidak ingin mencoba, Anda hampir tidak perlu untuk mencoba jika Anda tidak mau)
Mooing Duck

1
Saya memang mencoba keduanya, dan keduanya gagal. Offset trap sangat penting bahkan ketika sebuah gen tidak menggunakannya, karena gen ini masih dapat bermutasi kembali menjadi warna trap, dalam hal ini trap offset kemungkinan akan bermutasi ke bit konteks apa pun yang paling menguntungkan, dan kehilangan maknanya sebagai offset . Sekarang ia akan bermutasi kembali ke nilai offset yang menguntungkan, dan menghancurkan jalur tikus yang bergantung padanya sebagai indikator kontekstual. Saya pikir saya melihat kasus osilasi dengan alat grafis saya, tetapi tidak mudah untuk menunjukkan contoh yang jelas dari masalah ini.

16

ColorScorePlayer, skor awal ≈ 22

Ini adalah bot yang Anda lihat bekerja di GIF dalam tantangan.

Ini adalah bot pengujian kami sepanjang fase pengembangan. Ini menggunakan genom untuk menyimpan skor kualitas untuk masing-masing 16 warna. Kemudian itu membuat langkah maju yang memindahkannya ke warna dengan skor terbaik (dan tidak pernah bergerak ke -1). Dalam kasus dasi, suatu gerakan acak antara sel-sel yang mengikat diambil.

Kami telah mem-porting pemutar ini ke semua bahasa pengontrol, jadi ini berfungsi sebagai contoh cara menggunakannya:

Python

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)

Rubi

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; 
}

Jawa

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;
    }
}

Skor pemain tidak konsisten. Berikut adalah 50 putaran acak:

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

Tantangan ini benar-benar sangat menyenangkan dan sederhana jika Anda mencobanya.

Jangan tertunda oleh deskripsi panjang.
Cukup kunjungi GitHub dan periksa semuanya ... semuanya akan jauh lebih jelas! :)

Simulator C ++ sangat disarankan untuk kecepatannya. Bahkan setelah saya selesai menerjemahkan program python saya ke C ++, simulasi python masih belum berhenti.

Ini adalah varian yang disempurnakan dari ColorScorePlayer. Untuk memanfaatkan tampilan 5x5 dengan baik, ia mempertimbangkan langkah 2 langkah dari itu menggunakan fungsi tertimbang. Bergerak 1 langkah di depan itu diberi bobot lebih tinggi, karena mereka memiliki efek langsung lebih banyak pada kelangsungan hidup. Bergerak 2 langkah ke depan diberi bobot lebih rendah.

Berusaha untuk bergerak maju, tetapi jika tidak ada langkah aman yang terlihat ... kemudian mencoba ke samping ... dan jika semuanya gagal, bergerak mundur secara acak.

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())];

}

Skor:

Ada sedikit 1 ... yang bisa sedikit menyedihkan ketika Anda melihat konsol memuntahkan 1 setelah satu sama lain. Seperti sebuah planet dengan semua kebutuhan untuk kehidupan, tetapi tidak ada tanda-tanda peradaban tikus maju ...
Lalu lonjakan sesekali. :)

Hmm ... rupanya saya beruntung untuk batch pertama saya berjalan, mendapatkan geometrik 300+. Skor benar-benar berfluktuasi sedikit. Tapi bagaimanapun, dengan lebih banyak menjalankan simulator, itu mungkin lebih dekat ke ≈ 74. (Thx feersum untuk membantu saya mensimulasikan dan programnya yang sangat cepat)

Nilai dari hasil saya: 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 173732 1 1 57376 1 123870 4 1 1 79092 69931 594057 1 69664 5913 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
Saya mendapat rata-rata geometri 74,7 dengan 1000 pertandingan, pekerjaan yang bagus.
feersum

8

Uskup - Python, skor awal 1,901

Uskup selalu bergerak secara diagonal sehingga setengah papan tidak dapat diakses pada perjalanan yang diberikan melintasi papan, tetapi ini berarti lebih sedikit potensi gerakan untuk disandikan, sehingga setiap bit genom dapat mewakili gerakan (Uskup tidak pernah mundur). Bit yang mana untuk merujuk ditentukan berdasarkan blok 3x3 kotak di depan (di sebelah kanan) spesimen. Langkah terbaik untuk situasi tertentu hanya dengan sedikit mutasi saja.

Bot ini awalnya belajar dengan cepat, tetapi kemudian sering mengenai langit-langit sebelum mencapai finish, mungkin di mana salah satu dari dua masalah berikut terjadi:

  • Dua atau lebih bagian dari papan peta ke bit yang sama tetapi memerlukan gerakan yang berbeda.
  • Beberapa papan tidak bisa dilewati hanya dengan menggunakan gerakan diagonal.

Kode

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

Terlepas dari keterbatasan ini, pada kesempatan langka Uskup melakukannya dengan baik, dengan masing-masing spesimen menyelesaikan beberapa putaran papan. Saya berpikir bahwa pada pangkuan tertentu spesimen hanya dapat bergerak di setengah papan (setara dengan hanya kotak hitam atau hanya kotak putih di papan catur). Namun, seperti yang ditunjukkan Martin Büttner, seorang teleporter dapat memindahkan spesimen dari kotak hitam ke kotak putih atau sebaliknya sehingga pada kebanyakan papan mereka tidak akan dibatasi.

(Ada dua pasang tipe teleporter yang cocok dan masing-masing memiliki probabilitas 0,5 untuk memiliki offset yang memindahkan spesimen ke bagian lain dari kotak hitam dan putih. Jadi probabilitas papan memiliki teleporter yang membatasi spesimen hanya pada satu setengah dari papan per putaran hanya 0,25.)

Skor menunjukkan bahwa kemenangan sesekali diselingi dengan periode panjang gagal mencapai finish:

Skor: 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 player: Rata-rata geometri 50,35 (uji 5000-game)

Bot ini mencetak kuadrat berdasarkan warna masing-masing berdasarkan bagian 6-bit dari DNA seperti pemain skor warna, tetapi dengan sistem angka yang berbeda. Bot ini dimotivasi oleh pemikiran bahwa agak sewenang-wenang bahwa salah satu bit mengubah nilai skor dengan 32, sementara yang lain melakukannya dengan hanya 1. Ini menetapkan nilai n (n + 1) / 2 untuk menjalankan n berturut-turut 1 bit. Selain itu, ia menambahkan mekanisme pengacakan dalam upaya untuk menghindari macet. Ini akan membuat langkah maju acak dengan peluang 1 banding 30.

Sebagai perbandingan, pemain skor warna mencetak 30 hingga 35 dalam beberapa tes 1000 pertandingan. Menariknya, skor permainan maksimum pemain warna-skor berada di kisaran 3-5 juta, sementara maksimum run-bonus hanya 200 ribu. Jalankan-bonus manfaat dari sistem penilaian rata-rata logaritmik dengan mendapatkan skor bukan nol lebih konsisten.

Menjalankan 5000 game membutuhkan waktu sekitar 20 menit dengan 6 utas pada pengontrol C ++.

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)]};
}

hanya karena penasaran, berapa lama uji 5000 trek berlangsung? Tikus saya membutuhkan lebih dari satu jam untuk menyelesaikan 1000 trek, jadi saya harus membiarkan komputer berjalan sepanjang malam untuk mereproduksi test case Anda.

@kuroineko Jawaban atas pertanyaan Anda sudah ada dalam jawaban saya.
feersum

oops maaf. Saya akan mencoba kode Anda pada PC saya kemudian, untuk melihat bagian apa yang dimainkan oleh perangkat keras dalam perbedaan kecepatan. Dan mungkin coba gunakan gcc bukan MSVC. Saya perhatikan peningkatan kinerja 30% dari MSVC pada beberapa bit kode yang berat perhitungan lainnya.

Kode Anda berjalan dalam lebih dari 20 menit selama 1000 lagu di i3-2100@3.1GHz saya dengan 4 utas. Skornya sekitar 56 . Tampaknya berarti PC saya 5 kali lebih lambat dari milik Anda dan kode saya akan sekitar 6 kali lebih lambat pada mesin yang diberikan (tetapi memiliki skor yang lebih baik secara mekanis menyiratkan waktu komputasi yang lebih lama). Karena saya terlalu bangkrut untuk membeli PC baru, saatnya untuk sedikit optimasi ...

8

StarPlayer | C ++ | Nilai: 162 (berdasarkan 500 game run)

Pemain ini mencoba menggunakan A * untuk menemukan jalan maju terbaik. Itu memberi bobot dengan cara yang sama seperti ColorScorePlayer dan mencoba untuk menemukan jalannya ke tepi kanan tampilan. Implementasinya bukan yang tercantik yang pernah saya lakukan tetapi setidaknya tidak terlalu lambat.

#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;
}

Skor sampel:

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
Dalam 1000 pertandingan saya mendapat skor 133,2, bagus.
feersum

7

WallGuesser - Mencetak 113.266 dalam tes 1000 pertandingan

Pengkodean

Saya membuat penyandian 6 bit / warna yang sangat sederhana. Untuk memecahkan kode warna [n]

  • Jumlahkan setiap bit ke-9 dalam genom hingga 96
  • Jika skor penjumlahan> = 4 maka katakan kuadrat ini diblokir
  • Jika skor penjumlahan adalah <= 4 maka nilai akhirnya adalah 2 ^ dari nilai penjumlahannya

Dengan menyebarkan bit untuk warna di seluruh genom saya meningkatkan kemungkinan bit dari kedua orang tua akan digunakan untuk setiap warna.

Gerakan

Saya menggunakan (saya yakin tidak sangat efisien) pencarian berbasis * untuk mencari jalur biaya terendah ke salah satu kotak tepi kanan. Jika warna memetakan ke, "diblokir", maka itu tidak akan pernah dimasukkan oleh pencarian. Jika pencarian tidak dapat menemukan jalan, ia menganggap bahwa tikus ini tidak cocok untuk direproduksi dan mencoba untuk mengakhirinya dengan memindahkan satu ke kiri.

Mengurangi jumlah tikus yang tidak layak

Karena genom saya secara efektif menebak kotak mana yang merupakan tikus teleporter dinding atau mundur yang tidak memiliki tebakan (tidak ada warna yang dipetakan untuk diblokir) tidak terlalu cocok. Untuk mencoba dan menghapus tikus-tikus ini jika tidak ada warna yang ditandai sebagai diblokir maka SETIAP warna ditandai sebagai diblokir dan tikus akan selalu bergerak satu ke kiri.

MELAKUKAN

Saat ini tidak ada keacakan dalam perilaku sehingga mudah bagi tikus untuk terjebak.

#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, ini tidak cocok untuk saya g++ -std=c++11 .\wallguesser.cpp -O2 -o .\wallguesser.exe. Saya mendapatkan banyak kesalahan tetapi yang pertama adalah.\wallguesser.cpp:47:19: error: 'dna_t' has no member named 'at' if (d.at(i) == true){
Martin Ender

Tidak masalah, cukup mengubah atuntuk []memperbaikinya.
feersum

7

The FITTEST - Skor rata-rata geometris: ~ 922 (2K berjalan)

Pendekatan saya adalah:

  1. Cari tahu apa yang membunuh spesies dan tentukan perilaku yang diinginkan (fungsional)
  2. Terapkan perilaku yang diinginkan dalam kode (teknis)
  3. Berikan prioritas . Apakah lebih penting atau kurang penting daripada perilaku lain yang diinginkan.
  4. Optimalkan skor rata-rata Geometrik dengan mengutak-atik parameter solusi.

Saya menguji lebih dari 2000 set parameter dengan 50 biji yang sama. Set yang paling menjanjikan dipilih dan diberi skor menggunakan 250 biji identik dan yang dengan peringkat tertinggi adalah input untuk putaran tes berikutnya. Jadi saya berhasil membuat algoritma genetika untuk menemukan algoritma genetika yang optimal untuk masalah ini seperti yang disarankan oleh pengguna mbomb007 .

Perilaku yang diinginkan:

  1. Spesies harus mempelajari warna mana yang aman dan mana yang buruk.
  2. Spesies terutama harus memfokuskan keputusannya ke mana harus bergerak berdasarkan 3 sel tepat di depan, tetapi jika tidak ada gerakan yang baik tersedia, gerakan vertikal atau mundur harus dipertimbangkan
  3. Spesies juga harus melihat apa yang ada di luar 8 sel di sekitarnya dan menggunakannya sebagai informasi dalam pengambilan keputusan
  4. Spesies harus belajar mengidentifikasi jebakan .
  5. Beberapa spesies salah berasumsi bahwa dinding itu bagus dan mencoba untuk bergerak sepanjang waktu sehingga terhambat di depan dinding. Jika mereka adalah spesies dengan skor terkuat tertinggi pada saat itu, DNA mereka dengan asumsi yang salah tentang dinding digandakan berkali-kali menjadi bayi baru lahir . Setelah beberapa waktu semua spesies terjebak di depan dinding dan tidak satupun dari mereka mencapai tujuan untuk mencetak poin. Bagaimana cara menghentikan orang bodoh?

Metode penyimpanan data:

Kami ingin spesies mempelajari hal-hal, beradaptasi dengan lingkungannya, menjadi yang paling cocok. Tidak dapat dihindari ini hanya bekerja, jika pembelajaran dapat disimpan entah bagaimana. Pembelajaran akan 'disimpan' dalam 100 bit DNA. Ini adalah cara penyimpanan yang aneh, karena kita tidak dapat mengubah nilai DNA kita. Jadi kami berasumsi bahwa DNA sudah menyimpan informasi gerakan yang buruk dan baik. Jika untuk spesies tertentu informasi yang benar disimpan dalam DNA-nya ia akan bergerak maju dan menghasilkan banyak spesies baru dengan DNA-nya.

Saya menemukan skor rata-rata geometris sensitif terhadap bagaimana informasi disimpan. Mari kita asumsikan kita membaca 4 bit pertama dari 100 bit DNA dan ingin menyimpan ini dalam variabel integer. Kita dapat melakukan ini dalam beberapa cara:

  1. penyimpanan data desimal: dengan menggunakan fungsi 'built-in' dnarange, contoh: 4bits 1011akan menjadi `1x2 ^ 3 + 0x2 ^ 2 + 1x2 ^ 1 + 1x2 ^ 0 = 15. Nilai yang mungkin (untuk 4 bit): [0, 1 , 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
  2. melesat penyimpanan data: dengan menggunakan dnaStreakRangefungsi (didefinisikan di bawah), contoh: 4bits 1011 akan menjadi 1x1 + 0x1 + 1x1+ 1x2 = 4. Nilai yang mungkin (untuk 4 bit): [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. penyimpanan data bitsum: dengan menggunakan dnaCountRangefungsi (didefinisikan di bawah), contoh: 4bits 1011 akan menjadi 1x1 + 0x1 + 1x1 + 1x1 = 3. Nilai yang mungkin (untuk 4 bit): [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;
}

Perbedaan antara metode penyimpanan adalah:

  • Metode penyimpanan desimal rentan terhadap perubahan bit tunggal pada DNA. Ketika nilai bitum berubah dari 1011 menjadi 0011 nilainya berubah dari 3 menjadi 2 yang merupakan perubahan kecil.
  • Metode penyimpanan desimal adalah homogen . Setiap nilai yang mungkin memiliki perubahan yang sama terjadi. Kemungkinan Anda membaca nilai 15 dari blok memori penyimpanan 4 bit adalah 1/16 = 6%. The metode penyimpanan beruntun tidak homogen . Kemungkinan nilai bit 4 berurutan kurang atau sama dengan 6 adalah (15-3) / 16 = 81% (semua 16 kombinasi kecuali 0111.1110.111). Di bawah visual yang menunjukkan bentuk distribusi. Seperti yang Anda lihat di panah biru, peluang 4 bit beruntun menjadi kurang atau sama dengan 6 adalah 81%: visualisasi distribusi jenis penyimpanan desimal, garis dan bitum untuk bilangan biner panjang 4,5 dan 6 bit

Prioritaskan solusi.

Ketika ColorScorePlayer telah mengidentifikasi dua gerakan maju dengan skor yang identik, pilihan sewenang-wenang dibuat. IMHO, Anda tidak boleh menggunakan fungsi v.rng.rint()fungsi acak . Alih-alih, Anda harus menggunakan kesempatan ini dengan skor yang sama sebagai pengait untuk mengevaluasi solusi untuk efek urutan kedua.

Efek urutan pertama mendapatkan prioritas tertinggi. Jika skor yang sama tercapai, solusi dengan prioritas 2 menang dan seterusnya. Dengan mengubah parameter solusi, Anda dapat memengaruhi peluang terjadinya skor yang sama dan dengan demikian mengubah bobot prioritas 1 dan prioritas 2.

Implementasi perilaku yang diinginkan

Pelajari warna mana yang aman:

  • 33% dari 16 warna buruk dan oleh karena itu ketika skor suatu langkah di bawah 63/3 langkah itu tidak akan diizinkan. Oleh karena itu threshold = 63/3=21, di mana 63 adalah skor maksimum untuk 6 bit dan 33% = 1/3 (dapat dilihat pada grafik di atas).

Jika tidak ada gerakan bagus yang tersedia, gerakkan vertikal atau mundur:

  • Ketika tidak ada gerakan maju yang diizinkan, gerakan vertikal akan dibandingkan satu sama lain dengan cara yang sama. Jika juga tidak ada gerakan vertikal diizinkan, gerakan mundur diberi peringkat. Ini dicapai melalui weightMovevariabel.

Lihat apa yang ada di luar:

  • Ketika 2 atau 3 gerakan memiliki skor identik, kotak 3x3 di sekitar gerakan itu akan menentukan (melalui x2dan y2loop) apa pilihan terbaik (melalui mainSubScorevariabel). Kolom paling kanan di kotak 3x3 itu memimpin.
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};
}

Nilai: 123 (2K lari)

50 Skor Pertama (18 pertandingan hanya mencetak 1 poin):

1 10 1 79947 3 1 11 125 7333287 23701 310869 53744 1 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

Identifikasi jebakan:

Saya memeriksa DNA spesies dengan skor tertinggi ketika permainan arbitrer berakhir menggunakan penyimpanan bitsum4 (jadi skor warna memiliki rentang [0,4]):

  • skor 0: Teleport mundur, kedua dinding, 1x aman
  • skor 1: Perangkap mundur (sangat tidak berbahaya), Teleport mundur, 1x aman
  • skor 2: Jebakan ke depan (sangat berbahaya), 1x aman
  • skor 3: Teleport maju, 5x aman
  • skor 4: Teleport maju, 1x aman

Dari sini dapat disimpulkan bahwa dinding dan bank mendapatkan skor yang benar. Jebakan tidak diidentifikasi karena tergantung pada arah dan warna asal, sedangkan penilaian dilakukan pada warna tujuan. Oleh karena itu ada kebutuhan untuk juga menyimpan data pada warna asal, jadi v(0,0). Dalam dunia ideal kami ingin menyimpan informasi untuk 16 warna x 8 arah x 3 bit = 384 bit.

Sayangnya, hanya ada 100 bit yang tersedia dan kami tidak dapat menggunakannya semuanya karena kami juga membutuhkan beberapa memori untuk solusi yang dijelaskan di atas. Karena itu kami akan membuat 4 tempat sampah warna:

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

dan 4 tempat sampah arah bergerak

  • 0: bergerak vertikal atau mundur,
  • 1: bergerak maju,
  • 2: bergerak maju,
  • 3: bergerak maju ke bawah

Ketika skor desimal adalah 4 atau lebih tinggi (100.101.110.111), diasumsikan jebakan dikaitkan dengan sel ini, akibatnya gerakan ini tidak akan dipilih ketika skor yang sama muncul. Jadi identifikasi perangkap adalah efek urutan kedua dan 'lihat apa yang ada di luar' akan menjadi solusi prioritas ketiga.

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};
}

Nilai: 580 (lari 2K)

50 Skor Pertama (13 pertandingan hanya mencetak 1 poin):

28.044.169.169, 1, 66.45.168.163.453.453.453.758.457.451.164.457.457.75 dengan sekarang 1 2 ... 20-45 ... Lebih lanjut ... Lebih lanjut tentang ... Lebih lanjut tentang ... Lebih lanjut ... Lebih lanjut ... Lebih lanjut ... Baca lebih lanjut dengan sel ... Lebih lanjut ... Lebih lanjut ... Baca lebih lanjut ... Baca lebih lanjut dengan sela 1 2 2 ... 5–6.

Asumsi yang salah tentang dinding digandakan berkali-kali menjadi bayi baru lahir oleh orang bodoh:

Beberapa spesies salah berasumsi bahwa dinding itu bagus dan mencoba untuk bergerak sepanjang waktu sehingga terhambat di depan dinding. Mereka juga bisa terjebak dalam loop teleporter yang tak terbatas. Efeknya sama dalam kedua kasus.

Masalah utama adalah bahwa setelah beberapa ratus iterasi beberapa gen menjadi sangat dominan . Jika ini adalah gen 'kanan', Anda bisa mendapatkan skor sangat tinggi (> 1 juta poin). Jika ini salah, Anda mandek, karena Anda perlu keanekaragaman untuk menemukan gen yang 'tepat'.

Pertarungan orang bodoh: Solusi 1: pembalikan warna

Solusi pertama yang saya coba adalah upaya untuk memanfaatkan bagian dari memori yang tidak terpakai yang masih sangat beragam. Mari kita asumsikan Anda telah mengalokasikan 84 bit ke memori warna Anda dan menjebak memori temuan. 16 bit yang tersisa akan sangat beragam. Kita dapat mengisi 2 variabel desimal8 yang memiliki nilai pada interval [0,255] dan mereka homogen, yang berarti bahwa setiap nilai memiliki peluang 1/256. Variabel akan dipanggil inInversedan inReverse.

Jika inInversesama dengan 255 (peluang 1/256), maka kami akan membalikkan interpretasi skor warna . Jadi tembok yang dianggap tolol aman karena skornya tinggi, akan mendapat skor rendah dan karenanya akan menjadi langkah buruk. Kerugiannya adalah ini juga akan memengaruhi gen 'hak', jadi skor kita akan sangat rendah. Lebih jauh lagi, inInversespesies ini harus mereproduksi dirinya sendiri dan anak-anaknya juga akan mendapatkan bagian dari DNA dominan. Bagian terpenting adalah mengembalikan keragaman.

Jika inReversesama dengan 255 (peluang 1/256), maka kami akan membalik urutan posisi penyimpanan skor warna . Jadi sebelum warna 0 disimpan dalam bit 0-3. Sekarang warna 15 akan disimpan di posisi itu. Perbedaannya dengan inInversependekatan adalah bahwa inReversekehendak membatalkan pekerjaan yang dilakukan sejauh ini. Kami kembali di titik awal. Kami telah menciptakan spesies yang memiliki gen yang sama seperti ketika permainan dimulai (kecuali untuk memori jebakan)

Melalui pengoptimalan, ini diuji jika bijaksana untuk menggunakan inInversedan inReversepada saat yang sama. Setelah optimisasi disimpulkan skornya tidak meningkat. Masalahnya adalah kita memiliki populasi gen yang lebih beragam, tetapi ini juga mempengaruhi 'DNA yang tepat'. Kami membutuhkan solusi lain.

Pertarungan orang bodoh: Solusi 2: kode hash

Spesies memiliki 15 posisi awal yang memungkinkan dan saat ini ada kemungkinan terlalu besar ia akan mengikuti jalur yang sama persis jika ia mulai pada posisi awal yang sama. Jika dia adalah orang bodoh yang mencintai dinding, dia akan terjebak di dinding yang sama berulang-ulang. Jika dia berhasil mencapai dinding yang jauh di depan, dia akan mulai mendominasi kumpulan DNA dengan asumsi yang salah. Yang kita butuhkan adalah bahwa keturunannya akan mengikuti jalan yang sedikit berbeda (karena baginya bagaimanapun juga sudah terlambat), dan tidak akan terjebak di dinding yang jauh di depan, tetapi di tembok yang lebih dekat . Ini dapat dicapai dengan memperkenalkan kode hash .

Sebuah kode hash harus memiliki maksud untuk mengidentifikasi dan label posisi saat di papan unik. Tujuannya bukan untuk mencari tahu apa posisi (x, y) itu, tetapi untuk menjawab pertanyaan apakah leluhur saya pernah berada di lokasi ini?

Mari kita asumsikan Anda akan memiliki papan lengkap di depan Anda dan Anda akan membuat jpg dari masing-masing sel 5 dengan 5 sel mungkin. Anda akan berakhir dengan (53-5) x (15-5) = 380 gambar. Mari kita berikan angka-angka gambar dari 1 hingga 380. Kode hash kita harus dilihat sebagai ID seperti itu, dengan perbedaan yang tidak berjalan dari 1 hingga 330, tetapi memiliki IDS yang hilang, jadi mis. 563, 3424, 9424, 21245, dll.

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;
    }
}       

Bilangan prima 17dan 31ada di sana untuk mencegah informasi yang ditambahkan di awal dalam loop menghilang. Nanti lebih lanjut tentang cara mengintegrasikan kode hash kami ke dalam sisa program.

Mari kita ganti mekanisme subscoring "lihat apa yang ada di luar" dengan mekanisme subscoring lain. Ketika dua atau tiga sel memiliki skor utama yang sama akan ada peluang 50% yang teratas akan diambil, peluang 50% bahwa sel-sel bawah diambil dan peluang 0% bahwa sel tengah akan diambil. Kesempatan tidak akan ditentukan oleh generator acak, tetapi oleh bit dari memori , karena dengan cara itu kami memastikan bahwa dalam situasi yang sama pilihan yang sama dibuat.

Dalam dunia ideal (di mana kita memiliki jumlah memori tak terbatas), kita akan menghitung kode hash unik untuk situasi kita saat ini, misalnya 25881, dan pergi ke lokasi memori 25881 dan membaca di sana jika kita harus memilih sel atas atau bawah (ketika ada adalah skor yang sama). Dengan cara itu kita akan berada dalam situasi yang sama persis (ketika kita mis bepergian ke papan untuk kedua kalinya dan mulai pada posisi yang sama) membuat keputusan yang sama. Karena kita tidak memiliki memori tak terbatas, kita akan menerapkan modulo ukuran memori yang tersedia ke kode hash . Kode hash saat ini baik dalam arti bahwa distribusi setelah operasi modulo adalah homogen.

Ketika keturunan melakukan perjalanan papan yang sama dengan DNA sedikit berubah dia dalam banyak kasus (> 99%) akan membuat keputusan yang persis sama. Tetapi semakin jauh dia datang, semakin besar peluangnya untuk menjadi jalan yang dipilihnya berbeda dari leluhurnya. Jadi kemungkinan dia akan terjebak di dinding yang jauh di depan ini kecil. Walaupun terjebak di dinding yang sama dengan leluhurnya relatif besar, tetapi ini tidak terlalu buruk, karena ia tidak akan menghasilkan banyak keturunan. Tanpa pendekatan kode hash , kemungkinan terjebak di dinding terdekat dan jauh hampir sama

Optimasi

Setelah optimasi, disimpulkan bahwa tabel identifikasi perangkap tidak diperlukan dan 2 bit per warna sudah cukup. Sisa memori 100-2x16 = 68 bit digunakan untuk menyimpan kode hash. Tampaknya mekanisme kode hash dapat menghindari jebakan.

Saya telah mengoptimalkan 15 parameter. Kode ini termasuk set parameter tweak terbaik (sejauh ini):

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};
}   

Nilai: 922 (lari 2K)

50 Skor Pertama (9 pertandingan hanya mencetak 1 poin):

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.639.390.311.348.342

Ini adalah program C ++ pertama saya. Saya memiliki sebagian besar dari Anda sekarang latar belakang dalam analisis gnome. Saya ingin mengucapkan terima kasih kepada panitia, karena saya sangat menikmati mengerjakan ini.

Jika Anda memiliki umpan balik, silakan tinggalkan komentar di bawah ini. Permintaan maaf untuk teks yang panjang.


Saya menemukan analisis jebakan Anda cukup menarik.

Apakah Anda mencoba fungsi hash lain, seperti misalnya xoring nilai warna 25 dilihat sebagai 12,5 16 bit kata dan mengambil modulo? Saya tidak yakin kongruensi bilangan prima memberikan homogenitas yang lebih baik, tapi saya bukan ahli matematika besar.

Juga, apakah Anda mempertimbangkan untuk menambahkan algoritma jalur? Tampaknya menjadi faktor peningkatan besar terlepas dari genomnya, karena itu akan membatasi gerakan pada orang-orang yang menguji kemampuan genom hanya di sepanjang jalur yang jauh lebih mungkin mengarah ke posisi menang.

kuroi, terima kasih atas tanggapan Anda. Saya tidak mencoba xoring, karena saya tidak begitu mengenal operasi biner di c ++. Saya berasumsi maksud Anda 12,5 8 bit kata? Apakah Anda menggunakan xoring?
Merusak

Anda dapat melihat kode "orang percaya saya" untuk melihat fungsi hash seperti apa yang saya gunakan. Pada dasarnya saya melewatkan sel-sel off-track, dan menganggap warna on-track sebagai bagian urutan tinggi dan rendah dari kata 16 bit. Semua kata-kata ini diakumulasikan dengan XOR dalam register yang kemudian dibagi dengan ukuran tabel hash. Selama nilai hash max (65535) jauh lebih tinggi dari ukuran tabel (<100), modulo memiliki kekuatan penyebaran yang baik. Saya mengujinya pada serangkaian luas grid yang dihasilkan secara acak dan tampaknya memiliki homogenitas yang baik.

6

Pathfinder, C ++, skor awal 35.8504 (50 putaran)

Perombakan total! Saya memindahkan algoritma saya ke C ++ dan mengubahnya sedikit, tetapi nilainya masih tidak terlalu tinggi, mungkin karena tikus terus membenturkan kepalanya ke dinding. Saya lelah mencoba untuk memperbaiki ini, jadi saya akan membiarkannya untuk saat ini.


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};
}

Penjelasan

Gagasan umum adalah untuk mengklasifikasikan setiap warna sebagai jebakan atau tidak, kemudian menetapkan arah ke jebakan dan bobot untuk non-jebakan, dan mencoba mengikuti jalur bobot minimum ke batas kanan kisi visi.

Dalam 80 bit pertama genom, setiap warna diklasifikasikan menggunakan 5 bit abcde. Jika ab = 01, warnanya adalah jebakan, dan cdemengkodekan arahnya (delapan kemungkinan). Jika ab ≠ 01, warnanya bukan jebakan, dan beratnya adalah a + b + 2*(c + d + e).

Selanjutnya, kita menginisialisasi kotak 3x7, yang mewakili bidang penglihatan tikus di sebelah kanannya, diisi dengan warna "tidak dikenal". Bit 80-84 mengkodekan berat sel yang tidak diketahui mirip dengan warna non-trap, dan bit 85-89 mengkodekan berat umum untuk perangkap. Kami mengisi kisi-kisi dengan bobot, menghitung jalur terpendek, dan menambahkan beberapa bobot ekstra (dikodekan dalam bit 90-95) ke sel-sel yang berada langsung di atas dan di bawah tikus untuk mencegah gerakan menghindar. Bit 95-99 mengkodekan berat tujuan. Jika berat minimum jalan di bawahnya, tikus mungkin terjebak di suatu tempat, dan mulai bergerak secara acak (tetapi tidak pernah mundur). Jika tidak, itu mengikuti jalur berat minimum. Dengan probabilitas kecil tergantung pada berat yang mencegah sidestep, tikus memilih jalur berat kedua hingga minimum sebagai gantinya. Ini untuk mencegah macet di dinding (tapi sepertinya tidak berfungsi dengan baik sekarang).


Jalankan implementasi Anda di komputer saya. Butuh beberapa jam. Ia mendapat skor rata-rata 7,848433940863856 poin. pastebin.com/d50GcwnK
Jakube

@ Jakube Terima kasih banyak! Itu jauh lebih buruk daripada yang saya harapkan, tetapi sekarang saya melihat kode lagi, saya melihat beberapa bug dan keanehan lainnya. Saya akan mencoba untuk port ini ke C ++ nanti sehingga saya bisa menganalisisnya sendiri.
Zgarb

5

LookAheadPlayer C ++ ≈ 89.904

Pikiran awal saya adalah mencari 4 bit yang cocok dengan warna yang saya cari, dan menggunakan beberapa bit berikut sebagai skor. Ini ternyata merupakan ide yang mengerikan, kemungkinan karena mutasi.

Jadi saya berpikir tentang cara-cara melindungi terhadap mutasi dan crossover, dan itu mengingatkan saya pada pekerjaan yang telah saya lakukan pada decoding kode QR. Dalam kode QR, data dipecah menjadi blok dan bergaris untuk menghindari kesalahan karena merusak terlalu banyak bagian data yang diberikan.

Karena itu, seperti ColorScorePlayer, saya memotong DNA menjadi 16 bagian dan menggunakannya sebagai skor yang diberikan. Namun, skor bergaris sehingga bit individual dari setiap skor tidak berbatasan. Saya kemudian menjumlahkan skor dari kedua kemungkinan gerakan saat ini dan potensi pergerakan selanjutnya dan memilih langkah terbaik untuk dilakukan.

Catatan: ini diberi kode / diuji pada MinGW. Itu tidak akan dikompilasi dengan optimisasi, atau dengan multithreading. Saya tidak memiliki instalasi Linux atau Visual Studio yang praktis untuk menggunakan kompiler di mana ini akan bekerja. Saya akan mengujinya cepat besok pagi, tapi tolong beri tahu saya jika Anda mengalami masalah.

// 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 ++ (skor 9.7)

Kita tidak dapat bergantung pada menafsirkan potongan genom sebagai angka karena bit-flip tunggal dapat memiliki efek yang sangat berbeda tergantung pada posisinya. Itulah mengapa saya hanya menggunakan 16 segmen 6-bit dan memberi skor pada jumlah 1s. Awalnya 111111adalah baik dan 000000buruk, dan sementara itu tidak masalah dalam jangka panjang (setelah genom sepenuhnya berkembang) dalam konfigurasi awal dari DNA sebagian besar segmen memiliki 2-4 yang, jadi saya beralih menggunakan 9 - (#1 - 3)^2untuk penilaian, ini memungkinkan lebih banyak kebebasan bergerak di putaran pertama dan evolusi yang lebih cepat.

Saat ini saya hanya melihat 7 tetangga terdekat, menambahkan bias arah ke skor warna dan bergerak di salah satu arah tertinggi secara acak.

Meskipun skornya sendiri tidak terlalu tinggi, makhluk saya mencapai garis finish dan skor> 1 dalam 3/4 kasus.

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]};
}

Dan sampel mencetak 100 papan

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

Skor rata-rata geometri: 9,76557


Apakah skor yang Anda sebutkan untuk satu papan menggunakan tingkat mutasi standar atau nilai yang Anda sesuaikan?
trichoplax

"Makhluk saya mencapai garis finish dan skor> 1 dalam 3/4 kasus" Saya berharap metrik penilaian memberi penghargaan ini
Sparr

5

WeightChooser | C # | Skor: 220,8262 dalam 1520 Game

Menghitung berat untuk gerakan selanjutnya yang mungkin (biru) berdasarkan pada berat rata-rata dari gerakan yang mungkin diikuti (kuning)

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

RATS IN ACTION (bukan jawaban, tetapi alat grafis untuk bot C ++)

Sejak awal tantangan ini, saya mengalami kesulitan mencari tahu apa yang sebenarnya dihadapi tikus di lintasan.
Pada akhirnya saya meretas controller dan menulis alat samping untuk mendapatkan beberapa representasi grafis dari sebuah lagu.
Saya akhirnya melakukan beberapa peretasan lagi dan menambahkan visualisasi tentang kemungkinan jalur DNA tikus yang diberikan.

Peta ini sangat berantakan dan membutuhkan sedikit pembiasaan, tetapi saya merasa cukup membantu untuk memahami bagaimana bot saya bekerja.

Berikut ini sebuah contoh:

jalur sampel

Anda mungkin perlu memperbesar untuk melihat sesuatu, jadi inilah babak pertama:

setengah trek (tidak ada permainan kata-kata)

Pada awalnya, mari kita lihat jalur tikus. Ada satu jalur untuk setiap lokasi awal yang mungkin (biasanya 15, kadang-kadang sedikit kurang). Biasanya mereka cenderung bergabung, idealnya mengarah ke lokasi kemenangan tunggal.

Jalan diwakili oleh panah lurus besar. Warna menggambarkan hasil:

  • hijau: menang
  • kuning: infinite loop
  • coklat: pukulan dinding
  • merah: kecelakaan yang tidak menguntungkan

Dalam contoh ini, kami memiliki 12 posisi awal yang menang, satu mengarah ke loop tak terbatas dan dua menuju kematian yang melelahkan (diteleportasikan ke dalam perangkap, seperti yang terlihat).

Diskontinuitas jalur disebabkan oleh teleportasi, yang dapat Anda ikuti dengan panah melengkung yang sesuai.

Sekarang untuk simbol berwarna. Mereka mewakili makna 16 warna (yang abu-abu mewakili apa yang dilihat tikus).

  • dinding: persegi
  • teleporter: 4 bintang bercabang
  • detektor perangkap: octogon kecil

warna kosong adalah ... baik ... kosong.

Teleporter memiliki panah keluar yang menunjuk ke tujuan mereka.

Detektor perangkap juga memiliki panah yang menunjukkan perangkap, yang dianggap sebagai lingkaran merah.
Dalam satu kasus dari 9, perangkap terletak di sel yang sama dengan detektornya, di mana Anda akan melihat octogon kecil di atas lingkaran merah.

Ini adalah kasus perangkap kuning pucat dalam contoh ini.
Anda juga dapat melihat detektor perangkap ungu muda menunjuk ke perangkap yang ditunjukkan.

Perhatikan bahwa terkadang lingkaran merah jebakan akan disembunyikan di bawah dinding. Keduanya mematikan sehingga hasilnya sama dalam hal teleportasi.
Perhatikan juga bahwa sebuah jebakan mungkin terletak pada seorang teleporter, dalam hal mana teleporter didahulukan (yaitu tikus diteleportasi sebelum jatuh ke dalam jebakan, pada dasarnya menetralkan jebakan).

Terakhir, simbol abu-abu mewakili apa yang dilihat tikus saya (yaitu makna genomnya dikaitkan dengan warna).

  • dinding: persegi
  • detektor perangkap: octogon
  • perangkap: X

Pada dasarnya, semua sel yang duduk di persegi abu-abu dianggap sebagai dinding oleh tikus.
Big X mewakili sel yang dianggap sebagai perangkap, dengan octogon yang sesuai menunjukkan detektor yang melaporkannya.

Dalam contoh ini, kedua dinding diidentifikasi seperti itu, seperti perangkap kuning pucat (menunjukkan memang sel yang mematikan, sehingga mewakili itu sebagai dinding sudah benar).
Detektor perangkap ungu muda telah diidentifikasi seperti itu (itu duduk di octogon abu-abu), tetapi lokasi perangkap tidak benar (Anda dapat melihat bahwa beberapa lingkaran merah tidak memiliki salib di bawahnya).

Dari 4 teleporter, 2 dianggap sebagai dinding (pirus dan tan), dan 2 sebagai sel kosong (kemerahan dan kekuningan).

Beberapa sel kosong dianggap sebagai detektor atau dinding perangkap. Melihat dari dekat, Anda dapat melihat bahwa "detektor rusak" ini memang melarang masuk ke dalam sel yang akan membuat tikus bermasalah, jadi meskipun mereka gagal mencocokkan warna asli, mereka memiliki tujuan yang pasti.

Kode

Yah itu berantakan, tapi itu bekerja dengan baik.

Dilihat dari kode pemain, saya hanya menambahkan satu antarmuka: fungsi jejak yang digunakan untuk melaporkan arti DNA yang diberikan. Dalam kasus saya, saya menggunakan 3 jenis (dinding, detektor perangkap dan kosong) tetapi pada dasarnya Anda dapat menampilkan apa pun yang berhubungan dengan warna (atau tidak sama sekali jika Anda tidak menginginkan grafis yang berhubungan dengan genom).

Saya meretas controller untuk menghasilkan string karakter besar yang menyusun deskripsi trek dan warna dengan "run kering" DNA tikus dari semua lokasi yang mungkin.

Ini berarti hasilnya akan benar-benar bermakna hanya jika bot tidak menggunakan nilai acak. Jika tidak, jalur yang ditampilkan hanya akan mewakili satu hasil yang mungkin.

Terakhir, semua jejak ini dimasukkan ke dalam file teks besar yang kemudian dibaca oleh utilitas PHP yang menghasilkan output grafis.

Dalam versi saat ini, saya mengambil snapshot setiap kali tikus mati setelah mencapai kebugaran maksimal baru (yang menunjukkan dengan cukup baik penyempurnaan progresif genom tanpa memerlukan terlalu banyak snapshot), dan snapshot akhir di akhir permainan (yang menunjukkan DNA yang paling berhasil).

Jika seseorang tertarik, saya dapat mempublikasikan kodenya.

Jelas ini hanya berfungsi untuk bot C ++, dan Anda harus menulis fungsi jejak dan mungkin memodifikasi kode PHP jika Anda ingin menampilkan beberapa data spesifik genom (angka abu-abu dalam kasus saya).
Bahkan tanpa informasi spesifik DNA, Anda dapat melihat jalur yang diikuti oleh DNA Anda pada peta tertentu dengan sedikit usaha.

Mengapa output antara?

Pertama-tama, C ++ tidak memiliki perpustakaan grafik portabel yang layak untuk dibicarakan, terutama ketika menggunakan MSVC. Bahkan jika Win32 membangun biasanya tersedia, mereka sering datang sebagai renungan, dan jumlah perpustakaan eksternal, paket dan basa-basi seperti unix lain yang diperlukan membuat menulis aplikasi grafis cepat dan sederhana menjadi rasa sakit yang mengerikan di bagian tubuh seseorang yang kesopanan mencegah saya dari penamaan.

Saya mempertimbangkan untuk menggunakan Qt (tentang satu-satunya lingkungan yang membuat GUI portable / pengembangan grafis dalam C ++ menjadi tugas yang sederhana dan bahkan menyenangkan, IMHO - mungkin karena ia menambahkan sistem pesan à la Objective C yang C ++ sangat kurang dan melakukan pekerjaan luar biasa membatasi memori manajemen seminimal mungkin), tetapi ini terlihat seperti kerja keras yang berlebihan untuk tugas yang ada (dan siapa pun yang ingin menggunakan kode harus menginstal SDK biggish - hampir tidak sepadan dengan usaha, saya kira).

Bahkan dengan asumsi perpustakaan portabel, tidak ada persyaratan kecepatan untuk berbicara tentang (satu detik atau lebih untuk menghasilkan gambar sebagian besar cukup), dan dengan kekakuan pepatah dan kekacauan yang melekat, C ++ tentu bukan alat terbaik untuk pekerjaan itu.

Selain itu, memiliki output teks menengah menambah banyak fleksibilitas. Setelah data ada, Anda dapat menggunakannya untuk tujuan lain (menganalisis kinerja bot, misalnya).

Kenapa PHP?

Saya menemukan bahasanya sangat sederhana dan mudah beradaptasi, sangat nyaman untuk prototyping. Saya menjadikannya bahasa hewan peliharaan saya untuk tantangan kode yang tidak memerlukan performa ekstrem.
Meskipun demikian, ini adalah bahasa yang mengerikan untuk bermain golf, tetapi golf tidak pernah menjadi cangkir teh saya.

Saya kira python atau Ruby akan sama menyenangkan untuk digunakan untuk tujuan yang sama, tetapi saya tidak pernah memiliki kesempatan untuk melakukan beberapa pekerjaan serius dengan mereka, dan saya bekerja di situs web belakangan ini, jadi PHP itu.

Bahkan jika Anda tidak tahu bahasa, tidak boleh terlalu sulit untuk memodifikasi kode yang sesuai dengan kebutuhan Anda. Hanya saja, jangan lupakan $s sebelum variabel, sama seperti hari-hari dasar yang baik :).


1
Maukah Anda membagikan alat Anda? Saya tidak melihat kode atau tautan dalam jawaban Anda.
Franky

5

SkyWalker - Python - skor kurang dari 231 dalam 50 pertandingan

Jadi kode dulu dan kemudian beberapa penjelasan. Saya harap tidak ada yang rusak saat menyalin.

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

Beberapa Penjelasan

Menurut pendapat saya perbedaan utama adalah bahwa saya tidak kode setiap warna. Sebagai gantinya, saya mencoba menyimpan jumlah warna yang penting. Menurut saya warna-warna itu adalah jebakan, dinding, dan teleporter. Spesimen tidak perlu tahu warna sel yang baik. Oleh karena itu, genom saya terstruktur dengan cara berikut.

  • 2 x 8 bit untuk jebakan, 4 bit pertama adalah nomor warna, 4 lainnya adalah offset
  • 2 x 4 bit untuk dinding, hanya warnanya
  • 4 x 7 bit untuk teleporter, lagi 4 bit untuk warnanya, 3 untuk memutuskan baik atau buruk

Ini membuat total 52 bit digunakan. Namun, saya hanya menggunakan bit pertama dari 3 decoder teleporter (saya memeriksa apakah jumlahnya lebih besar 3). Oleh karena itu, 2 lainnya dapat dihapus, meninggalkan saya di 44 bit yang digunakan.

Pada setiap belokan, saya memeriksa setiap bidang visi saya apakah itu salah satu warna buruk (+ bagian luar papan -1) dan menambahkannya ke daftar bidang yang tidak ingin dipindahkan spesimennya. Dalam kasus jebakan, saya menambahkan bidang yang ada pada offset yang disimpan untuk warna jebakan itu.

Berdasarkan daftar bidang buruk itu langkah selanjutnya dihitung. Urutan bidang yang disukai adalah:

  1. meneruskan
  2. atas atau bawah
  3. mundur ke atas atau ke bawah
  4. ke belakang

Jika dua bidang kategori berlaku, satu dipilih secara acak.

Hasil

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

Pikiran

  • Saya tidak tahu, apakah saya beruntung dengan 50 berjalan atau jika sebenarnya ada beberapa kebijaksanaan dalam strategi saya.

  • Lari saya sepertinya tidak pernah lepas landas dan mendapatkan skor super tinggi tetapi mereka juga cenderung menemukan setidaknya beberapa kali tujuannya

  • Beberapa keacakan kecil baik untuk tidak terjebak dalam perangkap di suatu tempat yang dekat dengan akhir lomba

  • Saya pikir warna non-spesial tidak pernah buruk. Namun, contoh dari mereka bisa menjadi buruk, ketika mereka berada di offset perangkap. Dengan demikian, pelabelan warna buruk jika tidak menjebak, dinding atau teleporter buruk tidak masuk akal.

  • Tembok adalah musuh terbesar

Perbaikan

Pertama, meskipun saya akan kehilangan melihat kotak hitam semakin dekat dan lebih dekat ke tujuan port C ++ diperlukan untuk melakukan lebih banyak tes dan mendapatkan hasil yang lebih bermakna.

Salah satu masalah utama adalah bahwa jika ada sel-sel jahat (atau yang spesimennya anggap buruk) di depan tikus itu dengan mudah mulai bergerak naik dan turun dalam lingkaran. Ini bisa dihentikan atau dikurangi dengan melihat 2 bergerak maju dalam kasus-kasus itu dan mencegahnya pindah ke bidang di mana ia hanya akan bergerak kembali.

Seringkali dibutuhkan waktu hingga tikus dengan gen baik mencapai tujuan dan mulai menyebarkan gen. Mungkin saya perlu beberapa strategi untuk meningkatkan keragaman dalam kasus-kasus itu.

Karena teleporter sulit untuk dihitung, mungkin saya harus membagi populasi pada mereka yang berisiko dan selalu mengambil teleporter yang baik dan mereka yang lebih peduli dan hanya mengambilnya jika tidak ada pilihan lain.

Saya harus menggunakan bagian kedua genom saya.


Saya juga mencoba untuk menyimpan warna tetapi pada akhirnya menyimpulkan itu tidak berhasil karena Anda akan mendapatkan dua kali lipat. Misalnya jika self.bit_chunk(16, 4)dan self.bit_chunk(20, 4)memiliki kedua nilai yang 0010Anda miliki, secara efektif hanya menyimpan info tentang salah satu dari dua jebakan.
Ruut

Saya perlu menambahkan lekukan pada satu baris untuk menjalankan ini - saya kira itu hilang saat menyalin dan menempel. Saya telah menambahkannya ke kode Anda di sini sekarang juga.
trichoplax

Untuk orang lain yang ingin menjalankan ini: Ini berjalan di python 2, dan dapat dijalankan di python 3 dengan mengubah kejadian tunggal itervaluesmenjadi values.
trichoplax

Saya mendapat hasil berikut: [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] Rerata geometris 122.9220309940335
trichoplax

Sepertinya kita harus menjalankan lebih dari 50 game untuk mendapatkan skor yang andal.
trichoplax

3

Python, NeighborsOfNeighbors, Score = 259.84395 lebih dari 100 game

Ini adalah variasi pada ColorScorePlayer. Setiap 6 bit menyimpan skor kualitas untuk kuadrat. Ketika bot bergerak, skor masing-masing dari 3 kotak maju - diagonal ke atas, ke depan, dan diagonal ke bawah. Skornya adalah kualitas kotak ditambah setengah kualitas rata-rata dari 3 kotak berikutnya. Ini memberi bot beberapa pandangan ke depan, tanpa membebani kualitas kotak pertama. Algoritma ini mirip dengan LookAheadPlayer, yang tidak saya lihat sebelum menulis solusi ini.

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)

Ada lekukan yang hilang pada satu baris. Saya kira itu hilang ketika menempel. Saya telah menambahkannya.
trichoplax

Berjalan di python 3 itu mengeluh tentang membandingkan Tidak Ada saat menghitung maks (skor). Jadi saya berubah else Nonemenjadi else 0pada baris sebelumnya untuk menghitung skor Anda. Mudah-mudahan itu meninggalkan logika Anda tidak berubah (saya tidak membuat perubahan pada kode Anda di sini di SE selain menambahkan indentasi yang hilang).
trichoplax

Berjalan dalam python 3 saya mendapat skor berikut untuk jawaban ini: [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

Rata-rata geometris 428.3750848244933
trichoplax

2

ROUS (Hewan Pengerat dari Ukuran Tidak Biasa), Jawa, Skor = 0

Ini hash lingkungan untuk memutuskan ke mana harus pergi. Karena pengontrol Java tidak berfungsi saya tidak memiliki skor untuk ini. Ini hanya akan menjadi sangat jauh jika menemukan beberapa teleporter untuk membantunya.Ini cenderung punah dan crash controller sesekali. Ini mungkin disebabkan oleh fakta bahwa lingkungan alaminya adalah Rawa Api.

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
Pengontrol Java sedang bekerja sekarang.
Martin Ender

3
Pada awalnya saya pikir Anda memberi penghormatan kepada Rusia kuno, tetapi seperti yang terlihat pada Rob Reiner.

Skor minimum yang mungkin adalah 1
trichoplax

@trichoplax ...
TheNumberOne

Oh saya mengerti - jadi itu cukup sering terjadi sehingga Anda tidak dapat mencapai akhir lari?
trichoplax

2

Gray-Color Lookahead (C ++, ~ 1.35)

Yang ini rata-rata tidak bekerja dengan sangat baik, tetapi kadang-kadang jarang terjadi dengan sangat baik. Sayangnya, kami sedang dinilai pada rata-rata geometris (1,35), dan tidak pada skor maksimum (20077).

Algoritma ini bekerja dengan hanya menggunakan kode abu-abu 4-bit untuk memetakan skor setiap warna di suatu tempat dari -2 ke 2 (dengan bias terhadap kisaran [-1.1.1]), dan menghitung skor setiap ubin gerakan dan gerakan selanjutnya . Itu juga menggunakan kode abu-abu 2-bit untuk menentukan pengganda untuk ubin itu sendiri serta faktor biasing untuk bergerak ke kanan. (Kode abu-abu jauh lebih rentan terhadap lompatan besar karena mutasi, meskipun mereka tidak benar-benar melakukan bantuan untuk crossover mid-codepoint ...)

Itu juga sama sekali tidak mencoba menangani jebakan khusus, dan saya curiga itu mungkin kejatuhan (walaupun saya belum menambahkan instrumentasi apa pun ke controller untuk menguji teori ini).

Untuk setiap gerakan yang mungkin, ia menentukan skor, dan di antara semua gerakan dengan skor tertinggi yang dipilihnya secara acak.

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())];
}

Pada putaran terakhir saya, saya mendapat skor: 1 1 1 1 1 1 1 46 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

Saya berharap bisa mendapatkan lebih banyak dari 20077 dan lebih sedikit dari 1s. :)


1
Menggunakan kode abu-abu adalah ide abu-abu! ;)
matovitch

1
+1 untuk kode Gray. Namun, genom yang sepenuhnya mutasi-tahan akan sedikit merusak keanekaragaman. Dan Btw skor 20.000 bahkan tidak dekat dengan maks yang dapat Anda raih. Jika beberapa tikus mengembangkan kemampuan untuk menjalankan lintasan dari lokasi awal yang memungkinkan, ia akan berlaku abadi dan memperoleh skor kebugaran yang sangat besar. Genomnya dengan cepat mendominasi, mengarah ke populasi hingga hampir 50 ribu tikus dan skor beberapa juta.

2

C ++, TripleScore, Nilai: 100 ~ 400

Pertama-tama, skor saya sangat bervariasi selama beberapa kali (terutama karena jumlah 1).

Inti menghitung skor 5 arah: atas, bawah, maju-maju, maju dan maju-turun. Pertama skor naik dan turun dihitung, daripada hasilnya dibandingkan dengan nilai tinggal di tempat. Jika tetap di tempat lebih baik daripada bergerak ke atas atau ke bawah, arah ini tidak akan dipilih (jadi harus maju). Ini untuk mencegah memantul (naik, turun, naik, turun, ...) antara 2 titik.

Sekarang 3 arah lainnya diberi skor: maju-naik, lurus ke depan dan maju-turun. Dari semua arah yang diselidiki, yang dengan skor tertinggi disimpan dan 1 di antaranya dipilih secara acak.

Mencetak arah: TripleScore menghitung skor suatu gerakan menggunakan 3 subskala:

  • Skor warna tujuan (tergantung pada dna, seperti pada colorScorePlayer)
  • Skor maju (tergantung pada dna)
  • Skor maksimum untuk mengambil langkah maju dari tujuan (dikalikan dengan faktor yang disimpan dalam dna)

Seperti dengan jawaban lain, skor sangat tergantung pada jumlah 1-skor yang dikembalikan.

#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

Tikus yang sangat tidak deterministik ini menghitung probabilitas untuk pergi ke suatu tempat oleh lingkungannya. 16 slot pertama dalam genom mewakili 16 warna. 1 dalam slot berarti warnanya baik untuk diinjak, 0 berarti buruk. 16 berikutnya memegang yang sama untuk ruang di depan target Anda, dan seterusnya.

Keuntungan utama dari pendekatan probabilistik adalah bahwa hampir tidak mungkin terjebak di balik tembok terlalu lama. Kerugiannya adalah Anda hampir tidak akan pernah mendapatkan tikus yang hampir sempurna.


+1 untuk orisinalitas. Skor apa yang Anda dapatkan?

Belum pernah benar-benar mengujinya ...
MegaTom

Apakah Anda lupa memberi cnilai awal? Tampaknya tidak ditentukan saat Anda menggunakannya di pertama if.
Martin Ender

@ MartinBüttner ya saya lupa. Saya akan memperbaikinya sekarang.
MegaTom

Saya tidak begitu mengenal Ruby, tetapi kode Anda tidak berjalan di bawah Ruby2.1.5. coordsbukan daftar, Anda menggunakan &&bukan anddan lupa tanda kurung, dan bahkan setelah memperbaiki semua ini Anda tidak membatasi nilai RNG sehingga Anda mendapatkan arah kosong. Apakah ini pseudo-code, atau sesuatu yang dimaksudkan untuk dijalankan dengan semacam dialek Ruby?

2

Java, RunningStar, Score = 1817.050970291959 lebih dari 1000 pertandingan

Bot ini menggunakan kode warna Run-Bonus dengan teknik StarPlayer .

Pembaruan: Memperbaiki pengontrol java.

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

LeapForward, Python 2

Tidak terlalu terobosan tapi itu adalah satu-satunya upaya saya yang dilakukan ok-ish.

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)

Pada dasarnya, kode empat warna (masing-masing 4 bit) untuk menghindari, dalam genom. Kemudian maju ke warna yang tidak ada dalam daftar itu. Jika semua warna buruk, itu masih melompat ke depan ke yang tidak diketahui.


Mungkin seharusnya menyebutnya "RedQueen" :)
plannapus

1

Java - IAmARobotPlayer - Skor 3.7

Saya baru saja membuat tikus robot ini untuk perbandingan dengan program lain (tidak terlalu menarik sejauh ini) yang saya buat. Skor keseluruhan tidak baik, tetapi jika skor di suatu tempat, itu akan mendapatkan banyak tikus melalui. Idenya adalah bahwa ia hanya akan melihat tiga sel di depannya, setiap sel baik atau buruk. Ini memberikan angka biner. Kemudian akan mencari nomor ini dalam genomnya, mengambil tiga bit berturut-turut, juga mengubahnya menjadi angka dan mengambil tindakan yang disimpan di bawah nomor ini. Jadi itu bertindak selalu sama ketika menghadapi situasi yang sama.

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];

    }
}

Hasil:

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

Cautious Specimens - C ++ - skor sekitar 2030 lebih dari 200 berjalan

Ini menggunakan bagian warna (16x4 bit) dari pengkodean DNA dari Buta Buta tetapi meninggalkan sisanya (36bit) dari DNA yang sama sekali tidak digunakan.

Pengkodean warna adalah:

  • 10XX - untuk kotak yang aman;
  • 11XX - untuk kotak mematikan; dan
  • 0000 hingga 0111 - untuk kotak perangkap 8 jenis.

Di mana X menunjukkan bit yang tidak digunakan. Mengingat bahwa hanya 2 dari 16 warna yang merupakan jebakan yang akan menggunakan semua 4 bitnya (dan hanya jika jebakan diimbangi, yang akan menjadi kasus 8-dari-9 kali) maka biasanya akan ada 64 bit yang tidak digunakan - teorinya adalah bahwa mutasi yang mempengaruhi bit-bit yang tidak terpakai ini tidak akan merusak genom dan stabilitas lebih baik daripada solusi mewah yang dapat menggunakan bit-bit yang tersisa.

Spesimen kemudian menggunakan ini untuk merencanakan rute yang aman dalam kisi 7x7 yang berpusat pada diri mereka sendiri (5x5 yang memungkinkan penglihatan mereka ditambah 1 kuadrat di setiap sisi untuk memungkinkan jebakan ofset) memprioritaskan bergerak jarak terbesar ke depan setelah 3 gerakan.

Saya awalnya mulai membangun beberapa cek untuk memastikan bahwa fakta bahwa warna spesimen saat ini berdiri tidak mematikan sesuai dengan genom dan menandai setiap warna yang salah sebagai kotak keselamatan UNSURE (dan kotak yang berdekatan) - namun menambahkan signifikan komplikasi untuk keuntungan kecil atau tidak sama sekali dibandingkan dengan menandai kotak-kotak itu sebagai AMAN dan membunuh beberapa spesimen tambahan. Saya akan kembali ke ini jika saya punya waktu.

#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};
}

Skor Contoh:

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

Skor Maks selama pengujian: 8.150.817 Spesimen Disimpan.


Sekarang Anda melakukannya ... Saya ingin menyimpan pathing untuk nanti, tapi saya tidak bisa membiarkan tikus yang berhati-hati Anda tidak tertandingi :) Seperti yang terlihat, pathing bekerja lebih baik dengan pengkodean yang lebih efisien. Gagasan Anda untuk memperluas area jalur ke 7x7 juga tampak menjanjikan. Saya akan melihat apakah saya bisa menggunakannya.

Saat ini saya sedang menjalankan 2000 kali untuk ini ... setelah 900 yang pertama rata-rata tampaknya akan menyelesaikan sekitar 600, yang cukup jauh dari tahun 2000. Apakah Anda keberatan menjalankannya kembali pada akhir Anda juga, untuk melihat apakah tahun 2000 adalah hanya kebetulan?
Martin Ender
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.