国际象棋分析信息有限


19

在此挑战中,您仅获得有关特定棋类游戏的有限信息,并且需要预测谁赢得了该游戏

您将获得两组数据:

  1. 计件(哪些还活着)
  2. 木板颜色(木板上的棋子颜色)

更重要的是,知道这些碎片在哪里。您需要确定您认为会赢的人。

从2010年至今的PGNMentor上列出的所有事件中选择游戏。我从每场以胜利或失败告终的游戏中选择了所有董事会职位的10%。棋盘位置至少要有30步才能进入游戏。测试用例可以在这里找到。(首先列出白色胜利,然后是黑色胜利)

输入项

件数将是由每件的字符的字符串:kING,queen,rOOK,K n飞行,bishop,或p芒。小写表示黑色,大写表示白色。面板将是一个包含64个字符的字符串(8行8列)。B代表黑色,W代表白色,并且.代表空白。样品:

W..WB......W.BB....W..B..W.WWBBB..W...B....W..BBWWW...BB.W....B.,BBKPPPPPPPQRRbbkpppppppqrr

将代表以下董事会

...B.BB.
.BBBBBBB
.B.B....
B..W....
WWWW.W..
....W.W.
...W..WW
W.....W.

并且两种颜色都有2个主教,1个国王,7个兵,1个女王,2个白嘴鸦

输出量

您需要返回一个介于0和1(含)之间的浮点数,以确定白获胜的可能性。样品:

0.3     (30% chance that white wins)

更多细节:

  • 每个测试用例价值1分。您的得分将是1 - (1-Output)^2白人获胜或1 - (Output)^2黑人获胜。
  • 您的最终分数将是所有测试用例的总和。
  • 如果我认为提交的内容对输入进行了硬编码,则我保留更改测试用例的权利。(如果我更改它们,它们将具有SHA-256哈希值893be4425529f40bb9a0a7632f7a268a087ea00b0eb68293d6c599c6c671cdee
  • 您的程序必须独立运行测试用例。没有将信息从一个测试用例保存到下一个用例。
  • 如果您使用的是机器学习,我强烈建议对前80%的数据进行培训,并使用其余的20%进行测试。(或您使用的任何百分比)。我在数据中多次使用游戏,但是将相同的游戏顺序放置。
  • 更新:为了测试和学习目的,我添加了超过一百万个测试用例。由于github repo大小限制,它们分为黑色​​和白色部分。

祝好运并玩得开心点!


此对话已转移至聊天
丹尼斯

新的测试用例是否包含旧的用例,还是两组不相交?
致命

我不知道。我从不同的站点获得它们,因此它们可能包含相同的游戏集。
内森·美林

Answers:


8

Java 8 + Weka,6413点,94.5%

该答案使用机器学习方法。您需要检索Weka库,尤其是weka.jarPackageManager.jar

在这里,我使用多层感知器作为分类器。您可以替换mlp为任何Classifier类别的Weka来比较结果。

我没有对MLP的参数进行太多修改,只是简单地盯着它们(一层隐藏的50个神经元,100个时期,0.2个学习速率,0.1个动量)。

我为MLP的输出值设置了阈值,因此输出实际上是挑战中定义的1或0。这样,由Weka打印的正确分类实例的数量直接就是我们的分数。

特征向量构造

我将每个实例从字符串转换为包含76个元素的向量,其中:

  • 前64个元素代表板的单元格,其顺序与字符串中的顺序相同,其中1白色是一块,-1黑色是一块,0是一个空单元。
  • 最后12个元素代表每种乐曲类型(每个玩家6个);这些元素的值就是板上该类型的块数(0“没有该类型的块”)。可以应用归一化来重新拟合介于-1和1之间的值,但这在这里可能不是很有用。

训练次数

如果我使用给出的所有测试用例来训练我的分类器,那么我已经设法获得了6694个(即98.6588%)正确分类的实例。这显然不足为奇,因为在用于训练的相同数据上测试模型太简单了(因为在这种情况下,模型过拟合实际上是件好事)。

使用80%实例的随机子集作为训练数据,我们获得报头中报告的6413个(即94.5173%)正确分类的实例图(当然,由于该子集是随机的,您可能会得到略有不同的结果)。我有信心该模型可以很好地处理新数据,因为对其余20%的实例(未用于训练)进行测试可得出77.0818%的正确分类,这表明模型可以很好地概括(假设我们在这里给出的实例代表了我们将要给出的新测试用例。

使用一半的实例进行训练,另一半用于测试,我们在训练和测试数据上的获得率为86.7502%,仅在测试数据上的获得率为74.4988%

实作

正如我已经说过,这个代码需要weka.jarPackageManager.jar从Weka的。

使用可以控制训练集中使用的数据百分比TRAIN_PERCENTAGE

MLP的参数可以在下面更改TRAIN_PERCENTAGESMO只需替换mlp为另一个分类器,即可尝试Weka的其他分类器(例如,用于SVM)。

此程序将打印到结果集,第一个结果在整个集合(包括用于训练的数据)上,这是此挑战中定义的分数,第二个结果仅在未用于训练的数据上。

通过将包含数据的文件的路径作为参数传递给程序来输入数据。

import weka.classifiers.Classifier;
import weka.classifiers.Evaluation;
import weka.classifiers.functions.MultilayerPerceptron;
import weka.core.Attribute;
import weka.core.DenseInstance;
import weka.core.Instance;
import weka.core.Instances;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;

public class Test {

    public static void main(String[] arg) {

        final double TRAIN_PERCENTAGE = 0.5;

        final String HIDDEN_LAYERS = "50";
        final int NB_EPOCHS = 100;
        final double LEARNING_RATE = 0.2;
        final double MOMENTUM = 0.1;

        Instances instances = parseInstances(arg[0]);
        instances.randomize(new java.util.Random(0));
        Instances trainingSet = new Instances(instances, 0, (int) Math.floor(instances.size() * TRAIN_PERCENTAGE));
        Instances testingSet = new Instances(instances, (int) Math.ceil(instances.size() * TRAIN_PERCENTAGE), (instances.size() - (int) Math.ceil(instances.size() * TRAIN_PERCENTAGE)));

        Classifier mlp = new MultilayerPerceptron();
        ((MultilayerPerceptron) mlp).setHiddenLayers(HIDDEN_LAYERS);
        ((MultilayerPerceptron) mlp).setTrainingTime(NB_EPOCHS);
        ((MultilayerPerceptron) mlp).setLearningRate(LEARNING_RATE);
        ((MultilayerPerceptron) mlp).setMomentum(MOMENTUM);


        try {
            // Training phase
            mlp.buildClassifier(trainingSet);
            // Test phase
            System.out.println("### CHALLENGE SCORE ###");
            Evaluation test = new Evaluation(trainingSet);
            test.evaluateModel(mlp, instances);
            System.out.println(test.toSummaryString());
            System.out.println();
            System.out.println("### TEST SET SCORE ###");
            Evaluation test2 = new Evaluation(trainingSet);
            test2.evaluateModel(mlp, testingSet);
            System.out.println(test2.toSummaryString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Instances parseInstances(String filePath) {
        ArrayList<Attribute> attrs = new ArrayList<>(); // Instances constructor only accepts ArrayList
        for(int i = 0 ; i < 76 ; i++) {
            attrs.add(new Attribute("a" + String.valueOf(i)));
        }
        attrs.add(new Attribute("winner", new ArrayList<String>(){{this.add("white");this.add("black");}}));
        Instances instances = new Instances("Rel", attrs, 10);
        instances.setClassIndex(76);

        try {
            BufferedReader r = new BufferedReader(new FileReader(filePath));
            String line;
            String winner = "white";
            while((line = r.readLine()) != null) {
                if(line.equals("White:")) {
                    winner = "white";
                } else if(line.equals("Black:")) {
                    winner = "black";
                } else {
                    Instance instance = new DenseInstance(77);
                    instance.setValue(attrs.get(76), winner);
                    String[] values = line.split(",");
                    for(int i = 0 ; i < values[0].length() ; i++) {
                        if(values[0].charAt(i) == 'B') {
                            instance.setValue(attrs.get(i), -1);
                        } else if(values[0].charAt(i) == 'W') {
                            instance.setValue(attrs.get(i), 1);
                        } else {
                            instance.setValue(attrs.get(i), 0);
                        }
                    }
                    // Ugly as hell
                    instance.setValue(attrs.get(64), values[1].length() - values[1].replace("k", "").length());
                    instance.setValue(attrs.get(65), values[1].length() - values[1].replace("q", "").length());
                    instance.setValue(attrs.get(66), values[1].length() - values[1].replace("r", "").length());
                    instance.setValue(attrs.get(67), values[1].length() - values[1].replace("n", "").length());
                    instance.setValue(attrs.get(68), values[1].length() - values[1].replace("b", "").length());
                    instance.setValue(attrs.get(69), values[1].length() - values[1].replace("p", "").length());
                    instance.setValue(attrs.get(70), values[1].length() - values[1].replace("K", "").length());
                    instance.setValue(attrs.get(71), values[1].length() - values[1].replace("Q", "").length());
                    instance.setValue(attrs.get(72), values[1].length() - values[1].replace("R", "").length());
                    instance.setValue(attrs.get(73), values[1].length() - values[1].replace("N", "").length());
                    instance.setValue(attrs.get(74), values[1].length() - values[1].replace("B", "").length());
                    instance.setValue(attrs.get(75), values[1].length() - values[1].replace("P", "").length());

                    instances.add(instance);
                }
            }
        } catch (Exception e) { // who cares
            e.printStackTrace();
        }
        return instances;
    }
}

您如何编码输入?
内森·美林

@NathanMerrill我不确定我是否理解您的问题
致命一击

您如何将测试用例作为输入传递到神经网络?您只是传递原始字符串吗?
内森·美林

@NathanMerrill编辑了有关特征向量构造的一段。
致命

我们如何知道您要预测赢家?
user1502040

8

GNU sed + BC,4336 5074.5点,64 75%

更新: OP提供了一种新方法来计算单个测试用例的预测分数。使用Wolfram Alpha,我绘制了两组公式以查看差异。

当前方法带来了很大的动力来输出实际概率,而不仅仅是极限值0和1,对于这些极限值,新公式给出的最大得分与以前相同。这就是为什么下面的不变算法现在具有更好的预测率,而鉴于其简单性,实际上具有很高的预测率的原因。

但是,如“编辑1”中所述,新公式还存在一个缺点。


这是仅基于材料优点/缺点的简单估算,而忽略了零件的实际放置。我很好奇这将如何执行。我之所以使用sed,而不是一门语言就能做到这一点,是因为它是我最喜欢的深奥语言。

/:/d                                             # delete the two headers
s:.*,::                                          # delete board positions
s:$:;Q9,R5,B3,N3,P1,K0,q-9,r-5,b-3,n-3,p-1,k-0:  # add relative piece value table
:r                                               # begin replacement loop
s:([a-Z])((.*)\1([^,]+)):\4+\2:                  # table lookup: letter-value repl.
tr                                               # repeat till last piece
s:;.*::                                          # delete value table
s:.*:echo '&0'|bc:e                              # get material difference: bc call
/^0$/c0.5                                        # print potential draw score
/-/c0                                            # print potential black win score
c1                                               # print potential white win score

使用的标准件值:

  • 9-女王
  • 5-白嘴鸦
  • 3-骑士
  • 3-主教
  • 1-典当
  • 0-国王

我计算两面的材料,然后从白色中减去黑色的材料。每个测试用例的输出基于以下差异:

  • 如果差异> 0,则输出= 1(潜在的白赢)
  • 如果差= 0,则输出= 0.5(潜在消耗)。

这是我唯一的部分输出,因此如上所述有改进的原因。

  • 如果差异<0,则输出= 0(潜在的黑色获胜)

该方法的预测率为64%。现在,使用新公式的比例为75%。

我最初希望它更高,例如70%,但是作为一名国际象棋棋手,我可以理解结果,因为当我+1 / +2时我输了很多场比赛,而当我下棋时我赢了那么多场比赛。材料。这都是关于实际位置的。(好吧,现在我如愿以偿!)

编辑1:缺点

简单的解决方案是每个测试用例输出0.5,因为这样一来,无论谁赢了,您都得半分。对于我们的测试用例,这意味着总成绩为3392.5分(50%)。

但是使用新公式时,0.5(如果您不确定谁是赢家,您将得到的输出)将转换为0.75点。请记住,对于测试用例,您可以得到的最高分数是1,这表示获胜者会获得100%的信心。这样,恒定的0.5输出的新总得分是5088.75分,即75%!我认为,这种情况的动机太强了。

该分数比我的基于物质优势的算法要好,尽管有些微。这样做的原因是因为该算法给出的概率为1或0(无激励),假设获胜或失败,发生的次数(3831)比给出的0.5(激励),假定为平局(2954)的次数更多。该方法最后很简单,因此正确答案的百分比不高。从新公式提高到恒定的0.5,可以人为地达到该百分比。

编辑2:

在国际象棋书籍中提到的一个众所周知的事实是,有主教对通常比骑士对更好。在测试用例所在的游戏的中后期,尤其如此,因为主教的射程增加的可能性更大。

因此,我进行了第二次测试,但是这次我将主教的值从3替换为3.5。骑士的价值仍然是3。这是个人喜好,因此我没有将其作为默认提交。在这种情况下,总分为4411分(65%)。仅观察到1个百分点的增加。

使用新公式,总分为4835分(71%)。现在,加权的主教表现不佳。但是,之所以可以解释这种效果,是因为现在加权方法比假定的平局(1696)给出的假定胜负(5089)甚至更多。


1
+1提供合理的基准解决方案。我也想知道这样做的效果如何。
马丁·恩德

@MartinEnder谢谢。我上次提到的增加主教价值的想法仅使成功率增加了1%(请参阅更新2)。我认为标准值的确包含了这种效果。
seshoumara

嘿,根据xnor的评论,您介意将评分更改为绝对差的平方吗?
内森·美林

1
太棒了 另外,感谢您的回答!我一直担心我的难题无法得到答案。
内森·美林

@NathanMerrill我更新了我的答案,以根据要求使用新评分。抱歉,进行了长时间的分析,但我确实很好奇。
seshoumara

4

Python 3-84.6%,在验证集上获得5275分

如果我们作弊并使用所有数据,我们可以达到99.3%的准确性和6408的得分

只是使用Keras进行辍学的简单大型MLP

import collections
import numpy as np
import random

import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.layers.noise import GaussianDropout
from keras.optimizers import Adam

np.random.seed(0)
random.seed(0)

def load_data():
    with open('test_cases.txt', 'r') as f:
        for line in f:
            yield line.split(',')

def parse_data(rows):
    black_pieces = "kpbkrq"
    white_pieces = black_pieces.upper()
    for i, row in enumerate(rows):
        if len(row) >= 2:
            board = row[0]
            board = np.array([1 if c == 'W' else -1 if c == 'B' else 0 for c in board], dtype=np.float32)
            pieces = row[1]
            counts = collections.Counter(pieces)
            white_counts = np.array([counts[c] for c in white_pieces], dtype=np.float32)
            black_counts = np.array([counts[c] for c in black_pieces], dtype=np.float32)
            yield (outcome, white_counts, black_counts, board)
        else:
            if 'White' in row[0]:
                outcome = 1
            else:
                outcome = 0

data = list(parse_data(load_data()))
random.shuffle(data)
data = list(zip(*data))
y = np.array(data[0])
x = list(zip(*data[1:]))
x = np.array([np.concatenate(xi) for xi in x])

i = len(y) // 10

x_test, x_train = x[:i], x[i:]
y_test, y_train = y[:i], y[i:]

model = Sequential()
model.add(Dense(512, activation='relu', input_shape=(76,)))
model.add(GaussianDropout(0.5))
model.add(Dense(512, activation='relu'))
model.add(GaussianDropout(0.5))
model.add(Dense(512, activation='relu'))
model.add(GaussianDropout(0.5))
model.add(Dense(1, activation='sigmoid'))

model.compile(loss='mean_squared_error', optimizer=Adam())

use_all_data = False

x_valid, y_valid = x_test, y_test

if use_all_data:
    x_train, y_train = x_test, y_test = x, y
    validation_data=None
else:
    validation_data=(x_test, y_test)

batch_size = 128

history = model.fit(x_train, y_train, batch_size=batch_size, epochs=50, verbose=1, validation_data=validation_data)

y_pred = model.predict_on_batch(x_test).flatten()
y_class = np.round(y_pred)
print("accuracy: ", np.sum(y_class == y_test) / len(y_test))

score = np.sum((y_pred - (1 - y_test)) ** 2) * (len(y) / len(y_test))
print("score: ", score)

您使用多少数据进行培训才能获得84.6%的数字?
致命

我使用了代码中所示的90-10拆分
user1502040

嘿,我添加了一个,如果你有兴趣更多的测试用例。
内森·美林

2

Python 3 – 94.3%的准确性,在20%的数据的验证集上获得6447点

使用3个神经网络,最近邻回归器,随机森林和梯度增强。这些预测与也可以访问数据的随机森林结合在一起。

import collections
import numpy as np
import numpy.ma as ma
import random

import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, BatchNormalization, Activation, Conv2D, Flatten
from keras.layers.noise import GaussianDropout
from keras.callbacks import EarlyStopping
from keras.optimizers import Adam
from sklearn.neighbors import KNeighborsRegressor
from sklearn.ensemble import RandomForestRegressor
from sklearn.ensemble import GradientBoostingRegressor
import tensorflow

tensorflow.set_random_seed(1)
np.random.seed(1)
random.seed(1)

def load_data():
    with open('test_cases.txt', 'r') as f:
        for line in f:
            yield line.split(',')

def parse_data(rows):
    black_pieces = "kqrnbp"
    white_pieces = black_pieces.upper()
    for i, row in enumerate(rows):
        if len(row) >= 2:
            board = row[0]
            board = np.array([1 if c == 'W' else -1 if c == 'B' else 0 for c in board], dtype=np.float32)
            pieces = row[1]
            counts = collections.Counter(pieces)
            white_counts = np.array([counts[c] for c in white_pieces], dtype=np.float32)
            black_counts = np.array([counts[c] for c in black_pieces], dtype=np.float32)
            yield (outcome, white_counts, black_counts, board)
        else:
            if 'White' in row[0]:
                outcome = 1
            else:
                outcome = 0

data = list(parse_data(load_data()))
random.shuffle(data)
data = list(zip(*data))
y = np.array(data[0])
x = list(zip(*data[1:]))
conv_x = []
for white_counts, black_counts, board in x:
    board = board.reshape((1, 8, 8))
    white_board = board > 0
    black_board = board < 0
    counts = [white_counts, black_counts]
    for i, c in enumerate(counts):
        n = c.shape[0]
        counts[i] = np.tile(c, 64).reshape(n, 8, 8)
    features = np.concatenate([white_board, black_board] + counts, axis=0)
    conv_x.append(features)
conv_x = np.array(conv_x)
x = np.array([np.concatenate(xi) for xi in x])
s = x.std(axis=0)
u = x.mean(axis=0)
nz = s != 0
x = x[:,nz]
u = u[nz]
s = s[nz]
x = (x - u) / s

i = 2 * len(y) // 10

x_test, x_train = x[:i], x[i:]
conv_x_test, conv_x_train = conv_x[:i], conv_x[i:]
y_test, y_train = y[:i], y[i:]

model = Sequential()

def conv(n, w=3, shape=None):
    if shape is None:
        model.add(Conv2D(n, w, padding="same"))
    else:
        model.add(Conv2D(n, w, padding="same", input_shape=shape))
    model.add(BatchNormalization())
    model.add(Activation('relu'))

conv(128, shape=conv_x[0].shape) 
conv(128)
conv(128)
conv(128)
conv(128)
conv(128)
conv(128)
conv(128)
conv(128)
conv(128)
conv(2, w=1)
model.add(Flatten())
model.add(GaussianDropout(0.5))
model.add(Dense(256))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(GaussianDropout(0.5))
model.add(Dense(1))
model.add(BatchNormalization())
model.add(Activation('sigmoid'))

model.compile(loss='mse', optimizer=Adam())

model5 = model

model = Sequential()
model.add(Dense(50, input_shape=(x.shape[1],)))
model.add(Activation('sigmoid'))
model.add(Dense(1))
model.add(Activation('sigmoid'))

model.compile(loss='mse', optimizer=Adam())

model0 = model

model = Sequential()
model.add(Dense(1024, input_shape=(x.shape[1],)))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(GaussianDropout(0.5))
model.add(Dense(1024))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(GaussianDropout(0.5))
model.add(Dense(1024))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(GaussianDropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))

model.compile(loss='mse', optimizer=Adam())

model4 = model

use_all_data = False

x_valid, y_valid = x_test, y_test

if use_all_data:
    x_train, y_train = x_test, y_test = x, y
    validation_data=None
else:
    validation_data=(x_test, y_test)

def subsample(x, y, p=0.9, keep_rest=False):
    m = np.random.binomial(1, p, size=len(y)).astype(np.bool)
    r = (x[m,:], y[m])
    if not keep_rest:
        return r
    m = ~m
    return r + (x[m,:], y[m])

epochs=100

x0, y0, x_valid, y_valid = subsample(conv_x_train, y_train, keep_rest=True)
model5.fit(x0, y0, epochs=epochs, verbose=1, validation_data=(x_valid, y_valid), callbacks=[EarlyStopping(patience=1)])

x0, y0, x_valid, y_valid = subsample(x_train, y_train, keep_rest=True)
model0.fit(x0, y0, epochs=epochs, verbose=1, validation_data=(x_valid, y_valid), callbacks=[EarlyStopping(patience=1)])

x0, y0, x_valid, y_valid = subsample(x_train, y_train, keep_rest=True)
model4.fit(x0, y0, epochs=epochs, verbose=1, validation_data=(x_valid, y_valid), callbacks=[EarlyStopping(patience=1)])

model1 = RandomForestRegressor(n_estimators=400, n_jobs=-1, verbose=1)
model1.fit(*subsample(x_train, y_train))

model2 = GradientBoostingRegressor(learning_rate=0.2, n_estimators=5000, verbose=1)
model2.fit(*subsample(x_train, y_train))

model3 = KNeighborsRegressor(n_neighbors=2, weights='distance', p=1)
model3.fit(*subsample(x_train, y_train))

models = (model0, model1, model2, model3, model4, model5)

model_names = [
    "shallow neural net",
    "random forest",
    "gradient boosting",
    "k-nearest neighbors",
    "deep neural net",
    "conv-net",
    "ensemble"
]

def combine(predictions):
    clip = lambda x: np.clip(x, 0, 1)
    return clip(np.array([y.flatten() for y in predictions]).T)

def augment(x, conv_x):
    p = combine([m.predict(x) for m in models[:-1]] + [models[-1].predict(conv_x)])
    return np.concatenate((x, p), axis=1)

model = RandomForestRegressor(n_estimators=200, n_jobs=-1, verbose=1)
model.fit(augment(x_train, conv_x_train), y_train)

def accuracy(prediction):
    class_prediction = np.where(prediction > 0.5, 1, 0)
    return np.sum(class_prediction == y_test) / len(y_test)

predictions = [m.predict(x_test).flatten() for m in models[:-1]] + [models[-1].predict(conv_x_test).flatten()]+ [model.predict(augment(x_test, conv_x_test))]

for s, p in zip(model_names, predictions):
    print(s + " accuracy: ", accuracy(p))

def evaluate(prediction):
    return np.sum(1 - (prediction - y_test) ** 2) * (len(y) / len(y_test))

for s, p in zip(model_names, predictions):
    print(s + " score: ", evaluate(p))

嘿,我添加了一个,如果你有兴趣更多的测试用例。
内森·美林

哇,你出去了。
罗伯特·弗雷泽

请注意此处的Java答案,“跳动”您的报告似乎报告了整个数据集的百分比,而只获得了77%的未训练数据。
罗伯特·弗雷泽

0

Python 3-4353.25 / 6785点-64%

所以我昨天主要是在做这个。我打高尔夫球的第一篇文章,现在才一周左右才使用python,所以请原谅我,如果不是所有事情都得到了优化。

def GetWhiteWinPercent(a):
finalWhiteWinPercent=0
i=a.index(',')

#position
board=a[:i]
blackBoardScore=0
whiteBoardScore=0
for r in range(i):
    if board[r] == 'B': blackBoardScore += abs(7 - (r % 8))
    if board[r] == 'W': whiteBoardScore += r % 8
if   whiteBoardScore > blackBoardScore: finalWhiteWinPercent += .5
elif whiteBoardScore < blackBoardScore: finalWhiteWinPercent += .0
else: finalWhiteWinPercent+=.25

#pieces
pieces=a[i:]
s = {'q':-9,'r':-5,'n':-3,'b':-3,'p':-1,'Q':9,'R':5,'N':3,'B':3,'P':1}
pieceScore = sum([s.get(z) for z in pieces if s.get(z) != None])
if   pieceScore < 0: finalWhiteWinPercent += 0
elif pieceScore > 0: finalWhiteWinPercent += .5
else: finalWhiteWinPercent += .25

return finalWhiteWinPercent

我最终沿着与seshoumara的回答相同的道路前进。但是大量的测试用例甚至数不清,使我不满意。

因此,我搜索了那些决定谁在国际象棋上获胜的特征(我自己不玩游戏),并且注意到棋盘位置,特别是中控位置很大。这就是这个地方。

for r in range(i):
    if board[r] == 'B': blackBoardScore += abs(7 - (r % 8))
    if board[r] == 'W': whiteBoardScore += r % 8
if   whiteBoardScore > blackBoardScore: finalWhiteWinPercent += .5
elif whiteBoardScore < blackBoardScore: finalWhiteWinPercent += .0
else: finalWhiteWinPercent+=.25

这两个半部分的总和用于查找分数(0.0、0.25、0.50、0.75、1.0)

非常有趣的是,这个额外的董事会职位似乎并没有增加猜测获胜者的机会。

如果将测试用例放到某些文件中,那么这里就是测试。

whiteWins=0
blackWins=0
totalWins=0
for line in open('testcases2.txt','r'):
    totalWins += 1
    blackWins += 1 - GetWhiteWinPercent(line)
for line in open('testcases.txt','r'):
    totalWins += 1
    whiteWins += GetWhiteWinPercent(line)

print(str(whiteWins+blackWins) +'/'+str(totalWins))

我知道这不是高尔夫挑战,但是在这方面的任何提示或建议都值得赞赏!


我的答案?你是说seshoumara的答案?另外,您不需要打高尔夫球(除非您愿意)。这不是代码挑战。
内森·美林

您可以仅使用一个字符的变量名来保存许多字节。(尽管这并不重要,因为这不是代码高尔夫)
HyperNeutrino

哇!现在进行编辑。在工作中,这就是我要略读的内容!
数据流

2
请不要打高尔夫球。最好在非代码高尔夫时保持代码的可读性。
mbomb007 '17

控制板子中间并不意味着占据板子中间,而是攻击板子中间。如果您想为此增加一些复杂性,则可以提高您的分数。
并不是查尔斯(Charles)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.