Bỏ phiếu chiến lược, trò chơi


37

Một trong những hệ thống bỏ phiếu phổ biến nhất cho các cuộc bầu cử một người chiến thắng là phương thức bỏ phiếu đa số. Nói một cách đơn giản, ứng cử viên có nhiều phiếu nhất sẽ chiến thắng. Tuy nhiên, bỏ phiếu đa số là không chắc chắn về mặt toán học và có khả năng tạo ra các tình huống trong đó các cử tri bị buộc phải bỏ phiếu cho "ít tệ hơn hai tệ nạn" trái ngược với ứng cử viên họ thực sự thích.

Trong trò chơi này, bạn sẽ viết chương trình tận dụng hệ thống bỏ phiếu đa số. Nó sẽ bỏ phiếu cho một trong ba ứng cử viên trong một cuộc bầu cử. Mỗi ứng viên được liên kết với một mức chi trả nhất định cho chính bạn và mục tiêu của bạn là tối đa hóa mức chi trả dự kiến ​​của bạn.

Số tiền chi trả được phân bổ ngẫu nhiên "đồng đều", thay đổi theo từng cuộc bầu cử và thêm vào 100. Ứng cử viên A có thể có số tiền thưởng 40, Ứng viên B có thể có khoản chi trả 27 và Ứng viên C có thể có số tiền chi trả 33. Mỗi người chơi có một bộ số tiền chi trả khác nhau.

Khi đến lượt bạn bỏ phiếu, bạn sẽ có thông tin không đầy đủ. Dưới đây là thông tin mà bạn sẽ có sẵn cho bạn. Vì bạn không biết mức chi trả cá nhân của người chơi khác là gì, sẽ là thách thức của bạn để dự đoán cách họ sẽ bỏ phiếu cho kết quả cuộc thăm dò hiện tại.

  • Kết quả một phần của cuộc bầu cử cho đến nay
  • Số lượng người đăng ký (không bao gồm chính bạn), người chưa bỏ phiếu
  • Tiền thưởng cá nhân của bạn cho mỗi ứng cử viên
  • Tổng số tiền chi trả cho mỗi ứng cử viên

Sau khi mỗi người chơi đã có cơ hội bỏ phiếu, ứng cử viên có nhiều phiếu nhất sẽ chiến thắng theo tỷ lệ bỏ phiếu đa số. Mỗi người chơi sau đó nhận được số điểm tương ứng với mức thưởng của họ từ ứng cử viên đó. Nếu có một sự ràng buộc trong phiếu bầu, thì số điểm được chỉ định sẽ là trung bình của các ứng cử viên bị ràng buộc.

Cơ cấu giải đấu

Khi lần đầu tiên được thông báo, người đăng ký sẽ được cho biết số lượng cuộc bầu cử được tổ chức trong giải đấu. Tôi sẽ cố gắng để chạy một số lượng lớn các cuộc bầu cử. Sau đó, mỗi cuộc bầu cử sẽ được tiến hành từng cái một.

Sau khi những người tham gia được xáo trộn, mỗi người được lần lượt bỏ phiếu. Họ được cung cấp thông tin hạn chế được liệt kê ở trên và trả về một số biểu thị phiếu bầu của họ. Sau khi mỗi cuộc bầu cử kết thúc, mỗi bot được đưa ra kết quả thăm dò cuối cùng và số điểm của họ tăng lên từ cuộc bầu cử đó.

Người chiến thắng sẽ là người có tổng số điểm cao nhất sau khi một số lượng lớn các cuộc bầu cử đã được tổ chức. Bộ điều khiển cũng tính điểm "bình thường hóa" cho mỗi thí sinh bằng cách so sánh điểm của nó với phân phối điểm được dự đoán cho một bot bỏ phiếu ngẫu nhiên.

Chi tiết nộp

Đệ trình sẽ có dạng các lớp Java 8. Mỗi người đăng ký phải thực hiện giao diện sau:

public interface Player
{
    public String getName();
    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs);
    public void receiveResults(int[] voteCounts, double result);
}
  • Nhà xây dựng của bạn nên lấy một inttham số làm tham số, sẽ đại diện cho số lượng các cuộc bầu cử sẽ được tổ chức.
  • Các getName()phương thức trả về tên được sử dụng trên bảng. Điều này cho phép bạn có những cái tên được định dạng độc đáo, đừng phát điên.
  • Các getVote(...)trở về phương pháp 0, 1hoặc 2để biểu thị mà ứng cử viên sẽ nhận được phiếu bầu.
  • Các receiveResults(...)phương pháp chủ yếu là để cho phép sự tồn tại của chiến lược phức tạp hơn sử dụng dữ liệu lịch sử.
  • Bạn được phép tạo ra khá nhiều biến phương thức / thể hiện khác mà bạn muốn ghi lại và xử lý thông tin được cung cấp cho bạn.

Chu kỳ giải đấu, mở rộng

  1. Những người tham gia được mỗi ngay lập tức với new entrantName(int numElections).
  2. Đối với mỗi cuộc bầu cử:
    1. Bộ điều khiển xác định ngẫu nhiên số tiền chi trả cho mỗi người chơi cho cuộc bầu cử này. Mã cho điều này được đưa ra dưới đây. Sau đó, nó xáo trộn người chơi và bắt họ bỏ phiếu.
    2. Phương pháp này của dự thi public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs)được gọi, và người dự thi trả về bỏ phiếu của họ 0, 1hoặc 2cho các ứng cử viên mà họ lựa chọn.
    3. Những người tham gia có getVote(...)phương thức không trả lại phiếu bầu hợp lệ sẽ được chỉ định một phiếu bầu ngẫu nhiên.
    4. Sau khi mọi người đã bỏ phiếu, kiểm soát viên xác định kết quả bầu cử bằng phương pháp đa số.
    5. Những người tham gia được thông báo về số phiếu bầu cuối cùng và mức chi trả của họ bằng cách gọi phương thức của họ public void receiveResults(int[] voteCounts, double result).
  3. Sau khi tất cả các cuộc bầu cử đã được tổ chức, người chiến thắng là người có số điểm cao nhất.

Phân phối ngẫu nhiên của tiền chi trả

Việc phân phối chính xác sẽ có ảnh hưởng đáng kể đến lối chơi. Tôi đã chọn một phân phối có độ lệch chuẩn lớn (khoảng 23,9235) và có khả năng tạo ra cả hai mức chi trả rất cao và rất thấp. Tôi đã kiểm tra rằng mỗi trong số ba khoản chi trả có phân phối giống hệt nhau.

public int[] createPlayerPayoffs()
{
    int cut1;
    int cut2;
    do{
        cut1 = rnd.nextInt(101);
        cut2 = rnd.nextInt(101);  
    } while (cut1 + cut2 > 100);
    int rem = 100 - cut1 - cut2;
    int[] set = new int[]{cut1,cut2,rem};
    totalPayoffs[0] += set[0];
    totalPayoffs[1] += set[1];
    totalPayoffs[2] += set[2];
    return set;
}

Thêm quy tắc

Dưới đây là một số quy tắc tổng quát hơn.

  • Chương trình của bạn không được chạy / sửa đổi / khởi tạo bất kỳ phần nào của bộ điều khiển hoặc những người tham gia khác hoặc ký ức của họ.
  • Vì chương trình của bạn vẫn "trực tiếp" cho toàn bộ giải đấu, không tạo bất kỳ tệp nào.
  • Không tương tác với, giúp đỡ hoặc nhắm mục tiêu bất kỳ chương trình nào khác.
  • Bạn có thể gửi nhiều người đăng ký, miễn là họ khác nhau một cách hợp lý và miễn là bạn tuân theo các quy tắc trên.
  • Tôi chưa chỉ định giới hạn thời gian chính xác, nhưng tôi sẽ đánh giá rất cao thời gian chạy ít hơn đáng kể so với một giây trên mỗi cuộc gọi. Tôi muốn có thể điều hành càng nhiều cuộc bầu cử càng khả thi.

Bộ điều khiển

Bộ điều khiển có thể được tìm thấy ở đây . Chương trình chính là Tournament.java. Ngoài ra còn có hai bot đơn giản, sẽ cạnh tranh, có tiêu đề RandomBotPersonalFavoriteBot. Tôi sẽ đăng hai bot này trong một câu trả lời.

Bảng xếp hạng

Có vẻ như ExpectantBot là nhà lãnh đạo hiện tại, tiếp theo là Monte Carlo và sau đó là StaBot.

Leaderboard - 20000000 elections:
   767007688.17 (  937.86) - ExpectantBot                            
   766602158.17 (  934.07) - Monte Carlo 47                          
   766230646.17 (  930.60) - StatBot                                
   766054547.17 (  928.95) - ExpectorBot                             
   764671254.17 (  916.02) - CircumspectBot                          
   763618945.67 (  906.19) - LockBot                                 
   763410502.67 (  904.24) - PersonalFavoriteBot343                  
   762929675.17 (  899.75) - BasicBot                                
   761986681.67 (  890.93) - StrategicBot50                          
   760322001.17 (  875.37) - Priam                                   
   760057860.67 (  872.90) - BestViableCandidate (2842200 from ratio, with 1422897 tie-breakers of 20000000 total runs)
   759631608.17 (  868.92) - Kelly's Favorite                        
   759336650.67 (  866.16) - Optimist                                
   758564904.67 (  858.95) - SometimesSecondBestBot                  
   754421221.17 (  820.22) - ABotDoNotForget                         
   753610971.17 (  812.65) - NoThirdPartyBot                         
   753019290.17 (  807.12) - NoClueBot                               
   736394317.17 (  651.73) - HateBot670                              
   711344874.67 (  417.60) - Follower                                
   705393669.17 (  361.97) - HipBot                                  
   691422086.17 (  231.38) - CommunismBot0                           
   691382708.17 (  231.01) - SmashAttemptByEquality (on 20000000 elections)
   691301072.67 (  230.25) - RandomBot870                            
   636705213.67 ( -280.04) - ExtremistBot                            
The tournament took 34573.365419071 seconds, or 576.2227569845166 minutes.

Dưới đây là một số giải đấu cũ hơn, nhưng không có bot nào thay đổi chức năng kể từ khi những lần chạy này.

Leaderboard - 10000000 elections:
   383350646.83 (  661.14) - ExpectantBot                            
   383263734.33 (  659.99) - LearnBot                                
   383261776.83 (  659.97) - Monte Carlo 48                          
   382984800.83 (  656.31) - ExpectorBot                             
   382530758.33 (  650.31) - CircumspectBot                          
   381950600.33 (  642.64) - PersonalFavoriteBot663                  
   381742600.33 (  639.89) - LockBot                                 
   381336552.33 (  634.52) - BasicBot                                
   381078991.83 (  631.12) - StrategicBot232                         
   380048521.83 (  617.50) - Priam                                   
   380022892.33 (  617.16) - BestViableCandidate (1418072 from ratio, with 708882 tie-breakers of 10000000 total runs)
   379788384.83 (  614.06) - Kelly's Favorite                        
   379656387.33 (  612.31) - Optimist                                
   379090198.33 (  604.83) - SometimesSecondBestBot                  
   377210328.33 (  579.98) - ABotDoNotForget                         
   376821747.83 (  574.84) - NoThirdPartyBot                         
   376496872.33 (  570.55) - NoClueBot                               
   368154977.33 (  460.28) - HateBot155                              
   355550516.33 (  293.67) - Follower                                
   352727498.83 (  256.36) - HipBot                                  
   345702626.33 (  163.50) - RandomBot561                            
   345639854.33 (  162.67) - SmashAttemptByEquality (on 10000000 elections)
   345567936.33 (  161.72) - CommunismBot404                         
   318364543.33 ( -197.86) - ExtremistBot                            
The tournament took 15170.484259763 seconds, or 252.84140432938332 minutes.

Tôi cũng đã chạy một giải đấu 10m thứ hai, xác nhận sự dẫn đầu của ExpectantBot.

Leaderboard - 10000000 elections:
   383388921.83 (  661.65) - ExpectantBot                            
   383175701.83 (  658.83) - Monte Carlo 46                          
   383164037.33 (  658.68) - LearnBot                                
   383162018.33 (  658.65) - ExpectorBot                             
   382292706.83 (  647.16) - CircumspectBot                          
   381960530.83 (  642.77) - LockBot                                 
   381786899.33 (  640.47) - PersonalFavoriteBot644                  
   381278314.83 (  633.75) - BasicBot                                
   381030871.83 (  630.48) - StrategicBot372                         
   380220471.33 (  619.77) - BestViableCandidate (1419177 from ratio, with 711341 tie-breakers of 10000000 total runs)
   380089578.33 (  618.04) - Priam                                   
   379714345.33 (  613.08) - Kelly's Favorite                        
   379548799.83 (  610.89) - Optimist                                
   379289709.83 (  607.46) - SometimesSecondBestBot                  
   377082526.83 (  578.29) - ABotDoNotForget                         
   376886555.33 (  575.70) - NoThirdPartyBot                         
   376473476.33 (  570.24) - NoClueBot                               
   368124262.83 (  459.88) - HateBot469                              
   355642629.83 (  294.89) - Follower                                
   352691241.83 (  255.88) - HipBot                                  
   345806934.83 (  164.88) - CommunismBot152                         
   345717541.33 (  163.70) - SmashAttemptByEquality (on 10000000 elections)
   345687786.83 (  163.30) - RandomBot484                            
   318549040.83 ( -195.42) - ExtremistBot                            
The tournament took 17115.327209018 seconds, or 285.25545348363335 minutes.

Ôi, tôi đã làm rất kém!
Ismael Miguel

Theo những gì tôi đã thấy trong mã, tham số thứ 2 là số phiếu còn lại. Và cái đầu tiên là Arraymột số lượng tất cả các phiếu. Tôi có đúng không?
Ismael Miguel

1
@IsmaelMiguel Có.
PhiNotPi

1
Thư hai. Chúng là kết quả một phần của cuộc bầu cử, là phiếu bầu của những người đi trước bạn theo thứ tự xáo trộn.
PhiNotPi

2
Bạn cũng có thể muốn xem xét những gì xảy ra khi bạn cung cấp cho cử tri một loạt các bản sao. Nhìn thoáng qua, đôi khiSecondBestBot, NoThirdPartyBot và người lạc quan dường như đều được hưởng lợi từ các nhóm bỏ phiếu lớn hơn. (Cũng như người cực đoanBot và, theo cách riêng của nó, chủ nghĩa cộng
sảnBot

Câu trả lời:


10

NoThirdPartyBot

Bot này cố gắng đoán ứng cử viên nào sẽ đứng thứ ba và bầu chọn ứng cử viên mà anh ta thích nhất trong hai người chạy trước.

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class NoThirdPartyBot implements Player {

    public NoThirdPartyBot(int e) {
    }


    @Override
    public String getName() {
        return "NoThirdPartyBot";
    }

    @Override
    public int getVote(int[] voteCounts, int votersRemaining, int[] payoffs,
            int[] totalPayoffs) {
        List<Integer> order = order(totalPayoffs);

        if (payoffs[order.get(0)] > payoffs[order.get(1)]) {
            return order.get(0);
        } else {
            return order.get(1);
        }
    }

    static List<Integer> order(int[] array) {
        List<Integer> indexes = Arrays.asList(0, 1, 2);
        Collections.sort(indexes, (i1, i2) -> array[i2] - array[i1]);
        return indexes;
    }

    @Override
    public void receiveResults(int[] voteCounts, double result) {
    }
}

CircumspectBot

Bot này bỏ phiếu cho mục yêu thích của anh ấy đã không bị loại bỏ về mặt toán học.

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;


public class CircumspectBot implements Player {

    public CircumspectBot(int elections) {
    }

    @Override
    public String getName() {
        return "CircumspectBot";
    }

    @Override
    public int getVote(int[] voteCounts, int votersRemaining, int[] payoffs,
            int[] totalPayoffs) {
        List<Integer> indexes = new ArrayList<>();
        int topVote = Arrays.stream(voteCounts).max().getAsInt();
        for (int index = 0; index < 3; index++) {
            if (voteCounts[index] + votersRemaining + 1 >= topVote) {
                indexes.add(index);
            }
        }
        Collections.sort(indexes, (i1, i2) -> payoffs[i2] - payoffs[i1]);

        return indexes.get(0);
    }

    @Override
    public void receiveResults(int[] voteCounts, double result) {

    }

}

4
Tôi muốn đặt cược Circumspect Bot hoàn toàn tốt hơn Bot yêu thích cá nhân. Tốt đẹp.
isaacg

10

ExpectantBot

Bot này tính toán giá trị dự kiến ​​của mỗi tùy chọn bỏ phiếu giả định rằng tất cả các cử tri sau đó sẽ bỏ phiếu ngẫu nhiên.

import java.util.Arrays;

public class ExpectantBot implements Player {

    public ExpectantBot(int elections) {
    }

    @Override
    public String getName() {
        return "ExpectantBot";
    }

    static double choose(int x, int y) {
        if (y < 0 || y > x) return 0;
        if (y > x/2) {
            // choose(n,k) == choose(n,n-k), 
            // so this could save a little effort
            y = x - y;
        }

        double denominator = 1.0, numerator = 1.0;
        for (int i = 1; i <= y; i++) {
            denominator *= i;
            numerator *= (x + 1 - i);
        }
        return numerator / denominator;
    }

    double expectedPayout(int[] voteCounts, int[] payoffs, int votersRemaining) {
        double total = 0.0;
        for (int firstPartyVoters = 0; firstPartyVoters <= votersRemaining; firstPartyVoters++) {
            for (int secondPartyVoters = 0; secondPartyVoters <= votersRemaining - firstPartyVoters; secondPartyVoters++) {
                int thirdPartyVoters = votersRemaining - firstPartyVoters - secondPartyVoters;

                int [] newVoteCounts = voteCounts.clone();
                newVoteCounts[0] += firstPartyVoters;
                newVoteCounts[1] += secondPartyVoters;
                newVoteCounts[2] += thirdPartyVoters;
                int highest = Arrays.stream(newVoteCounts).max().getAsInt();
                int payoff = 0;
                int winCount = 0;
                for (int index = 0; index < 3; index++) {
                    if (newVoteCounts[index] == highest) {
                        payoff += payoffs[index];
                        winCount++;
                    }
                }
                double v = (double)payoff / (double) winCount;
                double value = choose(votersRemaining, firstPartyVoters)*choose(votersRemaining - firstPartyVoters, secondPartyVoters)*v*Math.pow(1/3.0, votersRemaining);
                total += value;
            }
        }
        return total;
    }

    @Override
    public int getVote(int[] voteCounts, int votersRemaining, int[] payoffs,
            int[] totalPayoffs) {

        int bestVote = 0;
        double bestScore = 0.0;
        for (int vote = 0; vote < 3; vote++) {      
            voteCounts[vote]++;
            double score = expectedPayout(voteCounts, payoffs, votersRemaining);
            if (score > bestScore) {
                bestVote = vote;
                bestScore = score;
            }
            voteCounts[vote]--;
        }
        return bestVote;

    }

    @Override
    public void receiveResults(int[] voteCounts, double result) {   
    }

}

Không có sự thay đổi nặng nề từ các đối thủ khác, tôi sẽ ngạc nhiên nếu có bất cứ điều gì đánh bại anh chàng này.
DoctorHeckle

@DoctorHeckle, tôi đã có hy vọng cho StatBot, nhưng tôi nghĩ bạn đã đúng.
Winston Ewert

9

HipBot

HipBot không quan tâm đến các khoản thanh toán. Tiền chỉ là một loại thuốc an thần làm sao lãng nghệ thuật thực sự.

HipBot muốn bỏ phiếu cho một người thực sự , không chỉ là một số shill công ty. Anh ấy cũng muốn mặc chiếc áo chiến dịch của họ sau thất bại nhục nhã (có lẽ là) của họ, vì vậy anh ấy cảm thấy vượt trội mỗi khi người chiến thắng làm điều gì đó sai.

Do đó, HipBot bỏ phiếu cho người có số phiếu thấp nhất hoặc, nếu có sự ràng buộc, bất cứ ai có khoản thanh toán tốt hơn. Ăn hữu cơ - chỉ không miễn phí.

public class HipBot implements Player{

    public HipBot(int rounds){ /*Rounds are a social construct*/ }

    public String getName(){ return "HipBot"; }

    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs){

        int coolest = 0;
        int lowest = 100000000;
        int gains = 0;

        for( int count = 0; count < voteCounts.length; count++ ){

            if( voteCounts[count] < lowest || (voteCounts[count] == lowest && payoffs[count] > gains) ){

                lowest = voteCounts[count];
                coolest = count;
                gains = payoffs[count];

            }

        }

        return coolest;

    }

    public void receiveResults(int[] voteCounts, double result){ /*The past is dead*/ }

}

HipBot cũng chưa được kiểm tra, vì vậy hãy cho tôi biết nếu có bất cứ điều gì đang xảy ra.

EDIT: được thêm vào trong tiebreaking cạnh tranh hơn, bình luận súc tích.


làm việc cho tôi, mặc dù sự thương hại của anh ấy đối với người lỏng lẻo không ảnh hưởng nhiều đến điểm số của anh ấy :)
euanjt

5
Anh ấy đã chiến thắng trong tâm trí của mình, và đối với anh ấy, đó mới là vấn đề: D
DoctorHeckle

8

PersonalFavoriteBot

Bot này chỉ đơn giản bỏ phiếu cho ứng cử viên có tỷ lệ hoàn trả cá nhân cao nhất, bỏ qua mọi thứ khác. Một trong những điểm chính của thách thức này là chứng minh làm thế nào đây không phải là chiến lược tối ưu.

import java.lang.Math;
import java.util.Random;
/**
 * This bot picks the candidate with the highest personal payoff, ignoring everyone else's actions.
 * 
 * @author PhiNotPi 
 * @version 5/27/15
 */
public class PersonalFavoriteBot implements Player
{
    Random rnd;
    String name;
    /**
     * Constructor for objects of class PersonalFavoriteBot
     */
    public PersonalFavoriteBot(int e)
    {
       rnd = new Random(); 
       name = "PersonalFavoriteBot" + rnd.nextInt(1000);
    }

    public String getName()
    {
        return name;
    }

    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs)
    {
        //return rnd.nextInt(3);
        int maxloc = 0;
        for(int i = 1; i< 3; i++)
        {
            if(payoffs[i] > payoffs[maxloc])
            {
                maxloc = i;
            }
        }
        return maxloc;
    }

    public void receiveResults(int[] voteCounts, double result)
    {

    }
}

RandomBot

Bot này bình chọn ngẫu nhiên. Bất kể số lượng các cuộc bầu cử được thực hiện (miễn là nó cao một cách hợp lý, như hơn 100), điểm số bình thường của thí sinh này dao động trong khoảng -2 đến 2.

import java.lang.Math;
import java.util.Random;
/**
 * This bot votes for a random candidate.
 * 
 * @author PhiNotPi 
 * @version 5/27/15
 */
public class RandomBot implements Player
{
    Random rnd;
    String name;
    /**
     * Constructor for objects of class RandomBot
     */
    public RandomBot(int e)
    {
       rnd = new Random(); 
       name = "RandomBot" + rnd.nextInt(1000);
    }

    public String getName()
    {
        return name;
    }

    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs)
    {
        return rnd.nextInt(3);
    }

    public void receiveResults(int[] voteCounts, double result)
    {

    }
}

7

Người theo dõi

Follower muốn phù hợp. Nó nghĩ cách tốt nhất để thực hiện điều đó là bỏ phiếu giống như mọi người khác, hoặc ít nhất là với số nhiều cho đến nay. Nó sẽ phá vỡ mối quan hệ theo sở thích riêng của mình, để thể hiện một chút độc lập. Nhưng không quá nhiều.

public class Follower implements Player
{
    public Follower(int e) { }

    public String getName()
    {
        return "Follower";
    }

    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs)
    {
        int mostPopular = 0;
        int mostVotes = voteCounts[0];
        for (int i = 1; i < voteCounts.length; i++) {
            int votes = voteCounts[i];
            if (votes > mostVotes || (votes == mostVotes && payoffs[i] > payoffs[mostPopular])) {
                mostPopular = i;
                mostVotes = votes;
            }
        }
        return mostPopular;

    }

    public void receiveResults(int[] voteCounts, double result) { }
}

Lưu ý: Tôi chưa kiểm tra điều này, vì vậy hãy cho tôi biết nếu có bất kỳ lỗi nào.


Nó dường như làm việc.
PhiNotPi

4

Monte Carlo

Điều này mô phỏng một lượng lớn các cuộc bầu cử ngẫu nhiên. Sau đó, nó chọn lựa chọn tối đa hóa lợi nhuận của chính nó.

import java.util.ArrayList;
import java.util.List;

public class MonteCarlo implements Player{

    private static long runs = 0;
    private static long elections = 0;

    public MonteCarlo(int e) {
        elections = e;
    }

    @Override
    public String getName() {
        return "Monte Carlo (difficulty " + (runs / elections) + ")";
    }

    @Override
    public int getVote(int[] voteCounts, int votersRemaining, int[] payoffs, int[] totalPayoffs) {
        elections++;
        double[] predictedPayoffs = new double[3];
        long startTime = System.nanoTime();
        while (System.nanoTime() - startTime <= 200_000){ //Let's give us 200 micro-seconds.
            runs++;
            int[] simulatedVoteCounts = voteCounts.clone();
            for (int j = 0; j < votersRemaining; j++){
                simulatedVoteCounts[((int) Math.floor(Math.random() * 3))]++;
            }
            for (int j = 0; j < 3; j++) {
                simulatedVoteCounts[j]++;
                List<Integer> winners = new ArrayList<>();
                winners.add(0);
                for (int k = 1; k < 3; k++) {
                    if (simulatedVoteCounts[k] > simulatedVoteCounts[winners.get(0)]) {
                        winners.clear();
                        winners.add(k);
                    } else if (simulatedVoteCounts[k] == simulatedVoteCounts[winners.get(0)]) {
                        winners.add(k);
                    }
                }
                for (int winner : winners) {
                    predictedPayoffs[j] += payoffs[winner] / winners.size();
                }
                simulatedVoteCounts[j]--;
            }
        }
        int best = 0;
        for (int i = 1; i < 3; i++){
            if (predictedPayoffs[i] > predictedPayoffs[best]){
                best = i;
            }
        }
        return best;
    }

    @Override
    public void receiveResults(int[] voteCounts, double result) {

    }
}

4

StatBot

StatBot dựa trên ExpectantBot; tuy nhiên, thay vì cho rằng mỗi phiếu bầu đều có thể xảy ra như nhau, nó thu thập số liệu thống kê về cách mọi người bỏ phiếu và sử dụng số đó để ước tính xác suất.

import java.util.Arrays;


public class StatBot implements Player {

    static private int[][][] data = new int[3][3][3];
    private int[] voteCounts;

    StatBot(int unused) {

    }

    @Override
    public String getName() {
        return "StatBot";

    }

     static double choose(int x, int y) {
            if (y < 0 || y > x) return 0;
            if (y > x/2) {
                // choose(n,k) == choose(n,n-k), 
                // so this could save a little effort
                y = x - y;
            }

            double denominator = 1.0, numerator = 1.0;
            for (int i = 1; i <= y; i++) {
                denominator *= i;
                numerator *= (x + 1 - i);
            }
            return numerator / denominator;
        }

    double expectedPayout(int[] voteCounts, int[] payoffs, int votersRemaining) {
        Integer[] indexes = {0, 1, 2};
        Arrays.sort(indexes, (i0, i1) -> voteCounts[i1] - voteCounts[i0]);
        int [] stats = data[indexes[0]][indexes[1]];
        int total_stats = Arrays.stream(stats).sum();
        double total = 0.0;
        for (int firstPartyVoters = 0; firstPartyVoters <= votersRemaining; firstPartyVoters++) {
            for (int secondPartyVoters = 0; secondPartyVoters <= votersRemaining - firstPartyVoters; secondPartyVoters++) {
                int thirdPartyVoters = votersRemaining - firstPartyVoters - secondPartyVoters;

                int [] newVoteCounts = voteCounts.clone();
                newVoteCounts[0] += firstPartyVoters;
                newVoteCounts[1] += secondPartyVoters;
                newVoteCounts[2] += thirdPartyVoters;
                int highest = 0;
                for (int h : newVoteCounts) {
                    if (h > highest) highest = h;
                }
                int payoff = 0;
                int winCount = 0;
                for (int index = 0; index < 3; index++) {
                    if (newVoteCounts[index] == highest) {
                        payoff += payoffs[index];
                        winCount++;
                    }
                }
                double v = (double)payoff / (double) winCount;
                double value = choose(votersRemaining, firstPartyVoters)*choose(votersRemaining - firstPartyVoters, secondPartyVoters)*v;
                value *= Math.pow((double)stats[0]/(double)total_stats, firstPartyVoters);
                value *= Math.pow((double)stats[1]/(double)total_stats, secondPartyVoters);
                value *= Math.pow((double)stats[2]/(double)total_stats, thirdPartyVoters);

                total += value;
            }
        }
        return total;
    }

    @Override
    public int getVote(int[] voteCounts, int votersRemaining, int[] payoffs,
            int[] totalPayoffs) {

        int bestVote = 0;
        double bestScore = 0.0;
        for (int vote = 0; vote < 3; vote++) {      
            voteCounts[vote]++;
            double score = expectedPayout(voteCounts, payoffs, votersRemaining);
            if (score > bestScore) {
                bestVote = vote;
                bestScore = score;
            }
            voteCounts[vote]--;
        }
        voteCounts[bestVote]++;
        this.voteCounts = voteCounts;

        return bestVote;

    }

    @Override
    public void receiveResults(int[] endVoteCounts, double result) {
        Integer[] indexes = {0, 1, 2};
        Arrays.sort(indexes, (i0, i1) -> voteCounts[i1] - voteCounts[i0]);
        for(int i = 0; i < 3; i++){
            data[indexes[0]][indexes[1]][i] += endVoteCounts[i] - voteCounts[i];
        }
    }
}

4

Ứng viên khả thi nhất

Phiên bản sửa đổi khá nhiều của trình ban đầu của tôi. Điều này vẫn loại bỏ bất kỳ ứng cử viên nào không thể giành chiến thắng với số phiếu còn lại sẽ được bỏ, nhưng sau đó sử dụng chiến lược cố gắng tối ưu hóa mức chi trả tương đối thay vì tỷ lệ tuyệt đối. Thử nghiệm đầu tiên là lấy tỷ lệ chi trả cá nhân của tôi cho tổng số tiền chi trả cho mỗi ứng viên, tìm kiếm giá trị tốt nhất ở đó. Sau đó, tôi tìm kiếm các tỷ lệ khác rất gần với tỷ lệ tốt nhất và nếu có một tỷ lệ có tỷ lệ hoàn trả thấp hơn so với tỷ lệ tốt nhất tôi chọn thay thế. Hy vọng rằng điều này sẽ có xu hướng làm giảm tỷ lệ xuất chi của những người chơi khác trong khi giữ cho tôi ở mức cao hợp lý.

Bot này gần như giống như bản gốc trong thử nghiệm của riêng tôi, nhưng không hoàn toàn. Chúng ta sẽ phải xem nó hoạt động như thế nào so với toàn bộ lĩnh vực.

 /**
  * This bot picks the candidate with the highest relative payoff out of those
  * candidates who are not already mathematically eliminated.
  *
  * @author Ralph Marshall
  * @version 5/28/2015
  */

import java.util.List;
import java.util.ArrayList;


public class BestViableCandidate implements Player
{
    private static int NUM_CANDIDATES = 3;
    private int relativeCount = 0;
    private int relativeCountLowerTotal = 0;
    private int totalRuns;

    public BestViableCandidate(int r) {
        totalRuns = r;
    }

    public String getName() {
        return "BestViableCandidate (" + relativeCount + " from ratio, with " + relativeCountLowerTotal + " tie-breakers of " + totalRuns + " total runs)";
    }

    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs) {

        int i, maxVoteSoFar = 0;

        // First we figure out the maximum possible number of votes each candidate would get
        // if every remaining bot voted for it
        int [] maxPossibleVotes = new int[NUM_CANDIDATES];
        for (i = 0; i < NUM_CANDIDATES; i++) {

            // The voters remaining does not include me, so we need to add one to it
            maxPossibleVotes[i] = voteCounts[i] + votersRemaining + 1;

            if (voteCounts[i] > maxVoteSoFar) {
                maxVoteSoFar = voteCounts[i];
            }
        }

        // Then we throw out anybody who cannot win even if they did get all remaining votes
        List<Integer> viableCandidates = new ArrayList<Integer>();
        for (i = 0; i < NUM_CANDIDATES; i++) {
            if (maxPossibleVotes[i] >= maxVoteSoFar) {
                viableCandidates.add(Integer.valueOf(i));
            }
        }

        // And of the remaining candidates we pick the one that has the personal highest payoff
        // relative to the payoff to the rest of the voters
        int maxCandidate = -1;
        double maxRelativePayoff = -1;
        int maxPayoff = -1;
        int minTotalPayoff = Integer.MAX_VALUE;

        int originalMaxCandidate = -1;
        double originalMaxPayoff = -1;

        double DELTA = 0.01;

        double tiebreakerCandidate = -1;

        for (Integer candidateIndex : viableCandidates) {
            double relativePayoff = (double) payoffs[candidateIndex] / (double) totalPayoffs[candidateIndex];
            if (maxRelativePayoff < 0 || relativePayoff - DELTA > maxRelativePayoff) {
                maxRelativePayoff = relativePayoff;
                maxCandidate = candidateIndex;

                maxPayoff = payoffs[candidateIndex];
                minTotalPayoff = totalPayoffs[candidateIndex];

            } else if (Math.abs(relativePayoff - maxRelativePayoff) < DELTA) {
                if (totalPayoffs[candidateIndex] < minTotalPayoff) {
                    tiebreakerCandidate = candidateIndex;

                    maxRelativePayoff = relativePayoff;
                    maxCandidate = candidateIndex;

                    maxPayoff = payoffs[candidateIndex];
                    minTotalPayoff = totalPayoffs[candidateIndex];

                }
            }

            if (payoffs[candidateIndex] > originalMaxPayoff) {
                originalMaxPayoff = payoffs[candidateIndex];
                originalMaxCandidate = candidateIndex;
            }
        }

        if (tiebreakerCandidate == maxCandidate) {
            relativeCountLowerTotal++;
        }

        if (originalMaxCandidate != maxCandidate) {
            /*                System.out.printf("%nSelecting candidate %d with relative payoff %f (%d/%d) instead of %d with relative payoff %f (%d/%d)%n",
                              maxCandidate, (double) payoffs[maxCandidate]/(double)totalPayoffs[maxCandidate], payoffs[maxCandidate], totalPayoffs[maxCandidate],
                              originalMaxCandidate, (double) payoffs[originalMaxCandidate]/(double)totalPayoffs[originalMaxCandidate], payoffs[originalMaxCandidate], totalPayoffs[originalMaxCandidate]);
            */
            relativeCount++;
        }

        return maxCandidate;
    }
}

1
Đây không giống như CircumspectBot?
TheNumberOne

Vâng, hóa ra nó là; Tôi đã bình luận về hiệu ứng đó trong câu hỏi chính. Khi tôi bắt đầu viết mã, tôi không nhận ra chính xác nó hoạt động như thế nào. Vì CircumspectBot được viết trước tiên nên rõ ràng sẽ nhận được tín dụng cho ý tưởng.
Ralph Marshall

Tôi nghĩ rằng bạn đang bỏ lỡ kết thúc lớp học của bạn.
Winston Ewert

Cảm ơn. Tôi đã mất cú đúp cuối cùng; không có mã nào khác sau những gì ở đó.
Ralph Marshall

3

Người lạc quan

Người lạc quan rất lạc quan và cho rằng một nửa số cử tri còn lại sẽ bỏ phiếu cho ứng cử viên mang lại cho họ mức thưởng cao nhất.

import java.lang.Integer;
import java.lang.String;
import java.util.Arrays;
import java.util.Comparator;

public class Optimist implements Player
{
    public Optimist(int _) { }
    public String getName() { return "Optimist"; }
    public int getVote(int[] curVotes, int rem, final int[] payoffs, int[] _)
    {
        Integer[] opt = new Integer[] { 0, 1, 2 };
        Arrays.sort(opt, new Comparator<Integer>() { public int compare(Integer i1, Integer i2) { return payoffs[i1] > payoffs[i2] ? -1 : payoffs[i1] == payoffs[i2] ? 0 : 1; } });
        int a = curVotes[opt[0]], b = curVotes[opt[1]], c = curVotes[opt[2]];
        double rest = (double)rem / 4;
        if (b <= a + rest && c <= a + rest)
            return opt[0];
        else if (c <= b)
            return opt[1];
        else
            return opt[0];
    }
    public void receiveResults(int[] _, double __) { }
}

3

ABotDoNotForget

Mục tiêu của anh ta rất đơn giản: xác định xu hướng chung bằng cách sử dụng tổng số tiền chi trả và đếm số thời gian mà những người thấp hơn / trung bình / cao hơn giành được. Sau đó, anh ta sẽ bỏ phiếu cho người có khả năng chiến thắng cao nhất.

import java.util.ArrayList;

public class ABotDoNotForget implements Player
{
    private int nbElec;
    private int countElec=0;
    private int[] currPayoffs=new int[3];
    private int[] lmh=new int[3];
    private int[] wins=new int[3];

    public ABotDoNotForget(int nbElec)
    {
        this.nbElec=nbElec;
    }

    public String getName() {return "ABotDoNotForget";}

    public int getVote(int[] voteCounts, 
                        int votersRemaining, 
                        int[] payoffs,
                        int[] totalPayoffs) 
    {
        countElec++;
        System.arraycopy(totalPayoffs, 0, currPayoffs, 0, totalPayoffs.length);

        if(countElec<=nbElec/20&&countElec<=20)
        {
            int best=0;
            for(int i=1;i<payoffs.length;i++)
                if(payoffs[i]>=payoffs[best])
                    best=i;
            return best;
        }

        for(int i =1;i<totalPayoffs.length;i++)
        {
            if(totalPayoffs[i]<totalPayoffs[i-1])
            {
                int tmp= totalPayoffs[i];
                totalPayoffs[i]=totalPayoffs[i-1];
                totalPayoffs[i-1]=tmp;
                if(i==2&&totalPayoffs[i-1]<totalPayoffs[i-2]){
                    tmp= totalPayoffs[i-1];
                    totalPayoffs[i-1]=totalPayoffs[i-2];
                    totalPayoffs[i-2]=tmp;
                }
            }
        }
        lmhDist(currPayoffs,totalPayoffs);
        int best=0;
        for(int i=1;i<wins.length;i++)
            if(wins[i]>=wins[best]){
                best=i;
            }
        int ownH=0;
        for(int i=1;i<payoffs.length;i++)
            if(payoffs[i]>=payoffs[ownH])
                ownH=i;
        int ownM=0;
        for(int i=1;i<payoffs.length;i++)
            if(payoffs[i]>=payoffs[ownM]&&i!=ownH)
                ownM=i;

        int persBest=(voteCounts[ownH]-voteCounts[ownM]+(votersRemaining/3)>=0
                &&voteCounts[ownH]-voteCounts[best]<(votersRemaining/3))?ownH:ownM;

        return persBest;

    }

    public void receiveResults(int[] voteCounts, double result) 
    {
        int best=0,bestV=voteCounts[best];
        for(int i=1;i<voteCounts.length;i++)
            if(voteCounts[i]>=bestV){
                best=i;
                bestV=voteCounts[i];
            }
        wins[lmh[best]]++;

    }

    private void lmhDist(int[] a,int[] s)
    {
        ArrayList<Integer> al = new ArrayList<Integer>();
        al.add(a[0]);al.add(a[1]);al.add(a[2]);
        lmh[0]=al.indexOf(s[0]);
        lmh[1]=al.indexOf(s[1]);
        lmh[2]=al.indexOf(s[2]);

    }
}

Chỉnh sửa :

Một số thay đổi được thực hiện trong đại số quyết định, bây giờ có tính đến khoản chi trả tốt nhất của chính ông. Bây giờ có thể bỏ phiếu tốt hơn khi phân phối hiện tại đang khiến anh ấy bỏ phiếu cho chính Hạ của mình khi những người khác bỏ phiếu cho mức thưởng cao hơn của họ.


3

Giải thưởng

Priam ghét đệ quy. Ông ước tính xác suất của mỗi bot còn lại dựa trên tổng số tiền chi trả và sau đó tính toán cách tốt nhất để tối đa hóa khoản thanh toán của mình.

public class Priam implements Player {
    private static double[] smallFactorials = {1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600,6227020800.,87178291200.,1307674368000.,20922789888000.,355687428096000.,6402373705728000.,121645100408832000.,2432902008176640000.};
    @Override
    public String getName() {
        return "Priam";
    }

    @Override
    public int getVote(int[] voteCounts, int votersRemaining, int[] payoffs,
            int[] totalPayoffs) {
        int totalPayoff = totalPayoffs[0] + totalPayoffs[1] + totalPayoffs[2];
        double p0 = ((double)totalPayoffs[0])/totalPayoff;
        double p1= ((double) totalPayoffs[1])/totalPayoff;
        double p2 = ((double)totalPayoffs[2])/totalPayoff;
        double[] expectedPayoffs = {0,0,0};
        for(int myChoice=0;myChoice<3;myChoice++)
        {
            for(int x0 = 0; x0 <= votersRemaining; x0++)
            {
                for(int x1 = 0; x1 <= (votersRemaining-x0); x1++)
                {
                    int x2 = votersRemaining - (x1 + x0);
                    double probability =
                            Math.pow(p0, x0)
                            * Math.pow(p1, x1)
                            * Math.pow(p2, x2)
                            * Choose(votersRemaining, x0)
                            * Choose(votersRemaining-x0, x1);
                    int votes0 = voteCounts[0];
                    int votes1 = voteCounts[1];
                    int votes2 = voteCounts[2];
                    if(myChoice == 0)
                    {
                        votes0++;
                    }
                    else if(myChoice==1)
                    {
                        votes1++;
                    }
                    else
                    {
                        votes2++;
                    }

                    votes0+=x0;
                    votes1+=x1;
                    votes2+=x2;
                    if(votes0>votes1 && votes0>votes2)
                    {
                        expectedPayoffs[myChoice]+=probability*payoffs[0];
                    }
                    else if(votes1>votes2)
                    {
                        expectedPayoffs[myChoice]+=probability*payoffs[1];
                    }
                    else
                    {
                        expectedPayoffs[myChoice]+=probability*payoffs[2];
                    }
                }
            }
        }
        if(expectedPayoffs[0]>expectedPayoffs[1] && expectedPayoffs[0]>expectedPayoffs[2])
        {
            return 0;
        }
        else if(expectedPayoffs[1]>expectedPayoffs[2])
        {
            return 1;
        }
        else
        {
            return 2;
        }
    }

    private long Choose(int source, int team) {
        return Factorial(source)/(Factorial(team)*Factorial(source-team));
    }

    private long Factorial(int n) {
        if(n<=20)
        {
            return (long)smallFactorials[n];
        }
        double d=(double)n;
        double part1 = Math.sqrt(2*Math.PI*d);
        double part2 = Math.pow(d/Math.E, d);
        return (long)Math.ceil(part1 * part2);
    }

    @Override
    public void receiveResults(int[] voteCounts, double result) {


    }
    public Priam(int i)
    {

    }
}

Nhanh hơn nhiều so với Odysseus vì không có đệ quy (chạy trong thời gian O (n ^ 2)) và có thể thực hiện một triệu cuộc bầu cử trong khoảng 15 giây.


"Tôi nghĩ rằng đây là bot đầu tiên sử dụng tham số tổng số tiền chi trả cho lợi ích riêng của mình :)" Hãy nhìn vào bot của tôi (ABotDoNotForget), anh ấy đã sử dụng nó, xin lỗi: D
Katenkyo 29/05/2015

Rất giống với bot mới nhất của tôi, ExpectantBot, ngoại trừ việc bạn sử dụng TotalPayoffs để dự đoán xác suất và tôi cho rằng mọi phiếu bầu đều có thể xảy ra như nhau. Tôi mong muốn xem chiến lược nào hoạt động tốt nhất.
Winston Ewert

@WinstonEwert Tôi nghĩ là của bạn, bạn đã thắng ba bài kiểm tra cuối cùng tôi đã làm.
euanjt

Tôi chỉ nhận thấy sự giống nhau - Tôi đã cố gắng tạo ra một phiên bản Odysseus không mất 10 giờ để chạy 100 cuộc bầu cử, vì vậy tôi đã sử dụng các vòng lặp
euanjt

Thành thật mà nói, tôi đã được truyền cảm hứng để tiếp cận bởi Odysseus.
Winston Ewert

2

NoClueBot

NoClue thực sự không biết nhiều về Java hoặc toán học, vì vậy anh ta không biết liệu tỷ lệ trọng số này sẽ giúp anh ta giành chiến thắng. Nhưng anh ấy đang cố gắng.

import java.lang.Math;
import java.util.*;
/**
 * Created by Admin on 5/27/2015.
 */
public class NoClueBot implements Player {

    public NoClueBot(int e) { }

    public String getName() {
        return "NoClueBot";
    }

    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs) {
        double x = 0;
        int y = 0;
        for (int i=0; i<3; i++) {
            double t = (double) voteCounts[i] * ((double) payoffs[i]/(double) totalPayoffs[i]);
            if (x<t) {
                x = t;
                y = i; 
            }
        }
        return y;
    }

    public void receiveResults(int[] voteCounts, double result) { }
}


Một số ClueBot

Một sốClueBot đã ngừng hoạt động. thực sự sử dụng logic! Được sử dụng logic, hóa ra là không hiệu quả, vì vậy thay vào đó anh ta trở nên chú ý đến tổng số tiền chi trả, chứ không phải của mình. sử dụng logic một lần nữa! Nhưng anh ta không làm tốt với tất cả những người theo dõi và những người lạc quan này, và thậm chí cả những người không quan tâm! :)


Đôi khiSecondBestBot

Về cơ bản PersonalFavouriteBot, được cải thiện (về lý thuyết).

import java.lang.Math;
/**
 * Created by Admin on 5/27/2015.
 */
public class SometimesSecondBestBot implements Player {
    public SometimesSecondBestBot(int e) { }

    public String getName() {
        return "SometimesSecondBestBot";
    }

    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs) {
        int m = 0;
        int n = 0;
        for(int i = 1; i< 3; i++) {
            if(payoffs[i] > payoffs[m]) { n = m; m = i; }
        }
        return (voteCounts[n]>voteCounts[m]&&totalPayoffs[n]>totalPayoffs[m])||(voteCounts[m]+votersRemaining<voteCounts[n])||voteCounts[m]+votersRemaining<voteCounts[Math.min(3-n-m, 2)] ? n : m;
    }

    public void receiveResults(int[] voteCounts, double result) { }
}

1
Có vẻ như bạn tính toán một số lớn nhất trong ba trọng số và hơn lấy giá trị đó mod 3 để chọn ứng cử viên tốt nhất. Điều đó có đúng không và nếu không thì về cơ bản nó là một con số ngẫu nhiên? Tôi hiểu rằng bạn đang gọi đây là "toán học là khó Barbie", vì vậy tôi không chắc mình có khái niệm này.
Ralph Marshall

@RalphMarshall Vâng, về cơ bản là ngẫu nhiên. Tuy nhiên, tôi hoàn toàn không có ý định làm điều đó, đã không chú ý, haha. Đã sửa nó ngay.
Kade

@PhiNotPhi Tôi nghĩ rằng tôi đã sửa nó ra khỏi phạm vi bây giờ. Và vâng, tôi không ngạc nhiên.
Kade

Trời ơi, điều này thật tệ .. trong công việc phòng thủ của tôi đã cực kỳ cạn kiệt tinh thần ngày hôm nay.
Kade

2

Người cực đoan

Luôn bỏ phiếu cho ứng cử viên có tỷ lệ hoàn trả thấp nhất

public class ExtremistBot implements Player
{
    public ExtremistBot(int e){}

    public void receiveResults(int[] voteCounts, double result){}

    public String getName(){
        return "ExtremistBot";
    }

    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs)
    {
        int min = 0;
        for(int i = 1; i<payoffs.length; i++){
            if(payoffs[i] <payoffs[min]){
                min = i;
            }
        }
        return min;
    }
}

2

SmashAtteemByEquality

Mục tiêu là để cân bằng tất cả các ứng cử viên, sau đó SMASH! tất cả các bot khác trên vòng cuối cùng.
Đây là một thuật toán phá hoại cố gắng loại bỏ tất cả những cái khác, để giành chiến thắng.

public class SmashAttemptByEquality implements Player {
    static private int elections;

    public SmashAttemptByEquality(int e) { 
        this.elections = e;
    }

    public String getName() {
        return "SmashAttemptByEquality (on " + String.valueOf(this.elections) + " elections)";
    }

    public int getVote(int[] voteCounts, int votersRemaining, int[] payoffs, int[] totalPayoffs) {

        //if there are no votes or it is a tie
        if(voteCounts.length == 0 || (voteCounts[0] == voteCounts[1] && voteCounts[1] == voteCounts[2]))
        {
            //let the system handle the (distributed?) randomness
            return 3;
        }

        //we want to win, so, lets not mess when there are no voters left
        if( votersRemaining > 0 )
        {
            //lets bring some equality!
            if( voteCounts[0] >= voteCounts[1] )
            {
                if(voteCounts[0] > voteCounts[2])
                {
                    return 2;
                }
                else
                {
                    return 0;
                }
            }
            else if( voteCounts[1] >= voteCounts[2] )
            {
                if(voteCounts[1] > voteCounts[0])
                {
                    return 0;
                }
                else
                {
                    return 1;
                }
            }
            else
            {
                return 0;
            }
        }
        else
        {
            //just play for the winner!
            if( voteCounts[0] >= voteCounts[1] )
            {
                if(voteCounts[0] > voteCounts[2])
                {
                    return 0;
                }
                else
                {
                    return 2;
                }
            }
            else if( voteCounts[1] >= voteCounts[2] )
            {
                if(voteCounts[1] > voteCounts[0])
                {
                    return 1;
                }
                else
                {
                    return 0;
                }
            }
            else
            {
                return 0;
            }
        }
    }

    public void receiveResults(int[] voteCounts, double result) { }
}

Lưu ý rằng điều này chưa được kiểm tra !


2

Bot cơ bản

Bot cơ bản chỉ bầu chọn cho những ứng cử viên không bị loại và có mức chi trả tối đa lớn nhất từ ​​những ứng cử viên đó.

public class BasicBot implements Player {
    public BasicBot(int e) { }
    public String getName()
    {
        return "BasicBot";
    }
    public static int getMax(int[] inputArray){ 
    int maxValue = inputArray[0]; 
    for(int i=1;i < inputArray.length;i++){ 
      if(inputArray[i] > maxValue){ 
         maxValue = inputArray[i]; 
      } 
    } 
    return maxValue; 
   }
    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs)
    {
        // Check for Eliminated Candidates
        int eliminated0 = 0;
        int eliminated1 = 0;
        int eliminated2 = 0;
        if( ((voteCounts[0] + votersRemaining) < voteCounts[1]) || ((voteCounts[0] + votersRemaining) < voteCounts[2]))
        {
            eliminated0 = 1;
        }
        if( ((voteCounts[1] + votersRemaining) < voteCounts[0]) || ((voteCounts[1] + votersRemaining) < voteCounts[2]))
        {
            eliminated1 = 1;
        }
        if( ((voteCounts[2] + votersRemaining) < voteCounts[0]) || ((voteCounts[2] + votersRemaining) < voteCounts[1]))
        {
            eliminated2 = 1;
        }
        // Choose the Candidates that is not elimated with the largest payoff
        if ((payoffs[0] == getMax(payoffs)) && eliminated0 == 0)
            return 0
        else if ((payoffs[1] == getMax(payoffs)) && eliminated1 == 0)
            return 1
        else
            return 2

    }

    public void receiveResults(int[] voteCounts, double result)
    {
    }

}

2

Yêu thích của Kelly

Tôi đã bắt đầu với CircumspectBot, nhưng không còn nhiều. Tạo ra một loại dự đoán nhàm chán về phân phối xác suất của các phiếu còn lại, và sau đó đưa ra lựa chọn tối đa hóa tiện ích đăng nhập của riêng mình (Tiêu chí Kelly). Không phải là nhanh nhất, nhưng trong công viên bóng của một số người khác. Ngoài ra, nó khá cạnh tranh với lĩnh vực này (vì nó đã đứng khi tôi bắt đầu làm việc này và tải xuống các bot khác).

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.HashMap;

public class KellysFavorite implements Player {
    private ArrayList<Double> cache = new ArrayList<Double>();

    public KellysFavorite(int elections) {
        cache.add(0.0);
        double v = 0.0;
        for(int i=1; i<1000; i++) {
            v += Math.log(i);
            cache.add(v);
        }
    }

    @Override
    public String getName() {
        return "Kelly's Favorite";
    }

    private double factln(int n) {
        return cache.get(n);
    }

    private  double binll(int x, int n, double p)
    {
        double ll = 0.0;
        ll += ((double)x)*Math.log(p);
        ll += ((double)(n - x))*Math.log(1.0 - p);
        ll += factln(n) - factln(x) - factln(n-x);
        return ll;
    }

    public  double logAdd(double logX, double logY) {
        // 1. make X the max
        if (logY > logX) {
            double temp = logX;
            logX = logY;
            logY = temp;
        }
        // 2. now X is bigger
        if (logX == Double.NEGATIVE_INFINITY) {
            return logX;
        }
        // 3. how far "down" (think decibels) is logY from logX?
        //    if it's really small (20 orders of magnitude smaller), then ignore
        double negDiff = logY - logX;
        if (negDiff < -20) {
            return logX;
        }
        // 4. otherwise use some nice algebra to stay in the log domain
        //    (except for negDiff)
        return logX + java.lang.Math.log(1.0 + java.lang.Math.exp(negDiff));
    }

    @Override
    public int getVote(int[] voteCounts,
                       int votersRemaining,
                       int[] payoffs,
                       int[] totalPayoffs) {
        int totalviable = 0;
        boolean[] viable = { false, false, false };
        int topVote = Arrays.stream(voteCounts).max().getAsInt();
        for (int index = 0; index < 3; index++) {
            if (voteCounts[index] + votersRemaining + 1 >= topVote) {
                viable[index] = true;
                totalviable += 1;
            }
        }

        // if only one candidate remains viable, vote for them
        if(totalviable == 1) {
            for(int index = 0; index < 3; index++)
                if(viable[index])
                    return index;
        } else {
            double votelikelihoods[] = { 0.0, 0.0, 0.0 };
            double totalweight = 0.0;
            for(int index=0; index<3; index++) {
                if(!viable[index])
                    votelikelihoods[index] -= 10.0;
                else if(voteCounts[index] < topVote)
                    votelikelihoods[index] -= 0.1;

                totalweight += Math.exp(votelikelihoods[index]);
            }

            double probs[] = new double[3];
            for(int index=0; index<3; index++) {
                probs[index] = Math.exp(votelikelihoods[index]) / totalweight;
            }

            double[] utilities = {0,0,0};
            for(int mychoice=0; mychoice<3; mychoice++) {
                boolean seen[] = { false, false, false };
                double likelihoods[] = { Double.NEGATIVE_INFINITY,
                                         Double.NEGATIVE_INFINITY,
                                         Double.NEGATIVE_INFINITY };
                int[] localVoteCounts = { voteCounts[0] + (mychoice==0?1:0),
                                          voteCounts[1] + (mychoice==1?1:0),
                                          voteCounts[2] + (mychoice==2?1:0) };
                for(int iVotes=0; iVotes<=votersRemaining; iVotes++)
                    for(int jVotes=0; jVotes<=(votersRemaining-iVotes); jVotes++) {
                        int kVotes = votersRemaining - iVotes - jVotes;

                        int a = localVoteCounts[0] + iVotes;
                        int b = localVoteCounts[1] + jVotes;
                        int c = localVoteCounts[2] + kVotes;
                        int wincount = Math.max(a, Math.max(b, c));
                        int winners = 0;
                        if(a>=wincount) { winners += 1; }
                        if(b>=wincount) { winners += 1; }
                        if(c>=wincount) { winners += 1; }

                        double likelihood =
                            binll(iVotes, votersRemaining, probs[0])
                            + binll(jVotes, votersRemaining-iVotes, probs[1] / (probs[1] + probs[2]));

                        likelihood += Math.log(1.0/winners);

                        if(a>=wincount) {
                            if(seen[0])
                                likelihoods[0] = logAdd(likelihoods[0],
                                                        likelihood);
                            else
                                likelihoods[0] = likelihood;
                            seen[0] = true;
                        }
                        if(b>=wincount) {
                            if(seen[1])
                                likelihoods[1] = logAdd(likelihoods[1],
                                                        likelihood);
                            else
                                likelihoods[1] = likelihood;
                            seen[1] = true;
                        }
                        if(c>=wincount) {
                            if(seen[2])
                                likelihoods[2] = logAdd(likelihoods[2],
                                                        likelihood);
                            else
                                likelihoods[2] = likelihood;
                            seen[2] = true;
                        }

                    }

                for(int index=0; index<3; index++)
                    utilities[mychoice] += Math.exp(likelihoods[index]) * Math.log((double)payoffs[index]);
            }

            double maxutility = Math.max(utilities[0], Math.max(utilities[1], utilities[2]));
            int choice = 0;
            for(int index=0; index<3; index++)
                if(utilities[index]>=maxutility)
                    choice = index;
            return choice;
        }

        throw new InternalError();
    }

    @Override
    public void receiveResults(int[] voteCounts, double result) {

    }

}

Cũng có sẵn tại https://gist.github.com/jkominek/dae0b3158dcd253e09e5 trong trường hợp đơn giản hơn.


2

Chủ nghĩa cộng sản

CommunismBot nghĩ rằng tất cả chúng ta nên hòa đồng và chọn ứng cử viên phù hợp nhất với mọi người.

public class CommunismBot implements Player
{
    Random rnd;
    String name;
    public CommunismBot(int e) {
        rnd = new Random(); 
        name = "CommunismBot" + rnd.nextInt(1000);
    }

    public String getName()
    {
        return name;
    }

    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs)
    {
        int maxloc = 0;
        for(int i = 1; i< 3; i++)
        {
            if(totalPayoffs[i] > totalPayoffs[maxloc])
            {
                maxloc = i;
            }
        }
        return maxloc;
    }

    public void receiveResults(int[] voteCounts, double result) { }
}

Hatebot

Hatebot luôn chọn ứng cử viên tốt nhất. Trừ khi họ là một bữa tiệc bẩn thỉu bẩn thỉu 1. Những kẻ đó thật kinh khủng.

import java.util.Random;


public class HateBot implements Player
{
    Random rnd;
    String name;
    public HateBot(int e) {
        rnd = new Random(); 
        name = "HateBot" + rnd.nextInt(1000); }

    public String getName()
    {
        return name;
    }

    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs)
    {
        if(payoffs[0]>payoffs[2])
            return 0;
        else
            return 2;
    }

    public void receiveResults(int[] voteCounts, double result) { }
}

StrategicBot

StrategicBot bỏ phiếu cho ứng cử viên tốt nhất với điều kiện là họ nằm trong một độ lệch chuẩn của ứng cử viên tốt nhất tiếp theo, với số lượng cử tri còn lại.

import java.util.Random;

public class StrategicBot implements Player
{
    Random rnd;
    String name;
    public StrategicBot(int e) {
        rnd = new Random(); 
        name = "StrategicBot" + rnd.nextInt(1000);

    }

    public String getName()
    {
        return name;
    }

    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs)
    {
        double margin = 9.0*votersRemaining/9;
        int maxloc = 0;
        boolean noLead=false;
        for(int i = 1; i< 3; i++)
        {
            for(int j = 1; j < 3; j++)
            {
                if(payoffs[j] + margin > payoffs[i])
                    noLead=true;
            }
            if(payoffs[i] > payoffs[maxloc] && noLead)
            {
                maxloc = i;
            }
            noLead=false;
        }
        return maxloc;
    }

    public void receiveResults(int[] voteCounts, double result) { }
}

2

ExpectorBot

Cố gắng dự đoán tất cả các Bots khác sẽ bỏ phiếu bằng cách tính Xuất chi trung bình cho những người khác. Phiếu bầu mặc định cho mức chi trả tốt nhất, nhưng sẽ bỏ phiếu cho vị trí thứ hai tốt nhất, nếu nó có nhiều phiếu dự kiến ​​hơn mức tốt nhất, mức chi trả trung bình tốt hơn cho tôi và khoản thanh toán tệ nhất có cơ hội chiến thắng điều này.

import java.util.Arrays;

public class ExpectorBot implements Player
{
    class Votee
    {
        int index;
        int payoff;
        float avgPayoff;
        float expectedVotes;
    }

    public ExpectorBot( final int e )
    {

    }

    @Override
    public String getName()
    {
        return "ExpectorBot";
    }

    @Override
    public int getVote( final int[] voteCounts, final int votersRemaining, final int[] payoffs, final int[] totalPayoffs )
    {
        final int otherVoters = Arrays.stream( voteCounts ).sum() + votersRemaining;
        final Votee[] v = createVotees( voteCounts, otherVoters, votersRemaining, payoffs, totalPayoffs );

        final Votee best = v[ 0 ]; // Most Payoff
        final Votee second = v[ 1 ];
        final Votee worst = v[ 2 ];

        int voteFor = best.index;

        if( ( second.expectedVotes >= best.expectedVotes + 1 ) // Second has more votes than Best even after I vote
                && ( second.payoff >= second.avgPayoff ) // Second payoff better than average for the others
                && ( worst.expectedVotes >= best.expectedVotes + 0.5f ) ) // Worst has a chance to win
        {
            voteFor = second.index;
        }

        return voteFor;
    }

    private Votee[] createVotees( final int[] voteCounts, final int otherVoters, final int votersRemaining, final int[] payoffs, final int[] totalPayoffs )
    {
        final Votee[] v = new Votee[ 3 ];

        for( int i = 0; i < 3; ++i )
        {
            v[ i ] = new Votee();
            v[ i ].index = i;
            v[ i ].payoff = payoffs[ i ];

            // This is the average payoff for other Players from this Votee
            v[ i ].avgPayoff = (float)( totalPayoffs[ i ] - payoffs[ i ] ) / otherVoters;

            // The expected number of Votes he will get if everyone votes for biggest payoff
            v[ i ].expectedVotes = voteCounts[ i ] + ( votersRemaining * v[ i ].avgPayoff / 100.0f );
        }

        Arrays.sort( v, ( o1, o2 ) -> o2.payoff - o1.payoff );

        return v;
    }

    @Override
    public void receiveResults( final int[] voteCounts, final double result )
    {

    }
}

1

LockBot

Chỉ là một triết gia cô đơn, tìm kiếm "e" ...

//He thinks he's the father of democracy, but something's missing....
public class LockBot implements Player {

public LockBot(int i) {
    //One election, 10000000, what's the difference?
}

@Override
public String getName() {
    return "LockBot";
}

@Override
public int getVote(int[] voteCounts, int votersRemaining, int[] payoffs,
        int[] totalPayoffs) {

    double totalPlayers = voteCounts.length + votersRemaining;
    double totalPayoff = totalPlayers * 100;

    //adjust total payoffs to ignore my own
    for( int i = 0; i < totalPayoffs.length; i++){
        totalPayoffs[i] -= payoffs[i];
    }

    //Votes are probably proportional to payoffs
    //So lets just find the highest weight
    double[] expectedOutcome = new double[3];
    for(int i = 0; i< expectedOutcome.length; i++){
        expectedOutcome[i] = (totalPayoffs[i] / totalPayoff) * payoffs[i];
    }

    //Find the highest
    int choice = 0;
    if(expectedOutcome[1] > expectedOutcome[choice]){
        choice = 1;
    }
    if(expectedOutcome[2] > expectedOutcome[choice]){
        choice = 2;
    }




    return choice;
}

@Override
public void receiveResults(int[] voteCounts, double result) {
    // TODO Auto-generated method stub

}

}

0

Thắng thua

Nếu bạn thắng, tôi thua! Thật đơn giản. Vì vậy, bot này bỏ phiếu cho người mà anh ấy thích và những người khác không thích.

public class WinLose implements Player
{
    public WinLose(int e) { }

    public String getName()
    {
        return "WinLose";
    }
    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs)
    {
        int max = 0;
        for(int i = 1; i< 3; i++)
        {
            if(10*payoffs[i]-totalPayoffs[i] > 10*payoffs[max]-totalPayoffs[max])
            {
                max = i;
            }
        }
        return max;
    }

    public void receiveResults(int[] voteCounts, double result)
    {

    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.