실험실 쥐 경주 : 유전자 알고리즘 연습


113

이것은 Fortnightly Challenge # 3입니다. 주제 : 유전자 알고리즘

이 도전은 약간의 실험입니다. 우리는 유전자 알고리즘으로 우리가 할 수있는 일을 도전적인 방법으로보고 싶었습니다. 모든 것이 최적은 아니지만 최선을 다해 액세스 할 수 있도록 노력했습니다. 이것이 효과가 있다면, 미래에 우리가 볼 수있는 것을 아는 사람. 어쩌면 언덕의 유전자 왕일까요?

사양이 꽤 길다! 우리는 스펙을 The Basics로 분리하려고 시도했습니다-프레임 워크로 게임을 시작하고 답변을 제출하기 위해 알아야 할 최소한의 정보와 Gory Details-전체 스펙과 컨트롤러에 대한 모든 세부 정보를 기반으로합니다. 직접 쓸 수 있습니다.
질문이 있으시면 언제든지 채팅참여하십시오!

당신은 행동 심리학의 연구원입니다. 금요일 저녁에 여러분과 동료들은 약간의 쥐 경주에 재미를 느끼고 실험실 쥐를 사용하기로 결정합니다. 실제로 감정적으로 너무 감정적으로 연결되기 전에 표본 이라고 부릅니다 .

시편에 작은 레이스 트랙을 설정했으며, 더 흥미롭게하기 위해 트랙을 가로 질러 벽과 함정 및 순간 이동 장치를 몇 개 배치했습니다. 자, 당신의 표본은 여전히 ​​쥐입니다 ... 그들은 함정이나 텔레 포터가 무엇인지 전혀 모릅니다. 그들이 보는 것은 다른 색상의 것들입니다. 그들은 또한 어떤 종류의 기억도 가지고 있지 않습니다. 그들이 할 수있는 모든 것은 그들의 현재 환경에 기초하여 결정을 내리는 것입니다. 자연 선택은 그렇지 않은 사람들의 함정을 피하는 방법을 알고있는 표본을 골라 낼 것입니다 (이 경주는 시간이 걸릴 것입니다 ...). 게임을 시작하자!

사용중인 보드의 이미지 예

† 84,465 개의 시편이이 도전을 위해 해를 입었습니다.

기초

이 게임은 싱글 플레이어 게임입니다 (귀하와 동료는 인구를 섞지 않기 때문에 각자 자신 만의 레이스 트랙을 만들었습니다). 레이스 트랙은 키가 15 셀 , 폭이 50 셀인 직사각형 그리드 입니다. 왼쪽 가장자리 ( x = 0 )의 무작위 (필수 별개의) 셀에서 15 개의 표본으로 시작 합니다. 시편은 x ≥ 490 ≤ y ≤ 14의 셀인 목표에 도달하려고 시도해야합니다 (시편이 트랙을 오른쪽으로 오버 슈트 할 수 있음). 이런 일이 생길 때마다 포인트를 얻습니다. 당신은 또한 1 포인트로 게임을 시작합니다. 10,000 회전 후 포인트를 최대화해야 합니다.

여러 시편이 동일한 셀을 차지할 수 있으며 상호 작용하지 않습니다.

각 차례마다, 각 시편은 주변의 5x5 격자를 본다 (중앙에 위치). 해당 격자의 각 셀에는의 색상이 포함 -1됩니다 15. -1경계를 벗어난 셀을 나타냅니다. 시편이 경계를 벗어나면 사망합니다. 다른 색상은 빈 셀, 트랩, 벽 및 텔레 포터를 나타냅니다. 그러나 표본은 어떤 색이 무엇을 나타내는 지 알지 못합니다. 그래도 몇 가지 제약이 있습니다.

  • 8 개의 색상은 빈 셀을 나타냅니다.
  • 4 색은 텔레 포터를 나타냅니다. 텔레 포터는 표본을 9x9 인근의 특정 셀로 보냅니다. 이 오프셋은 같은 색상의 모든 텔레 포터에서 동일합니다.
  • 2 색은 벽을 나타냅니다. 벽으로 이동하는 것은 여전히 ​​서있는 것과 같습니다.
  • 2 색은 함정을 나타냅니다. 트랩은 바로 근처에있는 9 개의 셀 중 하나 가 치명적 임을 나타냅니다 (트랩 셀 자체는 아님). 이 오프셋은 동일한 색상의 모든 트랩에 대해 동일합니다.

자, 자연 선택에 대해 ... 각 표본에는 100 비트 의 숫자 인 게놈이 있습니다. 두 개의 기존 표본을 교차 교배 한 다음 게놈을 약간 돌연변이시켜 새로운 표본을 만듭니다. 표본의 성공률이 높을수록 재현 가능성이 커집니다.

그래서 당신의 임무는 다음과 같습니다 : 단일 함수를 작성합니다.이 함수는 표본이 보는 5x5 격자와 게놈을 입력으로받습니다. 함수는 시편에 대한 이동 (Δx, Δy)을 반환합니다. 여기서 Δx 및 Δy는 각각 다음 중 하나입니다 {-1, 0, 1}. 함수 호출간에 데이터를 유지해서는 안됩니다. 여기에는 자신의 난수 생성기를 사용하는 것이 포함됩니다. 귀하의 기능에는 원하는대로 자유롭게 사용할 수있는 시드 RNG가 제공됩니다.

귀하의 제출 점수는 50 개의 무작위 트랙에 걸친 포인트 수의 기하 평균 입니다 . 이 점수에는 약간의 차이가있을 수 있습니다. 따라서이 점수는 예비 점수가됩니다 . 이 도전이 종료되면 마감일이 발표됩니다. 마감일이 끝나면 100 개의 보드가 무작위로 선택되며 모든 제출물은이 100 개의 보드에서 채점됩니다. 귀하의 답변에 예상 점수를 매길 수 있지만, 우리는 아무도 속임수를 쓰지 않도록 모든 제출물에 점수를 매길 것입니다.

우리는 소수의 언어로 컨트롤러 프로그램을 제공했습니다. 현재, 파이썬 (2 또는 3), Ruby , C ++ , C # 또는 Java로 제출물을 작성할 수 있습니다 . 컨트롤러는 보드를 생성하고 게임을 실행하며 유전자 알고리즘에 대한 프레임 워크를 제공합니다. 이동 기능을 제공하기 만하면됩니다.

잠깐, 유전체로 정확히 무엇을해야합니까?

도전은 그것을 알아내는 것입니다!

표본에 기억이 없기 때문에 주어진 차례에 당신이 얻는 것은 5x5 색상의 격자로 당신에게 아무런 의미가 없습니다. 따라서 목표를 달성하려면 게놈을 사용해야합니다. 일반적으로 게놈의 일부를 사용하여 색상 또는 그리드 레이아웃에 대한 정보를 저장하고 봇은 게놈에 저장된 추가 정보를 기반으로 결정을 내립니다.

물론 실제로 수동으로 아무것도 저장할 수는 없습니다. 따라서 저장된 실제 정보는 처음에는 완전히 무작위입니다. 그러나 유전자 알고리즘은 유전체에 올바른 정보가 포함 된 표본을 선택하고 잘못된 정보가있는 표본을 제거합니다. 목표는 게놈 비트 및 시야에서 이동으로의 맵핑을 찾는 것입니다.이를 통해 목표에 대한 경로를 신속하게 찾고 지속적으로 승리 전략으로 발전 할 수 있습니다.

시작하기에 충분한 정보가 있어야합니다. 원하는 경우 다음 섹션을 건너 뛰고 맨 아래에있는 컨트롤러 목록에서 해당 컨트롤러를 선택할 수 있습니다 (특정 컨트롤러 사용 방법에 대한 정보도 포함되어 있음).

모든 것을 원한다면 계속 읽으십시오 ...

처참한 세부 사항

이 사양이 완성되었습니다. 모든 컨트롤러는 이러한 규칙을 구현해야합니다.

달리 명시되지 않는 한 모든 무작위성은 균일 분포를 사용합니다.

트랙 생성 :

  • 트랙은 직사각형 그리드이며, X = 53 셀, Y = 15 셀입니다. x가 49 이상인 셀 은 목표 셀입니다 (여기서 x 는 0을 기준으로 함).
  • 각 세포는 단일 색상을 가지고 있으며 치명적이지 않을 수도 있습니다. 아래의 세포 유형 중 하나에 의해 명시되지 않는 한 세포는 치명적이지 않습니다.
  • 에서 로 레이블이 지정된 16 개의 서로 다른 셀 색상 이 있으며 그 의미는 게임 마다 다릅니다 . 또한 범위를 벗어난 셀을 나타냅니다.이 셀은 치명적 입니다.015-1
  • 8 임의의 색상을 선택하십시오 . 이것들은 비어있는 셀이 될 것입니다.
  • 임의의 색상을 4 개 더 선택하십시오 . 이들은 텔레 포터입니다. 이 색상 중 두 가지의 경우 9x9 이웃에서 (0,0을 제외하고 (-4, -4)에서 (4,4)까지 0이 아닌 오프셋을 선택하십시오 . 다른 두 가지 색상의 경우 해당 오프셋을 반전시킵니다. 시편이 텔레 포터를 밟으면 즉시 해당 오프셋만큼 이동합니다.
  • 무작위 색상을 2 개 더 선택하십시오 . 이들은 함정입니다. 이러한 각 색상에 대해 (1, -1)에서 (1,1)까지 3x3 이웃에서 오프셋을 선택하십시오. 트랩은 해당 오프셋의 셀이 치명적 임을 나타냅니다 . 참고 : 트랩 셀 자체가 반드시 치명적이지는 않습니다.
  • 2 나머지 색 이동을 방해하는 벽이다. 벽면 셀로 이동하려고하면 이동이 정지 상태로 유지됩니다. 벽 세포 자체는 치명적 입니다.
  • 그리드의 목표가 아닌 셀마다 임의의 색상을 선택하십시오. 각 목표 셀에 대해 임의의 색상을 선택하십시오 .
  • 트랙의 왼쪽 가장자리에있는 각 셀에 대해 100 턴 이내에 목표를 달성 할 수 있는지 여부를 결정합니다 ( 아래 의 턴 순서 규칙 에 따라 ). 그렇다면이 셀은 허용되는 시작 셀 입니다. 시작 셀이 10 개 미만인 경우 트랙을 삭제하고 새 트랙을 생성하십시오.
  • 무작위 게놈과 연령이 0 인 표본 15 개를 만듭니다 . 임의의 시작 셀에 각 표본을 놓습니다.

순서 전환 :

  1. 각 시편에 대해 다음 단계가 순서대로 수행됩니다. 표본은 서로 상호 작용하거나 보지 않으며 동일한 셀을 차지할 수 있습니다.
    1. 표본의 나이가 100 이면 사망합니다. 그렇지 않으면, 나이를 1 씩 늘리십시오.
    2. 시편에는 시편 중앙에 5x5 색상 격자가 표시되며 3x3 이웃으로 이동합니다. 이 범위를 벗어나면 컨트롤러가 종료됩니다.
    3. 대상 군이 벽이면 이동이 (0,0)으로 변경됩니다.
    4. 표적 세포가 텔레 포터 인 경우, 시편은 텔레 포터의 오프셋에 의해 이동됩니다. 참고 : 이 단계는 반복적으로 수행 되지 않고 한 번 수행 됩니다.
    5. 시편이 현재 점유하고있는 셀 (잠재적으로 하나의 텔레 포터를 사용한 후)이 치명적인 경우 시편이 사망합니다. 이것은 시편이 죽는 유일한 시간이다 (위의 1.1 단계와는 별개). 특히, 치명적인 세포에 생성되는 새로운 표본은 즉시 죽지는 않지만 위험한 세포에서 먼저 벗어날 수 있습니다.
    6. 시편이 목표 셀을 점유하면 점수를 매기고 시편을 임의의 시작 셀로 이동 하고 나이를 0으로 재설정합니다.
  2. 보드에 2 개 미만의 표본이 남아 있으면 게임이 종료됩니다.
  3. 나이가 0 인 10 개의 새로운 표본을 만듭니다 . 각 게놈은 아래의 육종 규칙에 의해 (개별적으로) 결정됩니다. 임의의 시작 셀에 각 표본을 놓습니다.

번식:

  • 새로운 표본이 만들어 지면 오른쪽으로 더 진행된 표본에 대한 편견과 함께 두 개의 별개의 부모를 무작위로 선택하십시오 . 표본이 선택 될 확률은 현재 체력 점수에 비례합니다 . 표본의 체력 점수는

    1 + x + 50 * 목표에 도달 한 횟수

    여기서 x 는 0 기반 가로 인덱스입니다. 같은 차례에 만들어진 표본은 부모로 선택할 수 없습니다.

  • 두 부모 중에서 첫 번째 게놈 비트를 취하기 위해 무작위를 선택하십시오.

  • 이제 게놈을 따라 걸을 때 확률이 0.05 인 부모를 전환 하고 결과 부모에서 비트를 계속 가져갑니다.
  • 완전히 조립 된 게놈을 돌연변이시킵니다 : 각 비트에 대해 확률 0.01으로 뒤집으십시오 .

채점 :

  • 한 게임은 10,000 턴 동안 지속됩니다 .
  • 플레이어는 기하 평균을 사용할 수 있도록 1 포인트로 게임을 시작합니다.
  • 표본이 목표에 도달 할 때마다 플레이어는 점수를 얻습니다.
  • 현재 각 플레이어의 제출은 각각 다른 무작위 트랙을 가진 50 게임에 대해 실행됩니다 .
  • 상기 접근법은 바람직한 것보다 더 많은 분산을 초래한다. 이 도전이 종료되면 마감일이 발표됩니다. 마감일이 끝나면 100 개의 보드가 무작위로 선택되며 모든 제출물은이 100 개의 보드에서 채점됩니다.
  • 플레이어의 전체 점수는 이러한 개별 게임 점수의 기하 평균 입니다.

컨트롤러

다음 컨트롤러 중 하나를 선택할 수 있습니다 (기능적으로 동일하므로). 우리는 모두 테스트했지만 버그를 발견하거나 코드 또는 성능을 개선하거나 그래픽 출력과 같은 기능을 추가하려는 경우 문제를 제기하거나 GitHub에서 풀 요청을 보내십시오! 다른 언어로 새 컨트롤러를 추가 할 수도 있습니다.

각 컨트롤러의 언어 이름을 클릭하면 README.md정확한 사용법 지침 이 포함 된 GitHub의 올바른 디렉토리로 이동 합니다.

git 및 / 또는 GitHub에 익숙하지 않은 경우 첫 페이지에서 전체 저장소를 ZIP으로 다운로드 할 수 있습니다 (사이드 바의 버튼 참조).

파이썬

  • 가장 철저한 테스트를 거쳤습니다. 이것이 우리의 참조 구현입니다.
  • Python 2.6 이상 및 Python 3.2 이상에서 작동합니다!
  • 매우 느립니다. 속도 를 높이 려면 PyPy 로 실행하는 것이 좋습니다 .
  • 중 하나를 사용하여 그래픽 출력 지원 pygame또는 tkinter.

루비

  • Ruby 2.0.0으로 테스트되었습니다. 최신 버전에서 작동합니다.
  • 또한 느리지 만 Ruby는 제출 아이디어를 프로토 타이핑하는 데 편리 할 수 ​​있습니다.

C ++

  • C ++ 11이 필요합니다.
  • 선택적으로 멀티 스레딩을 지원합니다.
  • 지금까지 가장 빠른 컨트롤러입니다.

씨#

  • LINQ를 사용하므로 .NET 3.5가 필요합니다.
  • 오히려 천천히.

자바

  • 특별히 느리지 않습니다. 특별히 빠르지는 않습니다.

예비 리더 보드

모든 점수는 예비입니다. 그럼에도 불구하고 문제가 있거나 잘못 된 경우 알려 주시기 바랍니다. 예제 제출은 비교를 위해 나열되었지만 경합에는 표시되지 않습니다.

  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

크레딧

이 도전은 큰 협력 노력이었습니다.

  • Nathan Merril : Python 및 Java 컨트롤러를 작성했습니다. 도전 개념을 왕의 왕에서 쥐 경주로 바꿨습니다.
  • trichoplax : 플레이 테스트 . 파이썬 컨트롤러에서 일했습니다.
  • feersum : C ++ 컨트롤러를 작성했습니다.
  • VisualMelon : C # 컨트롤러를 썼습니다.
  • 마틴 부트 너 : 개념. 루비 컨트롤러를 작성했습니다. 플레이 테스트. 파이썬 컨트롤러에서 일했습니다.
  • 아브라함 : 플레이 테스팅. Python을 테스트하고 C # 및 C ++ 컨트롤러를 검토했습니다.

위의 모든 사용자 (그리고 아마도 더 잊어 버린 몇 명)는 도전의 전반적인 디자인에 기여했습니다.

C ++ 컨트롤러 업데이트

Visual Studio 및 멀티 스레딩과 함께 C ++를 사용하는 경우 임의의 숫자 생성기 시드 관련 버그로 인해 최신 보드를 만들 수 있습니다.


3
누군가이 문제에 대한 최적의 유전자 알고리즘을 찾기 위해 유전자 유전자 알고리즘을 만들 수 없었습니까?
mbomb007

1
@ anon3202 글쎄, 그것은 당신이 어디에 있는지 측정 할 수 있기 때문에 트랙 레이아웃에 대한 더 많은 정보를 줄 것입니다. 본질적으로, 우리는 봇에 대한 인터페이스를 단순하게 유지하고 순전히 로컬 문제로 만들려고 노력했습니다. 여기에서 글로벌 진보에 가장 적합한 로컬 솔루션을 배우기 위해서는 게놈이 필요합니다.
Martin Ender

1
@matovitch Gory 세부 정보의 전체 주문 섹션 섹션 5 참조 (전체 사양) :'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
C ++ 코드를 조정하여 샘플 평균, stddev, stderr 및 99 % conf-interval ( "형상"log / exp 이전)을 표시하고 놀라운 발견을했습니다. "Blind Faith"응답은 50 회 실행 후 "샘플 평균 116529 +-2.78337e + 010 (99 %) stddev = 7.77951e + 010"이었습니다. 신뢰 구간을 50 %로 떨어 뜨려도 문제가 전혀 개선되지는 않습니다. 기하 평균은 "159.458 +-117262 (99 %) stddev = 32.6237의 평균"(800 점 이전의 업데이트)
Mooing Duck

1
나는 돌연변이율에 대한 실험을 해봤는데 확률이 0.01에서 .0227로 증가하면 10 %의 확률로 DNA를 얻을 수 있다면 도전이 더 흥미롭고 컨트롤러가 훨씬 빨리 실행될 것이라고 생각합니다. 돌연변이는 현재 값으로 37 % 대신 변하지 않았습니다. 이것은 어리석은 인구 폭발을 피하고 (결과적으로 많은 계산 시간을 절약합니다) 불충분 한 다양성으로 인한 많은 실패를 방지합니다. 개인의 점수는 낮지 만, 더 많은 런이 더 많은 승자를 생산하기 때문에 세계 평균이 상승하는 경향이 있습니다.

답변:


37

맹신-C ++-2,000 회 이상 800 (!) 이상 득점

신비한 트랙 피드백과 효과적인 벽걸이 방지 기능을 갖춘 컬러 코딩 게놈

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

샘플 결과 :

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

feersum의 자발적으로 긴 테스트를 기반으로, 2000 회 실행은 충분히 안정적인 결과를 생성하기에 충분합니다.
수정 된 컨트롤러는 각 실행 후 현재 기하 평균을 표시하므로 지난 50 회 실행의 변동이 비교적 작다는 것을 시각적으로 확인했습니다 (+ -10 포인트).

이 동물들이 똑딱 거리는 이유

각 색상에 동일한 우선 순위를 부여하는 대신 다음과 같은 가능한 값을 고려합니다.

  1. 좋은 -> 쥐가 안전하게 갈 수 있다고 생각합니다.
  2. 나쁜 -> 쥐가 가지 않을거야
  3. 함정 -> 쥐는 함정 의 위치가 불량한 것으로 간주 하고 세포는 함정이 양호 함을 나타냅니다 .
    이름을 바꾸기에는 너무 게으르지 만 실제 함정, 벽, 텔레 포터의 위치를 ​​의심하지 않는 방랑자를 불쾌한 장소로 보내거나 심지어 죽은 자의 입구까지 보내는 것을 나타내는 "위험 감지기" -종료. 요컨대, 현명한 쥐가 오히려 가지 않는 곳.

좋고 나쁨은 유전자 (예를 들면 2 비트 저장을 11하고 10), 그러나 트랩은 4 비트 (필요한 0ttt곳에는 ttt가능한 8 "위험한"위치 중 하나를 나타낸다).

(즉, 그 의미는 이후 고정 된 위치에있는 것으로 각 컬러 - 코딩 유전자를 필요로하는 완전히 다른 게놈 내로 혼입 된 유지) 일치하는 각각의 유전자를 유지하기 위해서는, 모든 값이 4 비트의 부호화 (매우 좋은 로 부호화 11xx불량10xx), 총 16 * 4 = 64 비트

나머지 36 비트는 "반벽 방지 기능"으로 사용됩니다 (나중에 자세히 설명). 25 개의 주변 색상이이 36 비트의 인덱스로 해시됩니다. 각 비트는 선호되는 수직 방향 (위 또는 아래)을 나타내며 두 ​​셀 사이에 선택이있을 때 사용됩니다.

전략은 다음과 같습니다.

  • 게놈에 따라 각 색상을 디코딩합니다 (또는 오프 트랙 "나쁜"셀에 대한 직접 컨트롤러 보고서)
  • 즉각적인 주변지도 (3x3 셀, 8 개의 이웃) 구축
  • 주변 환경의 서명을 계산합니다 (비 추적 셀을 제외한 25 가지 색상의 해시).
  • 서명에서 선호하는 수직 방향을 선택하십시오 (36 개의 해시 버킷 중)
  • 목표에 가장 가까운 사람들부터 시작하여 선호하는 수직 방향으로 먼저가는 "좋은"것으로 추측되는 이웃으로 이동하십시오.
  • "좋은"이웃을 찾을 수없는 경우, 한 셀을 뒤로 이동 시키십시오 (따라서 불행한 사고의 희생자가 될 수 있으며 모든 속도에서 체력을 높이 지 않는 것이 좋습니다)

설치류 여러분, 당신의 종류의 원수를보십시오

무서운 벽 순간 이동 루프

개체군에게 일어날 수있는 최악의 일은 아직 승자를 얻지 못했지만 많은 쥐들이 벽에 부딪 히거나 무한한 순간 이동 고리 안에 갇혀 번식을 위해 우세한 기회를 가질 수있는 목표에 가깝습니다 .
쥐가 함정에 찌그러 지거나 벽으로 순간 이동되는 것과는 달리,이 설치류는 나이가 들어서야 죽을 것입니다.
그들은 사촌이 ​​처음부터 3 세포를 고집하는 것에 비해 경쟁 우위가 없지만, 게놈이 지배적이 될 때까지 크레 틴 생성 후 번식 세대에 충분한 시간을 가질 것이므로 아무런 이유없이 유전 적 다양성을 심각하게 해칠 것입니다.

이 현상을 완화하기 위해,이 나쁜, 나쁜 쥐의 자손이 조상의 단계를 따르지 않도록하는 것이 더 좋습니다.
수직 방향 표시는 길이가 1 비트 (기본적으로 "이러한 환경에서 먼저 오르 내리기"라고 함)이며 경로에 영향을 줄 수있는 약간의 비트가 있으므로 돌연변이 및 / 또는 크로스 오버는 눈에 띄는 영향.
많은 자손들은 다른 행동을 할 것이며 같은 벽에 머리를 부딪치지 않을 것입니다 (굶주린 조상의 시체 중).
여기의 하위 특징은이 적응증이 쥐의 행동에 지배적 인 요소가 아니라는 것입니다. 대부분의 경우 색상 해석이 여전히 우선합니다 (위 / 아래 선택은 실제로 "좋은"두 가지가있는 경우에만 중요합니다.그리고 무엇 쥐 무해한 컬러로 보는 것은 벽에 캐스팅 기다리고 텔레 포터가) 없습니다.

왜 작동합니까?

나는 아직도 왜 정확한지 모른다.

해결되지 않은 수수께끼로 남아있는 행운의 절대 스트로크는 트랩 매핑 논리입니다. 의심의 여지없이 성공의 초석이지만 자체 신비한 방식으로 작동합니다.

코딩을 사용하면 무작위 게놈이 25 % "양호한", 25 % "나쁜"및 50 % "트랩"색상 식별자를 생성합니다.
"트랩"식별자는 5x5 환경과 관련하여 "좋은"평가와 "나쁜"평가를 차례로 생성합니다.
결과적으로, 주어진 위치에있는 쥐는 안정적이고 상황에 맞는 "go / no go"색상의 혼합으로 세상을 "볼"것입니다.

꽤 성공적인 안티 뱅킹 메커니즘이 나타내는 것처럼, 트랙의 최악의 요소는 끔찍한 벽입니다 (그리고 텔레 포팅 루프의 사촌이지만, 이것이 덜 일반적이라고 생각합니다).

결론은 성공적인 프로그램은 무엇보다도 목표에 도달하지 않고 느린 기아로 이어질 수있는 위치를 감지 할 수있는 쥐를 진화시키기 위해 관리해야한다는 것입니다.

벽을 나타내는 두 가지 색상을 "추측"하지 않아도 "트랩"색상은 쥐가 벽을 "보았 기"때문에가 아니라 몇 가지 장애물을 우회하도록하여 벽 회피에 기여하는 것으로 보입니다. 이 특정 환경에서 특정 벽 세포.

비록 쥐가 목표를 향해 나아가려고 노력하더라도 (가장“유용한”함정 지표는 앞의 위험을 나타내는 지표라고 생각할 수 있습니다), 나는 모든 함정 방향이 거의 같은 영향을 미친다고 생각합니다. 쥐 앞의 2 개의 세포는 쥐가 그 바로 위에 서있을 때 "앞으로 위험"을 나타내는 것과 같은 영향을 미칩니다.

이 믹스가 게놈을 성공적으로 수렴시키는 특성을 갖는 이유는 불행히도 내 수학을 초월합니다.

나는 벽을 막는 제지에 더 편하다. 이것은 내 예상보다 훨씬 높지만 계획대로 작동했습니다 (점수에는 기본적으로 4가 곱해졌습니다).

컨트롤러를 많이 해킹하여 일부 데이터를 표시했습니다. 다음은 몇 가지 실행입니다.

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

여기에 슈퍼 랫트의 품종이 일찍 나타났습니다 (트랙은 아마도 직선으로 달릴 수 있었고 첫 세대의 운이 좋은 쥐는 그것을 이용할 수있는 올바른 DNA를 가지고있었습니다). 결국 표본의 수는 약 100.000 쥐의 이론적 최대치의 약 절반입니다. 이는 거의 절반의 동물이이 특정 트랙에서 무기한 생존 할 수있는 능력을 얻었음을 의미합니다 (!).
물론 결과 점수는 계산 시간과 마찬가지로 단순하지 않습니다.

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

여기서 우리는 직장에서 게놈 정제를 볼 수 있습니다. 마지막 두 게놈 사이의 계통이 명확하게 나타납니다. 좋은나쁜 평가가 가장 중요하다. 트랩 표시는이 중 하나 "유용한"로 안정 될 때까지 진동하는 것 트랩 또는에 돌연변이 좋은 또는 나쁜 .

색상 유전자에는 몇 가지 유용한 특성이 있습니다.

  • 그것들은 독립적 인 의미를 지니고 있습니다
    (특정한 색은 특정한 방식으로 처리되어야합니다).
    각 색 코딩은 색이 실제로 결정적인 색이 아닌 한 행동을 크게 바꾸지 않고 완전히 다른 게놈에 던져 질 수 있습니다. 무한 루프로 이어지는 벽 또는 텔레 포터).
    가장 우선적 인 색상은 어디로 이동할지 결정하는 데 사용되는 유일한 정보이기 때문에 기본 우선 순위 코딩에서는 그렇지 않습니다. 여기서 모든 "양호한"색상은 동일하므로 "양호한"목록에 추가 된 특정 색상은 영향을 덜받습니다.
  • 이들은
    양호 / 불량 코딩이 4 개 중 2 개의 유효 비트만을 갖는 돌연변이에 대해 비교적 탄력적 이며, 트랩 위치는 래트 거동을 크게 변화시키지 않으면 서 대부분 변경 될 수있다.
  • 그것들은 작기 때문에 (4 비트) 크로스 오버에 의해 난파 될 확률은 매우 낮습니다.
  • 돌연변이는 의미있는 변화에 무해
    하다 함정) 또는 극적인 것 (색상이 벽을 나타내는 경우 새 쥐가 어딘가에 갇힐 가능성이 큼).
    "트랩 (trap)"으로 뒤집는 유전자는 래트를 필수 색상으로부터 빼앗거나 눈에 띄는 효과가 없다.
    트랩 위치의 돌연변이는 실제로 트랩 (또는 해로운 것)이있는 경우에만 중요하며, 상대적으로 작은 확률을 갖습니다 (1/3과 같이 말하겠습니다).

마지막으로, 마지막 36 비트는 쥐가 막히는 것을 피할뿐만 아니라 쥐를 트랙에 더 균등하게 퍼뜨리는 데 도움이됩니다. 따라서이기는 게놈이 등장하여 색상 코딩 부분을 통해 지배적이 될 때까지 유전 적 다양성을 보존합니다.

추가 작업

나는이 작은 동물들이 매력적이라고 ​​말합니다.
이 훌륭한 도전에 기여한 모든 분들께 다시 한번 감사드립니다.

성공적인 쥐의 조상과 같이 더 중요한 데이터를 표시하기 위해 컨트롤러를 더 도살하려는 생각입니다.

나는 또한이 쥐들이 실제로 활동하는 것을보고 싶어하지만, 언어의이 C ++ b ** ch는 (다른 많은 것들 중에서도) 이미지를 애매하게 만드는 것을 혼란스러운 일로 만든다.

결국, 나는 트랩 시스템에 대한 최소한의 설명을 만들고 그것을 개선하고 싶습니다.

컨트롤러 해킹

누군가 관심이 있다면 컨트롤러에 수정 한 내용을 게시 할 수 있습니다.
그들은 더럽고 저렴하지만 일을합니다.

나는 GitHub에 정통하지 않으므로 단순한 게시물을 거쳐야합니다.


16
10,000 게임에서 208.14 점을 얻었습니다. 1000으로 테스트하려고 시도했지만 추가 0을 입력했다고 알지 못했기 때문에 7 시간 이상이 걸렸습니다.
feersum

LOL 감사합니다. 내 두 번의 1000 회 실행과 비교하면 약 2000 회 실행하면 안정적인 결과를 얻을 수 있습니다.

무엇을 ^^v^vvv^^^vv^^v^vvv^v^^vvvv^^^^^^^^^의미합니까? 나머지는 추측 할 수 있지만 그 비트에 문제가 있습니까?
Mooing Duck

나는 한 번에 하나의 쥐를 달리는 별도의 "디버그"컨트롤러를 만드는 것을 고려하고 있었고, 새로운 쥐가 생성 될 때마다 부모와 자식의 DNA를 보여줍니다 (사용자 정의 기능을 통해). 쥐가 어떻게 작동하는지 훨씬 쉽게 검사 할 수 있습니다.
Mooing Duck

2
이는 36 개의 "위 / 아래"표시기 비트를 나타내지 만,이 예에서 승리 한 DNA는 이미 우세 해져서 크게 변하지 않습니다.

18

단단한 신자-C ++-(개선 된 텔레 포터) : 2000 회 실행시 10.000+

(이것은 맹목적인 믿음 의 진화 이므로, 당신은이 벽보다 먼저 다른 성벽을 올라가고 싶을 것입니다)

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

에피소드 IV : 그리드에 베어링 맞추기

결과

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

g ++ / MinGW와 3 개의 스레드로 전환했습니다.
GNU에 의해 생성 된 코드는 Microsoft보다 두 배 이상 빠릅니다.
놀라운 STL 구현이 무엇인지 궁금합니다.

순간 이동기

순간 이동기 효과는 위치에 따라 크게 달라집니다. 지금까지 나는 텔레 포터를 항상 좋거나 (빈 공간으로 본다) 또는 항상 나쁘다 (벽으로 보았 기 때문에 설치류가 그것을 가져 가지 않도록).

너무 조잡한 모델입니다.
주어진 순간 이동기는 목표에서 몇 세포가 나올 때까지 쥐를 앞으로 밀 수 있지만, 같은 순간 이동기가 있으면 쥐를 보드 밖으로 던질 수 있습니다.
그러한 텔레 포터는 (같은 x 위치로 "걸을 때"보다 체력이 더 빨리 증가하기 때문에) 통과 성으로 인식 될 가능성이 높으며, 지배적 인 게놈의 일부가되어 "항상 안전"하다고 믿는 거의 모든 쥐를 죽입니다.
쥐는 자신의 X 위치를 알 수있는 방법이 없기 때문에 이러한 위험한 텔레 포터를 탐지 할 수있는 유일한 해결책은 상황에 맞는 데이터 (예 : 5x5 컬러 그리드)를 기반으로 쥐를 밟을 것인지 결정하는 것입니다.

이를 위해 4 가지 유형의 색 유전자를 정의했습니다.

  • 위험 트랩 탐지기
  • 트랙의 아무 곳이나 비우기 가능
  • 트랙의 어느 곳에서나 금지 된 블록
  • 주변에 따라 비어 있거나 차단 된 것으로 보임

아이디어는 바로 8 이웃을보고 텔레 포터를 구별하려고합니다. 주어진 위치에 8 개의 동일한 이웃이있을 확률이 매우 낮기 때문에 각 텔레 포터의 고유 한 인스턴스를 식별 할 수 있어야합니다.

8 개의 이웃하는 색상을 결합하여 미로의 위치에 따라 변하지 않는 로컬 서명을 형성 할 수 있습니다. 불행하게도, 8 개의 이웃은 3x3 비전 내부 사각형 내에 위치한 셀에서만 볼 수 있으므로, 시야의 가장자리에서 서명이 정확하지 않을 것입니다.
그럼에도 불구하고, 이것은 우리에게 즉시 이웃에서 일정한 상황에 맞는 정보를 제공 할 것입니다. 이것은 텔레 포터를 성공적으로 항해 할 확률을 높이기에 충분합니다.

유전자는 2 비트 가변 필드를 갖는다.
주어진 텔레 포터 로컬 서명의 경우 셀을 통과 할 수없는 것으로 간주 될 가능성은 4 분의 1 입니다. 필드의 각 값은이 네 가지 가능성 중 하나를 선택합니다.
결과적으로, 이 2 비트 의 유전자 돌연변이는 색상의 4 가지 가능한 맥락 적 의미를 순환합니다.

게다가, 가장 중요한 추측은 여전히 ​​벽과 함정입니다. 이것은 쥐가 벽과 함정의 위치를 ​​알게 된 후에 만 텔레 포터 탐지를 허용해야한다는 것을 의미합니다 .

로컬 시그니처를 가끔씩 만 업데이트하면됩니다. 지역 서명을 업데이트하는 현재 기준은 잠재적 텔레 포터로 식별되는 색상의 주변에 있습니다.

이 코딩은 색상 유전자 당 5 비트 및 그룹 유형을 사용하여 유효하지 않은 3 비트를 해제하여 0..7 값을 인코딩합니다.

  • 4 위험
  • 4 개 비우기
  • 4 블럭
  • 4 빔

각 빔 유전자는 1/4의 확률로 블록으로 간주되고 3/4의 확률로 비어있는 것으로 간주되므로 평균적으로 1 개의 블록과 3 개의 빈이 나타납니다.

따라서 16 가지 색상의 랜덤 스프레드로 표현 된 평균 비율은 다음과 같습니다.

  • 4 위험
  • 7 개 비어 있음
  • 5 블럭

이 믹스는 지금까지 최고의 결과를 제공하는 것으로 보이지만 조정하지는 않았습니다.

유전자 변이

한 가지 확실한 점은 유전자 유형을 나타 내기 위해 선택한 코드 값이 중요하다는 것입니다. 두 값을 반전 시키면 2000 포인트 이상이 소요될 수 있습니다.

여기에 왜 또 내 수학을 넘어서는 이유가 있습니다.

내 생각에 한 유형에서 다른 유형으로의 돌연변이 확률은 균형을 이루어야하거나 Markow 행렬과 같이 누적 확률은 값이 들어오는 전이 확률이 가장 높은 하위 집합으로 제한하는 경향이 있습니다.

구조 경로

경로는 방문한 세포의 수를 극적으로 감소시켜 목표를 달성 할 가능성이 가장 높은 테스트 만 허용합니다. 따라서 일부 빈번한 데드 엔드 (dead end)를 피할 수있을뿐만 아니라 잘못된 색상 코드도 이전에 발견 될 가능성이 훨씬 높습니다.
결과적으로 수렴 시간이 크게 줄어 듭니다.

그러나 이것은 게놈이 트랙을 제대로 표현할 수없는지도를 해결하는 데 도움이되지 않습니다.

모론은 어떻게해야합니까?

트랙을 시각적으로 살펴본 후, 벽 앞에만있는 것처럼 보이지만 앞으로 나아가려고하는 기본 전략이 실제로 보류하는 것보다 더 나은 이유를 이해했습니다.
"벽"은 실제로 많은 불행한 결과를 만들어내는 텔레 포터에있을 수있다. 게놈은 그것들을 절대로 막을 수없는 장애물로 맵핑하지만,이 나쁜 텔레 포터의 특정 사례는 긍정적 (또는 최소한 치명적이지 않은) 효과를 가질 수있다. 따라서 뒤로 이동하지 않고 가져 가면 승리의 길을 찾을 가능성이 높아집니다.

초기 수렴

돌연변이 속도가 약간 낮습니다 (적어도 내 설치류의 경우).

현재 0.01 설정은 돌연변이 과정에서 DNA가 37 %의 확률로 생존 할 수 있습니다. 모수를 0.0227로 변경하면이 확률이 약 10 %로 낮아집니다.

신비한 공식은 P 1 비트 돌연변이 = 1-P 전체 게놈은 1/100 이며 100은 게놈 비트 길이입니다.

예를 들어 10 % 확률의 경우 P 1 비트 돌연변이 = 1-0.1 1/100 = 0.0277
5 % 확률의 경우 P = 1-0.05 1/100 = 0.0295
수식을 거꾸로 하면 0.01은 37 %의 확률을 나타냅니다 돌연변이에 의해 변하지 않습니다.

10 % 확률로 정확히 동일한 테스트 (고정 된 임의의 시드 시퀀스 사용)를 다시 실행합니다.
많은지도에서 이전의 실패는 (제한된) 성공으로 바뀌 었습니다. 다른 한편으로, 엄청난 인구 폭발은 더 적었다 (이것은 계산 속도를 높이는 흥미로운 부작용을 가졌다).
매우 높은 점수 (백만개 이상)가 흔하지는 않았지만 성공적인 실행 횟수는 보상하기에 충분했습니다.
결국 평균은 1400+에서 약 2000으로 상승했습니다.

반대로 P를 5 %로 설정하면 평균은 약 600이됩니다.
돌연변이율이 너무 높아서 쥐를이기는 게놈이 덜 효율적인 변이체로 너무 자주 퍼져 나갔다고 가정합니다.

이것이 어떻게 작동 하는가

텔레 포터 감지기가 추가됨에 따라 실패한 게임 수 (점수 <10)가 크게 줄었습니다.
2000 회 실행 시험에서는 실패의 1/3 만있었습니다.
기하 평균은 2900에서 3300으로 증가했지만이 숫자는 개선을 반영하지 못합니다.

빈 색은 종종 빔과 위험 (보통 2 ~ 5)으로 추측됩니다. 게놈은 쥐를 곤경에 빠뜨리는 경로를 막기 위해이 색을 "사용"합니다.

게놈은 트랩을 추측하는 데 매우 능숙합니다 (즉, 쥐가 목표에 도달 할 수있게되면 실제 트랩 감지기를 나타내는 색상은 시간의 약 90 %로 추측됩니다).
또한 텔레 포터를위한 새로운 빔 코드를 사용하지만, 드물게 (아마도 "복잡한"텔레 포터가 트랩보다 덜 일반적이고 다른 빔 / 위험 색상이 이러한 반역자의 마지막 인스턴스에 대한 경로를 차단하기 위해 진화하기 때문입니다).

5000 번 이상의 턴에서 승리 한 게놈이 등장하는 게임의 수에 따라,이 새로운 품종은 증가 된 돌연변이율로부터 큰 혜택을 얻을 것이라고 생각합니다.


트랩, 빈, 벽 및 텔레포트가 짝수이므로 비율을 정확하게 저장하려면 3 비트 만 필요합니다 (트랩 = 벽을 고려하더라도). 또한, 월-반 뱅킹에서 사용되지 않은 트랩 오프셋 비트를 사용한다는 아이디어를 고려 / 삭제 했습니까? 부모로부터 물려받지 않는 것이 목표이기 때문에 실제로 반월 킹에서 모든 비트를 사용할 수 있습니다 . 그들이 유일하다고 생각할 이유는 없습니다.
Mooing Duck

1
@MooingDuck 오프셋 비트 재사용에 대한 아이디어를 테스트했지만 실패했습니다. 두려운 목적으로 정보를 재사용하는 것은 효과가없는 것 같습니다. 예를 들어, 주어진 경로에서 게놈이 적절한 수직 방향을 선택하기 위해 주어진 색의 오프셋 비트가 필요하다고 가정하면,이 색은 더 이상 동일한 데이터에 의존하는 경로를 파괴하지 않으면 의미있는 함정을 나타낼 수 없습니다. 나는 또한 6 비트를 사용하려고했지만 나머지 4 개의 안티 월 뱅커도 너무 부족한 것으로 두려워했습니다.

1
알아두면 좋지만 두 가지 아이디어를 제안했습니다. 하나는 모든 비트를 사용하고 (일부는 재사용), 다른 하나는 벽 / 빈에 사용되지 않은 트랩 오프셋 비트를 사용하는 것입니다. 둘 다 시도 했습니까? (나는 당신이 시도하고 싶지 않다면 완전히 이해하고, 원하지 않는다면 시도하지 않아도됩니다)
Mooing Duck

1
나는 둘 다 시도했지만 둘 다 실패했습니다. 트랩 오프셋은 유전자가 유전자를 사용하지 않더라도 중요합니다.이 유전자는 여전히 트랩 색상으로 변형 될 수 있습니다.이 경우 트랩 오프셋은 가장 수익성이 높은 컨텍스트 비트로 변경 될 수 있으며 오프셋으로서의 의미를 잃을 수 있습니다. . 이제 수익성있는 오프셋 값으로 다시 변경되고 상황에 맞는 지표로 의존 한 쥐의 경로를 파괴합니다. 필자는 그래픽 도구를 사용하여 이러한 진동이 발생하는 것을 보았지만이 문제의 분명한 사례를 보여주는 것은 쉽지 않습니다.

16

ColorScorePlayer, 예비 점수 ≈ 22

이것은 챌린지에서 GIF에서 직장에서 보는 봇입니다.

이것은 개발 단계에서 테스트 봇이었습니다. 게놈을 사용하여 16 가지 색상 각각에 대한 품질 평가 점수를 저장합니다. 그런 다음 가장 높은 점수를 가진 색상으로 이동하고 앞으로 이동하지 않는 앞으로 이동합니다 -1. 동점의 경우, 묶는 셀 사이의 임의의 이동이 선택됩니다.

이 플레이어를 모든 컨트롤러 언어로 포팅 했으므로이를 사용하는 방법에 대한 예제로 작동합니다.

파이썬

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)

루비

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

씨#

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

자바

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

플레이어는 상당히 일관성이 없습니다. 다음은 50 회의 무작위 런입니다.

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

이 도전은 시도하면 정말 재미 있고 간단합니다.

긴 설명으로 연기하지 마십시오.
GitHub를 방문하여 내용을 확인하십시오. :)

C ++ 시뮬레이터는 속도가 매우 좋습니다. 파이썬 프로그램을 C ++로 변환 한 후에도 파이썬 시뮬레이션은 여전히 ​​멈추지 않았습니다.

이것은 ColorScorePlayer의 개선 된 변형입니다. 5x5 뷰를 잘 활용하기 위해 가중 함수를 사용하여 2 단계 이동을 고려합니다. 생존에 더 즉각적인 영향을 미치기 때문에 1 단계 앞으로 이동하면 더 높은 가중치가 부여됩니다. 2 단계 앞으로 이동하면 무게가 줄어 듭니다.

앞으로 이동하려고 시도하지만 안전한 움직임이 보이지 않으면 옆으로 시도하고 ... 다른 모든 것이 실패하면 임의로 뒤로 이동합니다.

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

}

점수:

콘솔이 서로 1을 뿜어내는 것을 볼 때 약간의 1이 있습니다. 생필품이 필요하지만 진보 된 쥐 문명의 징후가없는 행성처럼 ...
가끔씩 급증합니다. :)

흠 ... 분명히 첫 번째 런 배치에 대해 운이 좋았으며 300 +의 기하학적 모양을 얻었습니다. 점수는 실제로 약간 변동합니다. 그러나 어쨌든 더 많은 시뮬레이터를 실행하면 아마도 ≈ 74에 더 가깝습니다.

내 경기 점수 : 6 6 53 1 5 101223 89684 17 2 303418 4 85730 24752 11 1 3482515 39752 1 59259 47530 13 554321 1 563794 1 1770329 1 57376 1 1238704179790 69931 594057 1 69664 59 1 6 37857 1733138 55616 2 1 51704 1 254006 4 24749 1 117987 49591 220151 26 4292194 23 57616 72 67 1 308039 1 103 89258 1 286032 1 5 3 1 5 114851 46143712 5 15 9 80 7425 1 1 1 18383 70122 97238 1 5 2 23104794 1 10476 59245 1204 1112 1 29641 1 314894 18785 1111 1 526001 1 1 27559 29285 3 3128708 70386 30 2 1 208531 331112 61114993 1 15 51997 11146146191 1 31 4 161 422207 1 64 1 1 68594 145434 87763 150187169 185518 1 1 24208 2570 1 537 1 462284 1 55 1111 214365 1 40147 2 213952 1 29 3 1 2144435 5 4502444 72111 1 11 1 774547


1
나는 1000 게임, 좋은 직업으로 74.7의 기하학적 평균을 얻었다.
feersum

8

주교-파이썬, 예비 점수 1.901

주교는 항상 대각선으로 움직여 보드 전체의 주어진 트레킹에서 보드의 절반에 액세스 할 수 없지만 인코딩 할 잠재적 움직임이 적다는 것을 의미하므로 게놈의 각 개별 비트가 움직임을 나타낼 수 있습니다 (주교는 절대 후퇴하지 않습니다). 참조 할 비트는 시편의 앞 (오른쪽) 3x3 제곱 블록을 기준으로 결정됩니다. 주어진 상황에 대한 최선의 움직임은 단지 단일 비트 돌연변이입니다.

이 봇은 처음에는 빨리 배우지 만, 다음 두 가지 문제 중 하나가 발생했을 때 마무리에 도달하기 전에 종종 천장에 부딪칩니다.

  • 보드의 둘 이상의 부분이 동일한 비트에 매핑되지만 다른 이동이 필요합니다.
  • 일부 보드는 대각선 이동만으로는 통과 할 수 없습니다.

암호

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

이러한 제한에도 불구하고, 드문 경우에 주교가 잘 수행하며, 개별 표본이 각각 보드의 여러 바퀴를 완성합니다. 나는 주어진 무릎에서 표본이 보드의 절반에서만 움직일 수 있다고 생각했습니다 (체스 보드의 검은 사각형 또는 흰색 사각형과 동일). 그러나 Martin Büttner가 지적했듯이 텔레 포터는 표본을 검은 사각형에서 흰색 사각형으로 또는 그 반대로 이동할 수 있으므로 대부분의 보드에서 제한되지 않습니다.

(일치 된 텔레 포터 유형에는 두 쌍이 있으며 각각 0.5의 표본이 표본을 검은 색과 흰색 사각형의 다른 절반으로 이동시키는 오프셋을 가질 확률이 있으므로 보드는 시험편을 하나로 제한하는 텔레 포터 만 가지고 있습니다. 랩당 보드의 절반은 0.25입니다.)

점수는 때때로 승리가 마무리에 미치지 못하는 오랜 기간과 함께 산재되어 있음을 보여줍니다.

점수 : 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 12,544 1 2 1 1 1 1 3 7554 1 1 1 1 1


8

런 보너스 플레이어 : 기하 평균 50.35 (5000 게임 테스트)

이 봇은 색상 점수 플레이어와 같은 DNA의 6 비트 섹션을 기반으로하지만 숫자 시스템이 다른 개별 색상으로 사각형의 점수를 매 깁니다. 이 봇은 비트 중 하나가 점수 값을 32만큼 변경하고 다른 비트는 1 만 변경한다는 것은 임의적이라는 생각에 동기를 부여했습니다. n (n + 1) / 2 값을 n 연속 1 비트. 또한 중단을 피하기 위해 무작위 화 메커니즘을 추가합니다. 30 분의 1의 확률로 무작위 전진합니다.

비교를 위해, 컬러 스코어 플레이어는 몇 번의 1000 게임 테스트에서 30-35 점을 얻었습니다. 흥미롭게도, 컬러 스코어 플레이어의 최대 게임 점수는 3-5 백만의 범위에 있었고 달리기 보너스의 최대는 200,000에 불과했습니다. Run-bonus는 0이 아닌 점수를 더 일관되게 얻음으로써 로그 평균 점수 시스템의 이점을 얻습니다.

C ++ 컨트롤러에서 6 개의 스레드로 5000 개의 게임을 실행하는 데 약 20 분이 걸렸습니다.

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

호기심에서 5000 트랙 테스트에 얼마나 걸렸습니까? 쥐들은 1000 트랙을 완성하기 위해 한 시간 이상이 필요하므로 테스트 케이스를 재현하기 위해 밤새 컴퓨터를 작동시켜야합니다.

@kuroineko 귀하의 질문에 대한 답변은 이미 내 대답에 있습니다.
feersum

앗 미안 해요. 그런 다음 PC에서 코드를 시도하여 속도 차이에서 하드웨어가 어떤 부분을 차지하는지 확인합니다. MSVC 대신 gcc를 사용해보십시오. 몇 가지 다른 계산이 많은 코드에서 MSVC보다 30 % 성능이 향상되었습니다.

귀하의 코드는 4 개의 스레드가있는 i3-2100@3.1GHz에서 1000 트랙에 대해 20 분이 조금 넘게 실행되었습니다. 점수는 약 56 입니다. 내 PC가 귀하의 PC보다 5 배 느리고 내 코드는 주어진 컴퓨터에서 약 6 배 느리다는 것을 의미합니다 (그러나 점수가 높을수록 기계적으로 더 긴 계산 시간을 의미합니다). 새 PC를 구입하기에는 너무

8

StarPlayer | C ++ | 점수 : 162 (500 회 게임 기반)

이 플레이어는 A *를 사용하여 최선의 길을 찾습니다. ColorScorePlayer와 동일한 방식으로 가중치를 지정하고 뷰의 오른쪽 가장자리로 길을 찾습니다. 구현은 내가 한 것 중 가장 예쁘지는 않지만 적어도 너무 느리지는 않습니다.

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

샘플 점수 :

4 92078111 10 2314 2314314 5 24925 1 126502 1 24 1097182 39 1 47728 227625 137944 15 1 30061 1 1 3171790 19646 10 345866 11 829756 425 6699 22 8 1 6 6 104889 125608 1


1
1000 게임에서 나는 133.2의 점수를 얻었습니다.
feersum

7

WallGuesser-1000 게임 테스트에서 113.266 점을 획득했습니다

부호화

정말 간단한 6 비트 / 컬러 인코딩을 만들었습니다. 색상을 해독하려면 [n]

  • 게놈의 n 번째 비트마다 최대 96 개 합계
  • 합계 점수가> = 4이면이 사각형이 차단되었다고 말합니다.
  • 합계 점수가 <= 4 인 경우 최종 점수는 합계 점수의 2 ^입니다.

게놈 전체에 색의 비트를 분산시켜 두 부모의 비트가 각 색에 사용될 가능성을 높이고 있습니다.

운동

나는 (아주 효율적이지 않다) A * 기반 검색을 사용하여 오른쪽 가장자리 사각형 중 가장 저렴한 경로를 찾습니다. 색상이 "차단됨"에 매핑되면 검색에 의해 입력되지 않습니다. 검색에서 경로를 찾을 수 없으면이 쥐가 재생산하기에 적합하지 않다고 가정하고 하나를 왼쪽으로 이동하여 끝냅니다.

부적합한 쥐의 수를 줄이기

내 게놈은 어떤 사각형이 벽이나 후방 텔레 포터인지 추측 할 수 없기 때문에 추측이없는 쥐 (차단 된 색이 없음)는 적합하지 않습니다. 색상이 차단 된 것으로 표시되지 않은 경우 이러한 쥐를 제거하려고 시도하면 모든 색상이 차단 된 것으로 표시되며 쥐는 항상 왼쪽으로 이동합니다.

할 것

현재 행동에 임의성이 없기 때문에 쥐가 걸리기 쉽습니다.

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

흠, 이것은 나를 위해 컴파일되지 않습니다 g++ -std=c++11 .\wallguesser.cpp -O2 -o .\wallguesser.exe. 많은 오류가 발생하지만 첫 번째 오류는 다음과 같습니다.\wallguesser.cpp:47:19: error: 'dna_t' has no member named 'at' if (d.at(i) == true){
Martin Ender

문제 없습니다, 단순히 변경하지 at위해 []그것을 해결합니다.
feersum

7

FITTEST-기하 평균 점수 : ~ 922 (2K 실행)

내 접근 방식은 다음과 같습니다.

  1. 어떤 종을 죽이고 원하는 행동을 정의 하는지 파악하십시오 (기능적)
  2. 코드에서 원하는 동작 구현 (기술적)
  3. 그것에게주는 우선 순위를 . 다른 원하는 행동보다 더 중요하거나 덜 중요합니까?
  4. 솔루션의 매개 변수를 조정하여 기하 평균 점수를 최적화 하십시오.

동일한 50 개의 시드로 2000 개가 넘는 매개 변수를 테스트했습니다. 가장 유망한 세트를 선택하고 250 개의 동일한 종자를 사용하여 점수를 매겼으며 순위가 가장 높은 종은 다음 테스트 라운드의 입력이었습니다. 그래서 mbomb007 사용자가 제안한 대로이 문제에 대한 최적의 유전자 알고리즘을 찾기 위해 유전자 알고리즘만들었습니다 .

원하는 행동 :

  1. 종들은 어떤 색이 안전 하고 어떤 이 나쁜지를 배워야 합니다.
  2. 종은 주로 3 개의 세포를 기준으로 어디로 이동할 것인지 결정하는데 초점을 두어야하지만 , 좋은 움직임이 없다면 수직 또는 후진 움직임 을 고려해야합니다.
  3. 그 종은 또한 그 주변의 8 개 세포를 넘어서는 것을보고 의사 결정에 정보를 활용해야합니다.
  4. 종은 함정식별하는 법을 배워야 합니다 .
  5. 일부 종들은 벽이 좋다고 잘못 생각하고 항상 벽으로 이동하려고하므로 벽 앞에 붙어 있습니다. 그들이 그 시점에서 가장 적합한 점수를 가진 종이라면 벽에 대한 잘못된 가정을 가진 DNA는 신생아에게 여러 번 복제됩니다 . 시간이 지나면 모든 종들이 벽 앞에 갇히고 그 어느 것도 점수를 올리는 목표에 도달하지 못합니다. 바보를 막는 방법?

데이터 저장 방법 :

우리는 종들이 사물을 배우고 환경에 적응하고 가장 적합하기를 원합니다. 학습 내용을 어떻게 든 저장할 수 있다면 불가피하게 작동합니다. 학습은 100 DNA 비트에 '저장'됩니다. 우리는 DNA의 가치를 바꿀 수 없기 때문에 이상한 저장 방법입니다 . 따라서 우리 는 DNA가 이미 나쁜 행동과 좋은 행동에 대한 정보를 저장 한다고 가정 합니다. 특정 종의 경우 정확한 정보가 DNA에 저장되어 있으면 DNA를 사용하여 빠르게 새로운 종을 만들게됩니다.

기하 평균 점수가 정보 저장 방법에 민감하다는 것을 알았습니다. DNA 100 비트 중 첫 4 비트를 읽고이를 정수 변수에 저장하려고한다고 가정 해 봅시다. 여러 가지 방법으로이 작업을 수행 할 수 있습니다.

  1. 10 진수 데이터 저장 : '내장' dnarange기능 을 사용하여 예 : 10114 비트는`1x2 ^ 3 + 0x2 ^ 2 + 1x2 ^ 1 + 1x2 ^ 0 = 15가됩니다. 가능한 값 (4 비트) : [0, 1 , 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
  2. 줄무늬 데이터 저장 :dnaStreakRange 함수 (아래 정의) 를 사용하여 예 : 4 비트 1011이됩니다 1x1 + 0x1 + 1x1+ 1x2 = 4. 가능한 값 (4 비트) : [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. 비트 섬 데이터 저장 :dnaCountRange 함수 (아래 정의) 를 사용하여 예 : 4 비트 1011이됩니다 1x1 + 0x1 + 1x1 + 1x1 = 3. 가능한 값 (4 비트) : [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;
}

저장 방법의 차이점은 다음과 같습니다.

  • 10 진수 저장 방법은 DNA 의 단일 비트 변경취약합니다 . 비트 섬 값이 1011에서 0011로 변경되면 그 값은 3에서 2로 변경되며 이는 사소한 변경입니다.
  • 10 진수 저장 방법은 동종 입니다. 가능한 각 값은 동일하게 변경됩니다. 4 비트 저장 메모리 블록에서 15의 ​​값을 읽을 가능성은 1 / 16 = 6 %입니다. 킬 저장 방법은 균일하지 않다 . 연속 4 비트 값이 6보다 작거나 같을 확률은 6이 (15-3) / 16 = 81 % (0111,1110,111을 제외한 모든 16 개의 조합)입니다. 분포의 모양을 보여주는 비주얼 아래. 파란색 화살표에서 볼 수 있듯이 4 비트 행이 6 이하일 가능성은 81 %입니다. 4, 5 및 6 비트 긴 이진 숫자에 대한 10 진수, 연속 및 비트 저장 유형의 분포 시각화

솔루션의 우선 순위를 정하십시오.

ColorScorePlayer가 동일한 점수로 2 개의 전진 이동을 식별하면 임의의 선택이 이루어집니다. IMHO, 당신은 절대 함수 v.rng.rint()기능을 사용해서는 안됩니다 . 대신이 같은 기회의 기회를 2 차 효과에 대한 솔루션을 평가하기위한 후크로 사용해야합니다.

1 차 효과가 가장 우선 순위가 높습니다. 동일한 점수에 도달하면 우선 순위가 2 인 솔루션이 우선합니다. 솔루션의 매개 변수를 조정하면 동일한 점수가 발생할 확률에 영향을 주어 우선 순위 1 및 우선 순위 2 솔루션의 가중치를 변경할 수 있습니다.

원하는 행동의 구현

안전한 색상 알아보기 :

  • 16 색 중 33 %가 나쁘기 때문에 이동 점수가 63/3 미만이면 이동이 허용되지 않습니다. 따라서 threshold = 63/3=2163은 6 비트의 최대 점수이고 33 %는 1/3입니다 (위 그래프에서 찾아 볼 수 있음).

잘 움직일 수없는 경우 수직 또는 후방으로 이동하십시오.

  • 전진 이동이 허용되지 않으면 수직 이동은 동일한 방식으로 서로 비교됩니다. 세로 이동도 허용되지 않으면 뒤로 이동 순위가 매겨집니다. 이것은 weightMove변수 를 통해 달성됩니다 .

그 밖의 것을보십시오 :

  • 2 개 또는 3 개의 이동이 동일한 점수를 갖는 경우, 해당 이동 주위의 3x3 상자 는 ( 변수 를 통해) 최상의 옵션이 무엇인지 결정 (비아 x2y2루프)합니다 mainSubScore. 그 3x3 상자에서 가장 오른쪽 열이 선행됩니다.
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};
}

점수 : 123 (2K 회)

처음 50 점 (18 경기는 1 점 만점) :

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

트랩 식별 :

나는 임의의 게임이 비트 섬 4 저장을 사용하여 끝났을 때 가장 높은 점수를 가진 종의 DNA를 조사했다 (그래서 색상 점수의 범위는 [0,4])

  • 0 점 : 뒤로 텔레포트, 양쪽 벽, 1x 안전
  • 1 점 : 뒤로 트랩 (무해), 순간 이동 뒤로, 1x 안전
  • 득점 2 : 함정 앞으로 (위험), 1x 안전
  • 3 점 : 순간 이동, 5 배 안전
  • 4 점 : 순간 이동, 1 배 안전

이것으로부터 벽과 텔레포트가 정확한 점수를 얻는다는 결론을 내릴 수 있습니다. 트랩은 방향과 원산지 색상에 따라 다르므로 점수는 대상 색상에 따라 결정되므로 식별되지 않습니다. 따라서, 원색에 데이터를 저장할 필요가있다 v(0,0). 이상적인 세계에서는 16 색 x 8 방향 x 3 비트 = 384 비트에 대한 정보를 저장하려고합니다.

불행히도 100 비트 만 사용할 수 있으며 위에서 설명한 솔루션을 위해 메모리가 필요하기 때문에 모두 사용할 수는 없습니다. 따라서 우리는 4 가지 색상 빈을 만듭니다.

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

4 개의 이동 방향 빈

  • 0 : 세로 또는 뒤로 이동
  • 1 : 앞으로 이동
  • 2 : 앞으로 나아가십시오.
  • 3 : 아래로 이동

10 진수 점수가 4 이상 (100,101,110,111) 인 경우 트랩이이 셀과 연관된 것으로 가정되므로 동일한 점수가 발생하면이 이동이 선택되지 않습니다. 따라서 트랩 식별은 2 차 효과이며 '이후의 모습'은 세 번째 우선 순위 솔루션이됩니다.

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

점수 : 580 (2K 달리기)

첫 50 점수 (13 경기는 1 점 만점) :

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

벽에 대한 잘못된 가정은 모론에 의해 신생아에게 여러 번 복제됩니다.

일부 종들은 벽이 좋다고 잘못 생각하고 항상 벽으로 이동하려고하므로 벽 앞에 붙어 있습니다. 그들은 또한 순간 이동기의 무한 루프에 갇힐 수 있습니다. 두 경우 모두 효과는 동일합니다.

주요 문제는 몇 백 번의 반복 후에 일부 유전자가 매우 지배적이라는 것이다. 이것이 '올바른'유전자라면 매우 높은 점수를 얻을 수 있습니다 (> 1 백만 포인트). 이것이 틀렸다면 '올바른'유전자를 찾기 위해 다양성이 필요하기 때문에 당신은 붙어 있습니다.

Morons Fighting : 솔루션 1 : 색상 반전

내가 시도한 첫 번째 해결책은 여전히 ​​매우 다양한 미사용 메모리의 일부를 활용하려는 노력이었습니다. 컬러 메모리에 84 비트를 할당하고 찾기 메모리를 트랩했다고 가정합니다. 나머지 16 비트는 매우 다양합니다. 구간 [0,255]에 값이있는 2 개의 decimal8 변수를 채울 수 있으며이 값은 동종이므로 각 값의 확률은 1/256입니다. 변수는 호출됩니다 inInverseinReverse.

경우 inInverse255 (1/256 기회를) 동일, 우리는 것입니다 색상 점수의 해석을 반전 . 따라서 moron이 높은 점수이기 때문에 안전하다고 가정하는 벽은 낮은 점수를 얻으므로 나쁜 움직임이됩니다. 단점은 이것이 '권리'유전자에도 영향을 미치므로 점수가 매우 낮다는 것입니다. 또한이 inInverse종은 스스로 번식해야하며, 그 종족도 지배적 인 DNA의 일부를 얻게됩니다. 가장 중요한 부분은 다양성을 되 찾는 것입니다.

경우 inReverse255 (1/256 기회를) 동일, 우리는 것입니다 색상 점수의 저장 위치의 순서를 반대로 . 따라서 색상 0이 비트 0-3에 저장되기 전에. 이제 색 15가 해당 위치에 저장됩니다. inInverse접근 방식 의 차이점 은 inReverse지금까지 수행 한 작업을 취소 한다는 것입니다. 우리는 광장 1에 돌아 왔습니다. 게임을 시작할 때와 비슷한 유전자를 가진 종을 만들었습니다 (트랩 찾기 메모리 제외).

최적화를 통해 inInverseinReverse를 동시에 사용하는 것이 현명한 지 테스트합니다 . 최적화 후 점수가 증가하지 않았다고 결론 내렸다. 문제는 우리가 더 다양한 유전자 군을 가지고 있지만 이것은 '올바른 DNA'에도 영향을 미친다는 것입니다. 다른 해결책이 필요합니다.

Morons Fighting : 솔루션 2 : 해시 코드

종은 15 개의 가능한 시작 위치를 가지고 있으며 현재 같은 시작 위치에서 시작하면 정확히 같은 경로를 따라갈 가능성이 너무 높습니다. 그가 벽을 좋아하는 멍청한 사람이라면, 같은 벽에 반복해서 붙어있을 것입니다. 운 좋게도 훨씬 앞쪽 벽에 도달하면 잘못된 가정으로 DNA 풀을 지배하기 시작합니다. 우리가 필요로하는 것은 그의 후손이 약간 다른 길을 따라갈 것이고 (그가 너무 늦기 때문에) 훨씬 앞쪽 벽에 붙어 있지 않고, 더 가까운 벽에 붙어있을 것 입니다. 이것은 해시 코드 를 도입함으로써 달성 될 수있다 .

해시 코드는 고유하게 식별하고 보드의 현재 위치에 레이블 목적이 있어야합니다. 목적은 (x, y) 위치가 무엇인지 알아내는 것이 아니라이 위치에서 조상들이 전에 했던 질문에 답하는 것입니까?

당신 앞에 완전한 보드가 있고 각 5 x 5 셀의 jpg를 정사각형으로 만들 것이라고 가정 해 봅시다. (53-5) x (15-5) = 380 이미지로 끝납니다. 1에서 380까지의 이미지 번호를 드리겠습니다. 우리의 해시 코드 는 1에서 330까지 실행되지 않지만 563, 3424, 9424, 21245 등과 같이 IDS가 누락 된 것과 같은 ID로 표시되어야합니다.

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

프라임 숫자 17와는 31사라 루프의 시작에서 추가 정보를 방지하기 위해 거기에 있습니다. 나중에 해시 코드 를 나머지 프로그램 에 통합하는 방법에 대해 자세히 알아보십시오 .

"무엇보다 보이는지"서브 스코어링 메커니즘을 다른 서브 스코어링 메커니즘으로 대체 할 수 있습니다. 2 개 또는 3 개의 셀이 동일한 주 점수를 갖는 경우 상위 셀을 선택할 확률은 50 %, 하단 셀을 선택할 확률은 50 %, 중간 셀을 선택할 확률은 0 %입니다. 확률은 랜덤 제너레이터가 아닌 메모리의 비트에 의해 결정됩니다 . 같은 방식으로 동일한 상황에서 동일한 선택이 이루어 지도록하기 때문입니다.

이상적인 세계 (우리가 무한한 양의 메모리를 가지고있는 곳)에서 우리는 현재 상황에 대한 고유 해시 코드 ( 예 : 25881)를 계산하고 메모리 위치 25881로 이동하여 맨 위 또는 맨 아래 셀을 선택 해야하는 경우 거기를 읽습니다 같은 점수입니다). 그런 식으로 우리는 정확히 같은 상황에 처하게됩니다 (예를 들어 보드를 두 번째로 여행하고 같은 위치에서 시작할 때)는 같은 결정을 내립니다. 무한 메모리가 없기 때문에 사용 가능한 메모리 크기의 모듈로해시 코드에 적용 합니다. 현재 해시 코드 는 모듈로 연산 후의 분포가 균질하다는 점에서 좋습니다.

자손이 약간 변경된 DNA로 같은 보드를 여행 할 때 대부분의 경우 (> 99 %) 정확히 같은 결정을 내립니다. 그러나 그가 더 멀어 질수록 그의 경로는 그의 조상과 다를 가능성이 커진다. 그래서 그가이 먼 벽에 갇힐 가능성은 적습니다. 그의 조상과 같은 벽에 붙어있는 동안 상대적으로 크지 만 자손이 많지 않기 때문에 그렇게 나쁘지는 않습니다. 해시 코드 접근 방식이 없으면 근처 및 멀리 떨어진 벽에 붙어있는 확률이 거의 같습니다.

최적화

최적화 후, 트랩 식별 테이블이 필요하지 않고 컬러 당 2 비트로 충분하다는 결론을 내렸다. 나머지 메모리 100-2x16 = 68 비트는 해시 코드를 저장하는 데 사용됩니다. 해시 코드 메커니즘이 트랩을 피할 수 있는 것 같습니다 .

15 개의 매개 변수를 최적화했습니다. 이 코드에는 현재까지 조정 된 최상의 매개 변수 세트가 포함되어 있습니다.

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

점수 : 922 (2K 런)

첫 50 점 (9 게임은 1 점 만점) :

112,747 3 1,876,965 8 57 214,921 218,707 2,512,937 114,389 336,9411 6,915 2 219,471 74,289 31116 133,162 1 5 633,066 166,473 515,204 1 86,744 17,360 2 190,697 1 6,122,126,198 2,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692 1,3,69,2,69,3,69 2,3,69 2,3,69,2,99

이것은 내 첫 C ++ 프로그램입니다. 나는 대부분의 당신이 지금 그놈 분석에 배경을 가지고 있습니다. 나는 이것에 대해 정말로 즐겁게 일했기 때문에 주최자에게 감사하고 싶다.

의견이 있으시면 아래에 의견을 남겨주십시오. 긴 텍스트에 대한 사과.


트랩 분석이 꽤 흥미 롭습니다.

예를 들어 12.5 16 비트 단어로 표시되는 25 색 값을 조정하고 모듈로를 사용하는 것과 같은 다른 해시 함수를 사용해 보셨습니까? 나는 소수의 합동이 더 나은 균질성을 제공한다고 확신하지는 않지만 나는 큰 수학자가 아닙니다.

또한 경로 알고리즘 추가를 고려 했습니까? 그것은 게놈에 관계없이 큰 개선 요소로 보인다. 왜냐하면 그것은 승리 위치로 이어질 가능성이 훨씬 더 큰 경로를 통해서만 게놈의 능력을 테스트하는 것에 대한 움직임을 제한 할 것이기 때문이다.

kuroi, 의견 주셔서 감사합니다. 나는 C ++에서 이진 연산에 익숙하지 않기 때문에 xoring을 시도하지 않았습니다. 나는 당신이 12.5 8 비트 단어를 의미한다고 가정합니까? Xoring을 사용하고 있습니까?
Ruut

내 "하드 신자"코드를보고 어떤 종류의 해시 함수를 사용하는지 확인할 수 있습니다. 기본적으로 나는 오프 트랙 셀을 건너 뛰고 온 트랙 색상을 16 비트 워드의 고차 및 저 차수 부분으로 간주합니다. 이러한 모든 단어는 XOR과 함께 레지스터에 누적 된 다음 해시 테이블 크기로 나뉩니다. 해시 최대 값 (65535)이 테이블 크기 (<100)보다 훨씬 높으면 모듈러스는 우수한 확산 성능을 갖습니다. 무작위로 생성 된 광범위한 그리드에서 테스트했으며 균질성이 좋은 것으로 보입니다.

6

패스 파인더, C ++, 예비 점수 35.8504 (50 라운드)

완벽한 점검! 알고리즘을 C ++로 이식하고 약간 조정했지만 쥐가 머리를 벽에 부딪히기 때문에 점수는 여전히 높지 않습니다. 나는 이것을 향상시키는 데 지쳤으므로 지금 당장 내버려 두겠다.


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

설명

일반적인 아이디어는 각 색상을 트랩으로 분류 한 다음 트랩 및 웨이트에 방향을 비 트랩에 할당하고 비전 그리드의 오른쪽 경계에 대한 최소 웨이트 경로를 따르도록하는 것입니다.

게놈의 처음 80 비트에서 각 색상은 5 비트를 사용하여 분류됩니다 abcde. 인 경우 ab = 01색상이 트랩이며 cde방향 (8 가지 가능성)을 인코딩합니다. 인 경우 ab ≠ 01색상이 트랩이 아니며 가중치는 a + b + 2*(c + d + e)입니다.

다음으로, 우리는 3x7 격자를 초기화하는데, 이것은 쥐의 비전 필드를 오른쪽으로 나타내며 "알 수없는"색으로 채워져 있습니다. 비트 80-84는 비-트랩 색상과 유사하게 미지의 셀의 가중치를 인코딩하고, 비트 85-89는 트랩의 공통 가중치를 인코딩합니다. 우리는 그리드를 가중치로 채우고, 가장 짧은 경로를 계산하고, 사이드 스테핑을 막기 위해 쥐 바로 위와 아래의 셀에 약간의 가중치 (비트 90-95로 인코딩 됨)를 추가합니다. 비트 95-99는 목표 가중치를 인코딩합니다.. 만약 경로의 최소 무게가 그 아래에 있다면, 쥐는 아마도 어딘가에 붙어서 무작위로 움직입니다 (그러나 역 추적하지는 않습니다). 그렇지 않으면 최소 무게 경로를 따릅니다. 회피 방지 무게에 따라 작은 확률로, 래트는 대신 2 차에서 최소 무게 경로를 선택합니다. 이것은 벽에 붙어 방지하는 것입니다 (그러나 지금은 잘 작동하지 않는 것 같습니다).


내 컴퓨터에서 구현을 실행하십시오. 몇 시간을 보냈습니다. 평균 점수는 7.848433940863856입니다. pastebin.com/d50GcwnK
Jakube

@Jakube 감사합니다! 그것은 내가 기대했던 것보다 훨씬 나쁘지만 이제 코드를 다시 살펴보면 몇 가지 버그와 다른 이상한 점이 있습니다. 나중에 C ++로 이식하여 직접 분석 할 수 있습니다.
Zgarb

5

LookAheadPlayer C ++ ≈ 89.904

내 원래 생각은 내가 찾고있는 색상과 일치하는 4 비트를 찾고 다음 몇 비트를 점수로 사용하는 것이 었습니다. 이것은 돌연변이로 인해 끔찍한 아이디어로 판명되었습니다.

그래서 돌연변이와 교차로부터 보호하는 방법에 대해 생각했고 QR 코드 디코딩에 대한 작업을 상기시켜주었습니다. QR 코드에서, 데이터는 주어진 데이터의 너무 많은 부분이 파괴되는 것을 방지하기 위해 블록으로 분할되고 스트라이프됩니다.

따라서 ColorScorePlayer와 마찬가지로 DNA를 16 개의 청크로 잘라내어 주어진 점수로 사용합니다. 그러나 각 점수의 개별 비트가 인접하지 않도록 점수가 스트라이핑됩니다. 그런 다음 현재 가능한 움직임과 다음 잠재적 움직임의 점수를 합산하고 가장 좋은 움직임을 선택합니다.

참고 : 이것은 MinGW에서 코딩 / 테스트되었습니다. 최적화 또는 멀티 스레딩으로 컴파일되지 않습니다. 실제 Linux 설치 또는 Visual Studio가 없어서 컴파일러를 사용할 수 있습니다. 나는 내일 아침에 빨리 테스트 할 예정이지만 문제가 발생하면 알려주십시오.

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

단일 비트 플립은 위치에 따라 근본적으로 다른 효과를 가질 수 있기 때문에 게놈 덩어리를 숫자로 해석하는 데 의존 할 수 없습니다. 그렇기 때문에 단순히 16 개의 6 비트 세그먼트를 사용하고 1s 수에서 점수를 매 깁니다. 처음에는 111111좋았고 000000나빴으며, DNA의 초기 구성에서 장기적으로 (한 번 게놈이 완전히 진화되면) 중요하지 않지만 대부분의 세그먼트에는 2-4 개의 세그먼트가 있으므로 9 - (#1 - 3)^2점수 매기기 용도 로 전환 했습니다. 첫 번째 라운드에서 훨씬 더 자유로운 움직임과 더 빠른 진화를 허용합니다.

지금은 7 개의 가장 가까운 이웃 만보고, 색상 점수에 방향 편향을 추가하고 무작위로 가장 높은 방향 중 하나로 이동합니다.

점수 자체는 그다지 높지 않지만 내 동물은 결승선에 도달하고 사례의 3/4에서 1보다 큰 점수를 얻습니다.

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

그리고 100 개 보드에서 샘플 채점

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

기하 평균 점수 : 9.76557


표준 돌연변이율 또는 조정 된 값을 사용하여 한 보드에 대해 언급 한 점수입니까?
trichoplax

"나의 동물은 결승선에 도달하고 사례의 3/4에서 1보다 큰 점수를 얻었습니다."점수 지표가이를 보상했으면 좋겠습니다
Sparr

5

WeightChooser | C # | 1520 게임 점수 : 220.8262

가능한 후속 이동 (노란색)의 평균 무게를 기준으로 다음 다음 이동 (파란색)에 대한 가중치를 계산합니다.

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 (답변이 아니라 C ++ 봇을위한 그래픽 도구)

이 도전이 시작된 이래로 나는 쥐가 실제로 트랙에서 무엇을 향하고 있는지 알아내는 데 어려움을 겪었습니다.
결국 나는 컨트롤러를 해킹하고 트랙의 그래픽 표현을 얻기 위해 사이드 툴을 작성했습니다.
나는 결국 더 많은 해킹을 수행하고 주어진 쥐의 DNA의 가능한 경로에 대한 시각화를 추가했습니다.

지도는 매우 어수선 해졌으며 약간 익숙해 져야하지만 봇의 작동 방식을 이해하면 도움이됩니다.

예를 들면 다음과 같습니다.

샘플 트랙

무엇이든 보려면 확대해야 할 것이므로 다음은 상반기입니다.

하프 트랙

처음에는 쥐의 경로를 봅시다. 각 가능한 시작 위치마다 하나의 경로가 있습니다 (보통 15 개, 때로는 조금 적음). 일반적으로 그들은 합병하는 경향이 있으며, 이상적으로는 단일 승리 장소로 이어집니다.

경로는 큰 직선 화살표로 표시됩니다. 색상은 결과를 설명합니다.

  • 녹색 : 승리
  • 노랑 : 무한 루프
  • 갈색 : 벽 두드리기
  • 빨간색 : 불행한 사고

이 예에서는 12 개의 우승 시작 위치가 있습니다. 하나는 무한 루프로, 2 개는 심한 죽음으로 이어집니다 (트랩으로 순간 이동).

경로 불연속은 순간 이동으로 인해 발생하며 해당 곡선 화살표를 따라갈 수 있습니다.

이제 색깔있는 기호들. 그것들은 16 가지 색의 의미를 나타냅니다 (회색은 쥐가 보는 것을 나타냅니다).

  • 벽 : 광장
  • 순간 이동기 : 4 개의 분기 형 별
  • 트랩 탐지기 ​​: 작은 팔각형

빈 색은 ... 음 ... 비어 있습니다.

텔레 포터는 목적지를 가리키는 나가는 화살표가 있습니다.

트랩 탐지기에는 또한 트랩을 나타내는 화살표가 있으며, 이는 빨간색 원으로 표시됩니다.
9 중 하나의 경우, 트랩은 검출기와 동일한 셀에 위치하며,이 경우 빨간색 원 위에 작은 팔각형이 표시됩니다.

이 예에서 연한 노란색 트랩의 경우입니다.
자주색 트랩 검출기가 표시된 트랩을 가리키는 것을 볼 수도 있습니다.

트랩의 빨간색 원이 벽 아래 숨겨지는 경우가 있습니다. 둘 다 치명적이므로 순간 이동의 경우 결과는 동일합니다.
또한 텔레 포터에 트랩이있을 수 있으며,이 경우 텔레 포터가 우선합니다 (즉, 트랩에 빠지기 전에 래트가 텔레 포팅되어 사실상 트랩을 중화 함).

마지막으로, 회색 기호는 쥐가 보는 것 (즉, 게놈 속성이 색상에 미치는 의미)을 나타냅니다.

  • 벽 : 광장
  • 트랩 검출기 : 팔각형
  • 트랩 : X

기본적으로 회색 사각형에 앉아있는 모든 세포는 쥐에 의해 벽으로 간주됩니다.
빅 X는 트랩으로 간주되는 셀을 나타내며 해당 팔각형은이를보고 한 검출기를 나타냅니다.

이 예에서는 담황색 트랩과 같이 두 벽이 그대로 식별됩니다 (실제로 치명적인 셀을 나타내므로 벽을 나타내는 것으로 표시됨).
연보라 트랩 검출기는 회색 팔각형에있는 것으로 식별되었지만 트랩 위치가 올바르지 않습니다 (일부 빨간색 원은 그 아래에 십자가가 없음을 알 수 있습니다).

텔레 포터 4 개 중 2 개는 벽 (터키석 및 황갈색)으로, 2 개는 빈 셀 (붉은 색 및 노란색)로 간주됩니다.

빈 셀 몇 개는 트랩 탐지기 ​​또는 벽으로 간주됩니다. 자세히 살펴보면,이 "결함 탐지기"는 쥐가 문제를 일으키는 세포로 들어가는 것을 실제로 금지한다는 것을 알 수 있습니다. 따라서 실제 색상과 일치하지 않더라도 확실한 목적을 가지고 있습니다.

코드

글쎄, 그것은 엉망이지만 오히려 잘 작동합니다.

플레이어의 코드에서 볼 때, 주어진 DNA의 의미를보고하는 데 사용되는 추적 함수 인 인터페이스 하나만 추가했습니다. 필자의 경우 3 가지 유형 (벽, 트랩 감지기 및 비어 있음)을 사용했지만 기본적으로 색상 관련 항목을 출력 할 수 있습니다 (또는 게놈 관련 그래픽을 원하지 않으면 아무것도 아님).

나는 컨트롤러를 해킹하여 가능한 모든 위치에서 쥐의 DNA의 "건조한 실행"으로 트랙과 색상 설명을 조합하는 거대한 문자열을 생성했습니다.

봇이 임의의 값을 사용하지 않는 경우에만 결과가 실제로 의미가 있음을 의미합니다. 그렇지 않으면 표시된 경로는 하나의 가능한 결과 만 나타냅니다.

마지막으로,이 모든 추적은 큰 텍스트 파일에 저장되며 나중에 그래픽 출력을 생성하는 PHP 유틸리티에서 읽습니다.

현재 버전에서는 새로운 최대 체력에 도달 한 후 쥐가 죽을 때마다 스냅 샷을 찍습니다. 가장 성공적인 DNA).

누군가 관심이 있다면 코드를 게시 할 수 있습니다.

분명히 이것은 단지 C ++ 로봇 작동, 당신은 추적 함수를 작성해야합니다 일부 게놈 특정 데이터 (내 경우에는 회색 그림)를 표시하려면 아마도 PHP 코드를 수정합니다.
DNA 관련 정보가 없어도 약간의 노력으로 주어진지도에서 DNA가 따르는 경로를 볼 수 있습니다.

왜 중간 출력입니까?

우선, C ++에는 특히 MSVC를 사용할 때 적절한 휴대용 그래픽 라이브러리가 없습니다. Win32 빌드가 일반적으로 사용 가능하더라도 나중에 생각할 때가 많으며 필요한 외부 라이브러리, 패키지 및 기타 유닉스와 같은 멋진 기능은 신체의 일부에서 디시 전을 방지하는 빠르고 간단한 그래픽 응용 프로그램 작성을 끔찍한 고통으로 만듭니다. 명명에서 나.

Qt (C ++에서 이식 가능한 GUI / 그래픽 개발을 간단하고 쾌적한 작업으로 만드는 유일한 환경 인 IMHO를 사용하는 유일한 환경)에 대해 고려했습니다. 아마도 C ++가 부족하고 메모리를 제한하는 놀라운 일을 하는 메시징 시스템 - 목표 C를 추가하기 때문일 것입니다 최소한의 관리), 그러나 이것은 당면한 작업에 대한 과잉처럼 보였습니다 (그리고 코드를 사용하려는 사람은 biggish SDK를 설치해야합니다-노력의 가치는 거의 없습니다).

휴대용 라이브러리를 가정 할 때조차도 말할 필요가 없으며 (그림을 생성하는 데 1 초 정도면 충분합니다), 강력한 강성과 본질적인 혼란으로 인해 C ++은 분명히 작업에 가장 적합한 도구는 아닙니다.

또한 중간에 텍스트를 출력하면 유연성이 크게 향상됩니다. 데이터가 있으면 다른 목적으로 사용할 수 있습니다 (예 : 봇의 성능 분석).

왜 PHP인가?

나는 언어가 매우 간단하고 적응 가능하며 프로토 타이핑에 매우 편리하다는 것을 알게되었다. 나는 극한의 성능을 요구하지 않는 코드 문제를 위해 애완 동물 언어로 만들었습니다.
골프는 끔찍한 언어이지만 골프는 결코 차 한잔이 아닙니다.

나는 파이썬이나 루비가 같은 목적으로 사용하기에 유쾌하다고 생각하지만, 그들과 함께 심각한 작업을 할 기회가 없었으며 최근 웹 사이트에서 작업하고 있었으므로 PHP와 같습니다.

언어를 모르더라도 필요에 맞게 코드를 수정하는 것이 어렵지 않아야합니다. 그냥 $좋은 기본 일 :)처럼 변수 앞에 s를 잊지 마십시오 .


1
도구를 공유 하시겠습니까? 귀하의 답변에 코드 나 링크가 표시되지 않습니다.
Franky

5

SkyWalker-Python-50 게임에서 231 미만

먼저 코딩 한 다음 몇 가지 설명을 작성하십시오. 복사하는 동안 아무것도 끊어지기를 바랍니다.

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

일부 설명

내 의견으로는 주된 차이점은 모든 색상을 코딩하지는 않는다는 것입니다. 대신 중요한 색상 수를 저장하려고합니다. 제 생각에는 그 색은 함정, 벽 및 순간 이동기입니다. 표본은 좋은 세포의 색을 알 필요가 없습니다. 따라서 제 게놈은 다음과 같이 구성되어 있습니다.

  • 트랩의 경우 2 x 8 비트, 처음 4 비트는 색상 번호, 나머지 4는 오프셋
  • 벽용 2 x 4 비트, 색상 만
  • 텔레 포터 용 4 x 7 비트, 색상 용 4 비트, 양호 또는 불량 결정을위한 3 비트

이로 인해 총 52 비트가 사용됩니다. 그러나 나는 3 명의 텔레 포터 결정자의 첫 번째 비트 만 사용합니다 (3이 큰지 확인합니다). 따라서 다른 2 개를 삭제하여 44 비트를 사용했습니다.

매 턴마다 비전의 모든 필드가 나쁜 색인지 (+ -1 -1)-시편이 움직이고 싶지 않은 필드 목록에 추가합니다. 트랩의 경우 해당 트랩 색상에 대해 저장된 오프셋에있는 필드를 추가합니다.

해당 불량 필드 목록을 기반으로 다음 이동이 계산됩니다. 선호하는 필드의 순서는 다음과 같습니다.

  1. 앞으로
  2. 위 또는 아래
  3. 거꾸로 또는 아래로
  4. 뒤로

카테고리의 두 필드가 적용 가능한 경우 하나가 임의로 선택됩니다.

결과

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

생각

  • 나는 50 번의 달리기에 운이 좋았거나 내 전략에 실제로 지혜가 있는지 전혀 모른다.

  • 내 달리기는 절대 이륙하지 않고 최고 점수를 얻는 것처럼 보이지만 목표의 적어도 몇 배를 찾는 경향이 있습니다.

  • 레이스가 끝날 무렵 트랩에 갇히지 않는 작은 무작위성

  • 비 특수 색상은 결코 나쁘지 않다고 생각합니다. 그러나 트랩의 오프셋에있을 때 인스턴스가 잘못 될 수 있습니다. 따라서 트랩, 벽 또는 나쁜 텔레 포터가 아닌 경우 색상을 잘못 표시하면 의미가 없습니다.

  • 벽은 가장 큰 적입니다

개량

먼저, 검은 사각형이 목표에 점점 더 가까이 다가가는 것을 놓칠 수는 있지만 더 많은 테스트를 수행하고 더 의미있는 결과를 얻으려면 C ++ 포트가 필요합니다.

주요 문제 중 하나는 쥐 앞에 나쁜 세포 (또는 표본이 나쁜 것으로 생각하는 세포)가 있으면 쉽게 원에서 위아래로 움직이기 시작한다는 것입니다. 이런 경우에는 2 번의 움직임을 미리 보면서 멈추거나 줄일 수 있으며 다시 되돌아가는 필드로 이동하는 것을 방지 할 수 있습니다.

종종 좋은 유전자를 가진 쥐가 목표에 도달하고 그것을 전파하기 시작하는 데 꽤 시간이 걸립니다. 그런 경우에 다양성을 높이기 위해 전략이 필요할 수도 있습니다.

텔레 포터는 계산하기가 어려우므로 위험하고 항상 좋은 텔레 포터와 더 관심이있는 사람들로 인구를 분할해야하며 다른 선택이없는 경우에만 사람들을 데려 가야합니다.

나는 어떻게 든 게놈의 후반부를 사용해야한다.


나는 또한 색상을 저장하려고하지만 결국 두 배를 얻을 것이기 때문에 작동하지 않는다고 결론지었습니다. 예를 들어 경우 self.bit_chunk(16, 4)self.bit_chunk(20, 4)값 모두가 0010효과적으로에만 두 함정 중 하나에 대한 정보를 저장 한을.
Ruut

이것을 실행하려면 한 줄에 들여 쓰기를 추가해야했습니다. 복사 및 붙여 넣을 때 잃어 버린 것 같습니다. 여기 코드에도 추가했습니다.
trichoplax

다른 사람이 이것을 실행하려면 : 파이썬 2에서 실행되고 단일 항목을 itervalues로 변경하여 파이썬 3에서 실행할 수 있습니다 values.
trichoplax

다음과 같은 결과를 얻었습니다 : [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] 기하 평균 122.9220309940335
trichoplax

신뢰할만한 점수를 얻으려면 50 개 이상의 게임을 실행해야 할 것 같습니다.
trichoplax

3

Python, NeighborsOfNeighbors, 100 개 이상의 게임에 대한 점수 = 259.84395

이것은 ColorScorePlayer의 변형입니다. 6 비트마다 제곱에 대한 품질 점수가 저장됩니다. 봇이 움직일 때 3 개의 정사각형 정사각형-대각선 위, 앞으로 및 대각선 아래로 각각 득점합니다. 점수는 사각형의 품질에 다음 3 개의 사각형의 평균 품질의 절반을 더한 값입니다. 이를 통해 봇은 첫 번째 광장의 품질을 압도하지 않으면 서 미리 볼 수 있습니다. 알고리즘은이 솔루션을 작성하기 전에 보지 않은 LookAheadPlayer와 유사합니다.

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)

한 줄에 들여 쓰기가 누락되었습니다. 붙여 넣을 때 잃어버린 것 같아요. 추가했습니다.
trichoplax

파이썬 3에서 실행하면 max (scores)를 계산할 때 None을 비교하는 것에 대해 불평했습니다. 그래서 점수를 계산하기 위해 이전 줄로 변경 else None했습니다 else 0. 다행히도 논리가 변경되지 않은 상태로 유지됩니다 (잃어버린 들여 쓰기를 추가하는 것 외에는 SE에서 코드를 변경하지 않았습니다).
trichoplax

파이썬 3에서 실행하면이 답변에 대해 다음 점수를 얻었습니다. [1, 13085, 360102, 1, 73713, 1, 189, 1, 1, 193613, 34, 195718, 199, 8, 1, 1, 60006, 66453, 2, 2, 53, 425206, 1, 4, 1, 1, 16, 153556, 1, 18134, 35655, 1, 4211684, 2, 1, 26451, 8, 1, 724635, 69242, 38469, 796553, 111340, 1, 25, 40017, 76064, 66478, 209365, 3925393]
trichoplax

428.3750848244933의 기하학적 평균
trichoplax

2

ROUS (특이한 크기의 설치류), Java, 점수 = 0

이것은 갈 곳을 결정하기 위해 주변을 해시합니다. Java 컨트롤러가 작동하지 않아서 점수가 없습니다. 텔레 포터가 몇 명 있으면 도움이됩니다.이것은 때때로 멸종하고 컨트롤러를 한 번 충돌시키는 경향이 있습니다. 이것은 아마도 자연 환경이 화재 늪이라는 사실 때문일 것입니다.

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

public class ROUS extends Player{

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

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

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

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

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

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

1
Java 컨트롤러가 현재 작동 중입니다.
마틴 엔더

3
처음에 나는 당신이 고대 러시아에 경의를 표한다고 생각했지만, 그것이 보이는 것처럼 Rob Reiner에게였습니다.

최소 점수는 1
trichoplax입니다.

@trichoplax ... 컨트롤러 충돌 ...
TheNumberOne

오, 알 겠어-그래서 종종 당신은 달리기의 끝에 도달 할 수 없을만큼 충분히 발생합니까?
trichoplax

2

그레이 컬러 룩어 헤드 (C ++, ~ 1.35)

이것은 평균적으로 잘 수행되지 않지만 드물게 훌륭하게 수행됩니다. 불행하게도, 우리는 최대 점수 (20077)가 아닌 기하 평균 (1.35)으로 평가되고 있습니다.

이 알고리즘은 4 비트 그레이 코드를 사용하여 각 색상의 점수를 -2에서 2 사이 ([-1..1] 범위로 편향) 어딘가에 매핑하고 각 이동 타일의 점수와 다음 동작을 계산합니다. . 또한 2 비트 그레이 코드를 사용하여 타일 자체의 승수와 오른쪽으로 이동하기위한 바이어스 요인을 결정합니다. (회색 코드는 돌연변이로 인해 큰 점프에 훨씬 덜 민감하지만 실제로는 중간 코드 포인트 크로스 오버에 유리하지 않습니다 ...)

또한 트랩을 특별히 처리하려고 시도하는 것은 전혀 없으며,이 이론을 테스트하기 위해 컨트롤러에 계측기를 추가하지 않았음에도 불구하고 몰락 할 수 있습니다.

각각의 가능한 움직임에 대해 점수를 결정하고, 가장 높은 점수를 가진 모든 움직임 중에서 무작위로 선택합니다.

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

내가 가장 최근에 뛰었을 때, 나는 다음과 같은 점수를 얻었다. 20077 1 1 2 1 1 1 1 1

더 많은 20077s와 더 적은 1s를 얻을 수 있기를 바랍니다. :)


1
회색 코드를 사용하는 것은 회색 아이디어입니다! ;)
matovitch

1
회색 코드의 경우 +1 그러나, 완전히 돌연변이 회복력있는 게놈은 다양성을 상당히 손상시킬 것입니다. 그리고 Btw는 20.000의 점수가 달성 할 수있는 최대치에 미치지 못합니다. 일부 쥐가 가능한 출발지에서 트랙을 달릴 수있는 능력을 발전 시키면 사실상 불멸의 상태가되어 큰 체력 점수를 얻습니다. 그 게놈은 빠르게 지배하여 최대 50 만 마리의 쥐와 수백만의 점수를 얻습니다.

2

C ++, 트리플 스코어, 점수 : 100 ~ 400

우선, 내 점수는 여러 번의 실행에서 크게 다릅니다 (주로 1의 수 때문에).

코어는 5 방향의 점수를 계산합니다 : 위, 아래, 앞으로 위로, 앞으로 및 앞으로. 먼저 결과가 제자리에 머무르는 값과 비교되는 것보다 위아래 점수가 계산됩니다. 제자리에 머무르는 것이 위나 아래로 움직이는 것보다 낫다면 이러한 방향은 선택되지 않으므로 앞으로 진행해야합니다. 이것은 두 지점 사이에 수신 거부 (위, 아래, 위, 아래, ...)를 방지하기위한 것입니다.

이제 3 가지 다른 방향으로 점수가 매겨집니다 : 정방향, 정방향 및 정방향. 조사 된 모든 지시 사항에서 점수가 가장 높은 지시 사항이 유지되고 그 중 하나가 무작위로 선택됩니다.

방향 점수 매기기 : TripleScore는 3 개의 하위 점수를 사용하여 이동 점수를 계산합니다.

  • 대상 색상의 점수 (colorScorePlayer에서와 같이 dna에 따라 다름)
  • 앞으로 나아갈 점수 (DNA에 따라 다름)
  • 대상에서 앞으로 이동 한 최대 점수 (dna에 저장된 요소를 곱한 값)

다른 답변과 마찬가지로 점수는 반환되는 1 점수에 크게 좌우됩니다.

#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

루비-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

이 결정적이지 않은 쥐는 주변에 의해 공간을 차지할 확률을 계산합니다. 게놈의 처음 16 개 슬롯은 16 개의 색상을 나타냅니다. 슬롯에 1은 색상이 짙어지고 0은 불량에 해당함을 의미합니다. 다음 16은 대상 앞의 공간과 동일하게 유지됩니다.

확률 론적 접근 방식의 주요 장점은 벽 뒤에 오랫동안 붙어있는 것이 거의 불가능하다는 것입니다. 단점은 거의 완벽한 쥐를 얻을 수 없다는 것입니다.


독창성을 위해 +1. 어떤 점수를 받았습니까?

실제로 아직 테스트 한 적이 없습니다 ...
MegaTom

c초기 값 을 잊어 버리셨습니까 ? 처음 사용할 때 정의되지 않은 것 같습니다 if.
Martin Ender

@ MartinBüttner 네, 잊어 버렸습니다. 이제 고칠 게요.
MegaTom

Ruby를 잘 모르지만 Ruby2.1.5에서 코드가 실행되지 않습니다. coords는 목록이 아니며 괄호 &&대신 사용 and하고 괄호를 잊어 버렸 으며이 모든 것을 고친 후에도 RNG 값을 제한하지 않으므로 빈 방향이됩니다. 이 의사 코드입니까, 아니면 어떤 종류의 루비 방언으로 실행되도록되어 있습니까?

2

자바, RunningStar, 점수 = 1817.050970291959 1000 게임 이상

이 봇은 StarPlayer 의 기술 과 함께 Run-Bonus 의 색상 코딩을 사용합니다.

업데이트 : 고정 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

특히 획기적인 것은 아니지만 확인을 수행하는 유일한 시도입니다.

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)

기본적으로 게놈에서 피하기 위해 4 가지 색상 (각 4 비트)을 코딩합니다. 그런 다음 해당 목록에없는 색상으로 이동합니다. 모든 색상이 나쁘면 여전히 미지의 수준으로 도약합니다.


아마 그것을 "RedQueen"이라고 불렀을 것입니다 :)
plannapus

1

자바-IAmARobotPlayer-3.7 점

방금 만든 다른 (지금까지는 흥미롭지 않은) 프로그램과 비교하기 위해이 로봇 쥐를 만들었습니다. 전반적으로 점수가 좋지는 않지만 어딘가에 점수를 매기면 많은 쥐가 생길 것입니다. 아이디어는 앞에있는 세 개의 셀 만 볼 것이며 각 셀은 좋거나 나쁘다는 것입니다. 이것은 이진수를 제공합니다. 그런 다음 게놈에서이 숫자를 찾아 3 개의 연속 비트를 가져 와서 숫자로 수렴하고이 숫자 아래에 저장된 조치를 수행합니다. 따라서 동일한 상황이 발생하면 항상 동일하게 작동합니다.

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

    }
}

결과:

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

신중한 표본-C ++-200 번의 실행에서 약 2030 점

이것은 Blind Faith 에서 인코딩 한 DNA의 색상 부분 (16x4 비트)을 사용하지만 DNA 의 나머지 (36 비트)는 완전히 사용되지 않습니다.

색상 인코딩은 다음 중 하나입니다.

  • 10XX-안전한 정사각형;
  • 11XX-치명적인 사각형의 경우; 과
  • 0000-0111-8 가지 유형의 트랩 사각형.

여기서 X는 사용되지 않은 비트를 나타냅니다. 16 비트 중 2 가지 색상 만 4 비트를 모두 사용하는 트랩 인 경우 (트랩이 오프셋 된 경우 (8 ~ 9 회)) 일반적으로 64 개의 사용되지 않는 비트가 있습니다. -이론은 이러한 미사용 비트에 영향을 미치는 돌연변이는 게놈을 손상시키지 않으며 안정성은 나머지 비트를 사용할 수있는 다른 멋진 솔루션보다 낫다는 것입니다.

그런 다음 시편은이를 사용하여 자신을 중심으로 7x7 그리드 내에서 안전한 경로를 계획합니다 (시각 5x5에 오프셋 트랩을 허용하기 위해 각 측면에 1 제곱 더하기) .3 이동 후 최대 거리를 앞으로 이동합니다.

나는 처음에 표본이 현재 서있는 색이 게놈에 치명적이지 않고 잘못된 색을 UNSURE 안전의 제곱 (및 인접한 사각형)으로 표시한다는 사실을 확인하기 위해 몇 가지 검사를 시작했습니다. 그 정사각형을 SAFE로 표시하고 몇 가지 추가 시편을 사살하는 것과 비교하여 적은 이득을위한 합병증. 시간이 있으면 이것으로 돌아갑니다.

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

샘플 점수 :

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

테스트 중 최대 점수 : 8,150,817 시편 저장.


이제 당신이 해냈어 ... 나중에 경로를 저장하고 싶었지만 신중한 설치류를 도전적으로 남겨 둘 수는 없었습니다. 경로 영역을 7x7로 확장하려는 아이디어도 유망한 것으로 보입니다. 내가 그것을 사용할 수 있는지 보자.

나는 현재 이것을 위해 2000 런을하고 있습니다 ... 첫 번째 900 이후 평균은 600에서 약 2000에서 상당히 떨어져있는 것으로 보입니다. 그냥 우연이야?
Martin Ender 2019
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.