การลงคะแนนเชิงกลยุทธ์, เกม


37

หนึ่งในระบบลงคะแนนที่ใช้กันมากที่สุดสำหรับการเลือกตั้งผู้ชนะเพียงคนเดียวคือวิธีการลงคะแนนส่วนใหญ่ เพียงแค่ใส่ผู้สมัครที่มีคะแนนโหวตมากที่สุดชนะ การออกเสียงลงคะแนนส่วนใหญ่ แต่เป็นคณิตศาสตร์ที่ไม่มั่นคงและมีแนวโน้มที่จะสร้างสถานการณ์ที่ผู้มีสิทธิเลือกตั้งจะถูกผลักดันให้ลงคะแนนให้ "น้อยกว่าสองชั่วร้าย" เมื่อเทียบกับผู้สมัครที่พวกเขาต้องการอย่างแท้จริง

ในเกมนี้คุณจะเขียนโปรแกรมที่ใช้ประโยชน์จากระบบการลงคะแนนส่วนใหญ่ มันจะลงคะแนนให้หนึ่งในสามของผู้สมัครในการเลือกตั้ง ผู้สมัครแต่ละคนมีความเกี่ยวข้องกับผลตอบแทนที่แน่นอนสำหรับตัวคุณเองและเป้าหมายของคุณคือเพิ่มผลตอบแทนที่คุณคาดหวังให้สูงสุด

ผลตอบแทนคือ "สม่ำเสมอ" กระจายสุ่มเปลี่ยนการเลือกตั้งในแต่ละครั้งและเพิ่ม 100 ผู้สมัครAอาจมีผลตอบแทน 40 ผู้สมัครBสามารถจ่าย 27 และผู้สมัครCสามารถมีผลตอบแทน 33 ผู้เล่นแต่ละคนมีการจ่ายเงินที่แตกต่างกัน

เมื่อถึงคราวที่คุณจะลงคะแนนคุณจะมีข้อมูลที่ไม่สมบูรณ์ ด้านล่างนี้เป็นข้อมูลที่คุณจะสามารถใช้ได้ เนื่องจากคุณไม่ทราบว่าการจ่ายเงินแต่ละครั้งของผู้เล่นคนอื่นคืออะไรมันเป็นความท้าทายของคุณที่จะทำนายว่าพวกเขาจะลงคะแนนอย่างไรเมื่อได้รับผลการสำรวจความคิดเห็นในปัจจุบัน

  • ผลการเลือกตั้งบางส่วนจนถึงขณะนี้
  • จำนวนผู้เข้าร่วม (ไม่รวมตัวคุณเอง) ที่ยังไม่ได้ลงคะแนน
  • ผลตอบแทนส่วนบุคคลของคุณสำหรับผู้สมัครแต่ละคน
  • ผลตอบแทนกลุ่มรวมสำหรับผู้สมัครแต่ละคน

หลังจากผู้เล่นแต่ละคนได้รับโอกาสลงคะแนนเสียงผู้สมัครที่ได้คะแนนมากที่สุดจะชนะตามการลงคะแนนเสียงข้างมาก ผู้เล่นแต่ละคนจะได้รับจำนวนคะแนนที่สอดคล้องกับผลตอบแทนจากผู้สมัคร หากมีคะแนนเสียงเท่ากันจำนวนคะแนนที่ได้รับจะเป็นค่าเฉลี่ยของผู้สมัครที่ถูกผูกไว้

โครงสร้างการแข่งขัน

เมื่ออินสแตนซ์แรกผู้เข้าร่วมจะได้รับแจ้งจำนวนการเลือกตั้งที่จัดขึ้นในการแข่งขัน ฉันจะพยายามจัดการเลือกตั้งจำนวนมาก จากนั้นการเลือกตั้งแต่ละครั้งจะดำเนินการทีละคน

หลังจากผู้เข้าร่วมถูกสับแต่ละคนจะได้รับการลงคะแนน พวกเขาจะได้รับข้อมูลที่มี จำกัด ในรายการด้านบนและส่งคืนหมายเลขที่แสดงถึงการลงคะแนน หลังจากการเลือกตั้งสิ้นสุดลงบอทแต่ละครั้งจะได้รับผลการสำรวจครั้งสุดท้ายและคะแนนของพวกเขาเพิ่มขึ้นจากการเลือกตั้งครั้งนั้น

ผู้เข้าร่วมที่ชนะจะได้รับคะแนนรวมสูงสุดหลังจากมีการเลือกตั้งจำนวนมาก ผู้ควบคุมยังคำนวณคะแนน "ปกติ" สำหรับผู้แข่งขันแต่ละคนโดยเปรียบเทียบคะแนนของตนกับการแจกแจงคะแนนที่คาดการณ์ไว้สำหรับบอทลงคะแนนแบบสุ่ม

รายละเอียดการส่ง

การส่งจะอยู่ในรูปของคลาส Java 8 ผู้เข้าร่วมแต่ละคนจะต้องใช้อินเทอร์เฟซต่อไปนี้:

public interface Player
{
    public String getName();
    public int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs);
    public void receiveResults(int[] voteCounts, double result);
}
  • คอนสตรัคของคุณควรintเป็นพารามิเตอร์เดียวซึ่งจะแสดงจำนวนการเลือกตั้งที่จะมีขึ้น
  • getName()วิธีการส่งกลับชื่อที่จะใช้ในลีดเดอร์บอร์ด การทำเช่นนี้ช่วยให้คุณมีชื่อที่มีการจัดรูปแบบได้อย่างดีเยี่ยม
  • getVote(...)วิธีการส่งกลับ0, 1หรือ2ที่มีความหมายว่าผู้สมัครจะได้รับการโหวต
  • receiveResults(...)วิธีเป็นหลักในการช่วยให้การดำรงอยู่ของกลยุทธ์ที่ซับซ้อนมากขึ้นที่ใช้ข้อมูลทางประวัติศาสตร์
  • คุณได้รับอนุญาตให้สร้างวิธี / ตัวแปรอินสแตนซ์อื่น ๆ ที่คุณต้องการบันทึกและประมวลผลข้อมูลที่คุณมอบให้

รอบการแข่งขันขยาย

  1. ผู้เข้าแต่ละ instantiated new entrantName(int numElections)กับ
  2. สำหรับการเลือกตั้งแต่ละครั้ง:
    1. ผู้ควบคุมสุ่มกำหนดผลตอบแทนสำหรับผู้เล่นแต่ละคนสำหรับการเลือกตั้งครั้งนี้ รหัสนี้ได้รับด้านล่าง จากนั้นจะสลับผู้เล่นและให้พวกเขาเริ่มลงคะแนน
    2. วิธีการเข้าแข่งขันของpublic int getVote(int [] voteCounts, int votersRemaining, int [] payoffs, int[] totalPayoffs)ถูกเรียกและผู้เข้าแข่งขันส่งกลับการลงคะแนนเสียงของพวกเขา0, 1หรือ2ให้ผู้สมัครของทางเลือกของพวกเขา
    3. ผู้เข้าร่วมที่getVote(...)วิธีการไม่ส่งคืนการโหวตที่ถูกต้องจะได้รับการโหวตแบบสุ่ม
    4. หลังจากที่ทุกคนลงคะแนนแล้วผู้ควบคุมจะกำหนดผลการเลือกตั้งด้วยวิธีการส่วนใหญ่
    5. public void receiveResults(int[] voteCounts, double result)ผู้เข้าจะได้รับแจ้งของคะแนนเสียงขั้นสุดท้ายและผลตอบแทนของพวกเขาโดยเรียกวิธีการของพวกเขา
  3. หลังจากการเลือกตั้งทั้งหมดได้รับการจัดขึ้นผู้ชนะคือผู้ที่มีคะแนนสูงสุด

การกระจายแบบสุ่มของการจ่ายเงิน

การกระจายที่แน่นอนจะมีผลอย่างมากต่อการเล่นเกม ฉันเลือกการกระจายที่มีค่าเบี่ยงเบนมาตรฐานขนาดใหญ่ (ประมาณ 23.9235) และสามารถสร้างผลตอบแทนสูงและต่ำมากได้ ฉันตรวจสอบแล้วว่าการจ่ายผลตอบแทนสามครั้งแต่ละครั้งมีการแจกแจงที่เหมือนกัน

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

กฎเพิ่มเติม

ต่อไปนี้เป็นกฎทั่วไปที่เพิ่มเติม

  • โปรแกรมของคุณจะต้องไม่เรียกใช้ / แก้ไข / สร้างอินสแตนซ์ส่วนใด ๆ ของคอนโทรลเลอร์หรือผู้เข้าร่วมอื่น ๆ หรือความทรงจำของพวกเขา
  • เนื่องจากโปรแกรมของคุณยังคง "สด" ตลอดทัวร์นาเมนต์อย่าสร้างไฟล์ใด ๆ
  • อย่าโต้ตอบช่วยเหลือหรือกำหนดเป้าหมายโปรแกรมผู้เข้าร่วมอื่น ๆ
  • คุณอาจส่งผู้เข้าร่วมหลายคนตราบใดที่พวกเขาแตกต่างกันอย่างสมเหตุสมผลและตราบใดที่คุณปฏิบัติตามกฎข้างต้น
  • ฉันยังไม่ได้ระบุกำหนดเวลาที่แน่นอน แต่ฉันจะขอบคุณมาก runtimes ที่มีอย่างมีนัยสำคัญน้อยกว่าที่สองต่อการโทร ฉันต้องการที่จะจัดการเลือกตั้งให้ได้มากที่สุด

ผู้ควบคุม

ควบคุมสามารถพบได้ที่นี่ Tournament.javaโปรแกรมหลักคือ นอกจากนี้ยังมีสองบอทง่ายซึ่งจะแข่งขันบรรดาศักดิ์และRandomBot PersonalFavoriteBotฉันจะโพสต์บอททั้งสองนี้ในคำตอบ

ลีดเดอร์บอร์ด

ดูเหมือนว่า ExpectantBot จะเป็นผู้นำคนปัจจุบันตามด้วย Monte Carlo และ 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.

นี่คือทัวร์นาเมนต์ที่เก่ากว่า แต่ไม่มีบอตใดที่มีการเปลี่ยนแปลงในการทำงานตั้งแต่การรันเหล่านี้

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.

ฉันยังใช้การแข่งขัน 10 ม. สองเพื่อยืนยันการเป็นผู้นำของ 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.

oO ว้าวฉันทำไม่ดีเลย!
Ismael Miguel

ตามที่ฉันเห็นในโค้ดพารามิเตอร์ที่สองคือจำนวนคะแนนที่เหลือ และคนแรกคือการArrayนับประกอบด้วยคะแนนเสียงทั้งหมด ฉันถูกไหม?
Ismael Miguel

1
@IsmaelMiguel ใช่
PhiNotPi

1
ที่สอง. พวกเขาคือผลลัพธ์บางส่วนของการเลือกตั้งซึ่งเป็นคะแนนโหวตของคนที่อยู่ข้างหน้าคุณตามลำดับที่ถูกสับ
PhiNotPi

2
คุณอาจต้องการดูว่าเกิดอะไรขึ้นเมื่อคุณให้โคลนนิ่งของผู้มีสิทธิเลือกตั้ง โดยสรุปสั้น ๆ บางครั้งวินาที BestBot, NoThirdPartyBot และคนที่มองโลกในแง่ดีดูเหมือนจะได้รับประโยชน์จากกลุ่มการลงคะแนนที่มีขนาดใหญ่กว่า (เช่นพวกหัวรุนแรงบ็อตและในทางของตัวเอง CommunismBot แต่มันสำคัญน้อยกว่า)
Saidoro

คำตอบ:


10

NoThirdPartyBot

บอทนี้พยายามที่จะเดาว่าผู้สมัครคนใดจะเป็นอันดับสาม

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

บอทนี้ให้คะแนนความชื่นชอบของเขาที่ยังไม่ได้ถูกตัดออกทางคณิตศาสตร์

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
ฉันจะเดิมพัน Circumspect Bot ดีกว่าบอตโปรดส่วนตัวอย่างเคร่งครัด ดี
isaacg

10

ExpectantBot

บอทนี้จะคำนวณมูลค่าที่คาดหวังของตัวเลือกการลงคะแนนแต่ละตัวโดยสมมติว่าผู้ลงคะแนนทุกคนหลังจากนั้นจะทำการโหวตแบบสุ่ม

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) {   
    }

}

หากไม่มี metagaming หนักจากคู่ต่อสู้คนอื่นฉันจะแปลกใจถ้ามีอะไรชนะ
DoctorHeckle

@DoctorHeckle ฉันหวังเป็น StatBot แต่ฉันคิดว่าคุณพูดถูก
Winston Ewert

9

HipBot

HipBot ไม่สนใจเรื่องการจ่ายเงิน เงินเป็นเพียงยากล่อมประสาทที่เบี่ยงเบนความสนใจจากงานศิลปะที่แท้จริง

HipBot ต้องการลงคะแนนให้กับใครบางคนจริงไม่ใช่แค่หน้าม้าขององค์กร นอกจากนี้เขายังต้องการที่จะสวมเสื้อรณรงค์ของพวกเขาหลังจากพ่ายแพ้อย่างน่าอับอาย (สันนิษฐาน) ดังนั้นเขาจึงรู้สึกดีกว่าเมื่อผู้ชนะทำอะไรผิด

ดังนั้น HipBot ให้คะแนนบุคคลที่มีคะแนนต่ำสุดหรือหากมีการเสมอกันใครก็ตามที่ได้รับการจ่ายเงินที่ดีกว่า การกินแบบออร์แกนิกเท่านั้นไม่ฟรี

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 ยังไม่ผ่านการทดสอบดังนั้นให้ฉันรู้ว่ามีอะไรเกิดขึ้นบ้าง

แก้ไข: เพิ่มใน tiebreaking การแข่งขันมากขึ้นความคิดเห็นสาระสำคัญ


การทำงานสำหรับฉันแม้จะสงสารของเขาสำหรับการโยกไม่ได้ทำมากสำหรับคะแนนของเขา :)
euanjt

5
เขาชนะใจของเขาและสำหรับเขานั่นคือสิ่งที่สำคัญทั้งหมด: D
DoctorHeckle

8

PersonalFavoriteBot

บอทนี้เพียงลงคะแนนให้ผู้สมัครที่มีผลตอบแทนสูงที่สุดโดยไม่สนใจสิ่งอื่นใด หนึ่งในประเด็นหลักของความท้าทายนี้คือการแสดงให้เห็นว่านี่ไม่ใช่กลยุทธ์ที่ดีที่สุด

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

บอทนี้โหวตแบบสุ่ม โดยไม่คำนึงถึงจำนวนการเลือกตั้งที่ดำเนินการ (ตราบใดที่มันมีเหตุผลสูงเช่นมากกว่า 100) คะแนนปกติของผู้เข้าประกวดนี้จะผันผวนระหว่าง -2 และ 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

ลูกศิษย์

ผู้ติดตามต้องการให้พอดีกับมันคิดว่าวิธีที่ดีที่สุดในการทำสิ่งนั้นให้สำเร็จคือการลงคะแนนในแบบเดียวกับคนอื่น ๆ หรืออย่างน้อยก็ด้วยเสียงส่วนใหญ่ มันจะทำลายความผูกพันกับความชอบของตัวเองเพื่อแสดงความเป็นอิสระ แต่ไม่มากเกินไป

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) { }
}

หมายเหตุ: ฉันยังไม่ได้ทดสอบสิ่งนี้ดังนั้นแจ้งให้เราทราบหากมีข้อผิดพลาดใด ๆ


ดูเหมือนว่าจะทำงาน
PhiNotPi

4

Monte Carlo

นี่เป็นการจำลองการเลือกตั้งแบบสุ่มจำนวนมาก จากนั้นจะเลือกตัวเลือกที่เพิ่มผลกำไรสูงสุด

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 ตั้งอยู่บน ExpectantBot; อย่างไรก็ตามแทนที่จะสมมติว่าการลงคะแนนแต่ละครั้งนั้นมีความเป็นไปได้อย่างเท่าเทียมกันจะรวบรวมสถิติเกี่ยวกับวิธีการที่ผู้คนโหวตและใช้เพื่อประเมินความน่าจะเป็น

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

ผู้สมัครที่ทำงานได้ดีที่สุด

ฉบับดั้งเดิมของฉันฉบับปรับปรุงค่อนข้างหนัก อันนี้ยังกำจัดผู้สมัครใด ๆ ที่ไม่สามารถชนะได้ด้วยคะแนนเสียงที่เหลือจากการโยน แต่จากนั้นใช้กลยุทธ์ที่พยายามเพิ่มประสิทธิภาพผลตอบแทนสัมพัทธ์แทนที่จะปรับให้เหมาะสม การทดสอบครั้งแรกคือการใช้อัตราส่วนของผลตอบแทนส่วนบุคคลของฉันต่อผลตอบแทนโดยรวมสำหรับผู้สมัครแต่ละคนโดยมองหาค่าที่ดีที่สุดที่นั่น ฉันมองหาอัตราส่วนอื่น ๆ ที่ใกล้เคียงที่สุดและถ้ามีอัตราส่วนที่ให้ผลตอบแทนโดยรวมต่ำกว่าอัตราส่วนที่ดีที่สุดฉันเลือกอัตราส่วนนั้นแทน หวังว่านี่จะมีแนวโน้มที่จะกดดันการจ่ายเงินของผู้เล่นคนอื่น ๆ ในขณะที่รักษาระดับของฉันไว้สูงพอสมควร

ธ ปทนี้จะเกือบได้เป็นอย่างดีเช่นเดิมในการทดสอบของตัวเอง แต่ไม่มาก เราจะต้องดูว่ามันจะทำอย่างไรกับสนามเต็ม

 /**
  * 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
สิ่งนี้ไม่เหมือนกันCircumspectBotหรือ
TheNumberOne

ใช่มันกลายเป็นว่า; ฉันแสดงความคิดเห็นต่อผลกระทบนั้นในคำถามหลัก เมื่อฉันเริ่มเขียนโค้ดฉันไม่ได้ตระหนักว่ามันทำงานอย่างไร เนื่องจาก CircumspectBot ถูกเขียนขึ้นก่อนจึงควรได้รับเครดิตสำหรับแนวคิดนี้อย่างชัดเจน
Ralph Marshall

ฉันคิดว่าคุณขาดเรียนไปแล้ว
Winston Ewert

ขอบคุณ ฉันสูญเสียรั้งสุดท้าย ไม่มีรหัสอื่นใดหลังจากที่มีอยู่
Ralph Marshall

3

ผู้มองในแง่ดี

ผู้มองโลกในแง่ดีมองโลกในแง่ดีมากและคาดว่าครึ่งหนึ่งของผู้มีสิทธิเลือกตั้งที่เหลือจะลงคะแนนให้ผู้สมัครที่ให้ผลตอบแทนดีที่สุด

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

เป้าหมายของเขานั้นง่าย: การกำหนดแนวโน้มโดยรวมโดยใช้การจ่ายผลตอบแทนรวมและนับจำนวนครั้งที่ผู้ชนะต่ำ / กลาง / สูงกว่าจะได้รับ จากนั้นเขาจะลงคะแนนให้กับผู้ที่มีโอกาสชนะมากที่สุด

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

    }
}

แก้ไข:

การเปลี่ยนแปลงที่เกิดขึ้นในการตัดสินใจบางอย่างตอนนี้คำนึงถึงผลตอบแทนที่ดีที่สุดของเขาเอง ตอนนี้ควรจะสามารถลงคะแนนได้ดีขึ้นเมื่อการกระจายปัจจุบันทำให้เขาลงคะแนนให้ล่างของตัวเองเมื่อคนอื่น ๆ ที่ลงคะแนนให้กับการจ่ายเงินรางวัลที่สูงขึ้น


3

ไพรแอม

Priam เกลียดการสอบถามซ้ำ เขาประเมินความน่าจะเป็นของบอทที่เหลืออยู่โดยพิจารณาจากผลตอบแทนรวมแล้วคำนวณวิธีที่ดีที่สุดในการเพิ่มผลตอบแทนให้สูงสุด

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

    }
}

เร็วกว่า Odysseus มากเนื่องจากไม่มีการเรียกซ้ำ (ดำเนินการในเวลา O (n ^ 2)) และสามารถทำการเลือกตั้งหนึ่งล้านครั้งในเวลาประมาณ 15 วินาที


"ฉันคิดว่านี่เป็นบอตแรกที่ใช้พารามิเตอร์ผลตอบแทนรวมเพื่อผลประโยชน์ของตัวเอง :)" ดูที่บอทของฉัน (ABotDoNotForget) เขาใช้มันไปแล้วขอโทษ: D
Katenkyo

คล้ายกับบอทรุ่นล่าสุดของฉัน ExpectantBot ยกเว้นว่าคุณใช้ยอดรวมการจ่ายเงินเพื่อทำนายความน่าจะเป็น ฉันกระตือรือร้นที่จะดูว่ากลยุทธ์ใดทำงานได้ดีที่สุด
Winston Ewert

@ Winston ถึงฉันคิดว่าคุณทำคุณได้รับการทดสอบสามครั้งสุดท้ายที่ฉันทำ
euanjt

ฉันเพิ่งสังเกตเห็นความคล้ายคลึงกัน - ฉันพยายามทำรุ่น Odysseus ซึ่งใช้เวลาไม่ถึง 10 ชั่วโมงในการเลือกตั้ง 100 ครั้งดังนั้นฉันจึงใช้วงวน
euanjt

พูดตามตรงฉันได้แรงบันดาลใจให้ Odysseus เข้าใกล้
Winston Ewert

2

NoClueBot

NoClue ไม่รู้จัก Java หรือคณิตศาสตร์เป็นอย่างดีดังนั้นเขาจึงไม่รู้ว่าการถ่วงน้ำหนักแบบอัตราส่วนนี้จะช่วยให้เขาชนะได้หรือไม่ แต่เขาก็พยายาม

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) { }
}


SomeClueBot

SomeClueBot ได้รับการปลดประจำการแล้ว ใช้ตรรกะจริง ๆ ! เคยใช้ตรรกะซึ่งกลายเป็นว่าไม่มีประสิทธิภาพดังนั้นเขาจึงหันมาใส่ใจกับผลตอบแทนทั้งหมดไม่ใช่ของเขาเอง ใช้ตรรกะอีกครั้ง! แต่เขาไม่ทำดีกับผู้ติดตามและผู้มองโลกในแง่ดีเหล่านี้และแม้แต่คนที่ไม่สนใจ! :)


SometimesSecondBestBot

PersonalFavouriteBot พื้นฐานได้รับการปรับปรุง (ในทางทฤษฎี)

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
ดูเหมือนว่าคุณจะคำนวณตัวเลขที่มีน้ำหนักมากที่สุดสามน้ำหนักและใช้ค่า mod 3 นั้นเพื่อเลือกผู้สมัครที่ดีที่สุด ถูกต้องและถ้าเป็นเช่นนั้นจะไม่เป็นจำนวนสุ่ม? ฉันเข้าใจว่าคุณกำลังเรียก "คณิตศาสตร์ยากสำหรับบาร์บี้" ดังนั้นฉันไม่แน่ใจว่าฉันมีแนวคิด
Ralph Marshall

@RalphMarshall ใช่มันเป็นแบบสุ่ม อย่างไรก็ตามฉันไม่ได้ตั้งใจทำแบบนั้นเลยไม่สนใจเลยฮ่าฮ่า แก้ไขทันที
Kade

@PhiNotPhi ฉันคิดว่าฉันคงแก้ไขแล้ว และใช่ฉันไม่แปลกใจ
Kade

เทพเจ้าของฉันนี้ไม่ดี .. ในงานการป้องกันประเทศของฉันคือการระบายน้ำจิตใจอย่างมากในวันนี้
Kade

2

พวกหัวรุนแรง

ลงคะแนนให้ผู้สมัครที่มีผลตอบแทนต่ำที่สุดเสมอ

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

SmashAttemptByEquality

เป้าหมายคือการทำให้เท่าเทียมกันกับผู้สมัครทั้งหมดจากนั้นชน! บอทอื่น ๆ ทั้งหมดในรอบสุดท้าย
นี่เป็นอัลกอริธึมการทำลายล้างที่พยายามบั๊กคนอื่น ๆ ทั้งหมดเพื่ออ้างสิทธิ์ในการชนะ

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) { }
}

สังเกตว่านี่ยังไม่ได้ทดสอบ !


2

บอทขั้นพื้นฐาน

บอทขั้นพื้นฐานเพียงลงคะแนนให้กับผู้สมัครที่ไม่ได้ถูกกำจัดออกไปและมีการจ่ายผลตอบแทนสูงสุดมากที่สุดจากผู้สมัครเหล่านั้น

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

เคลลี่ชื่นชอบ

ฉันเริ่มต้นด้วย CircumspectBot แต่เหลือไม่มาก ทำการเดาที่น่าเบื่อในการแจกแจงความน่าจะเป็นของการลงคะแนนที่เหลืออยู่จากนั้นจึงเลือกตัวเลือกที่จะเพิ่มอรรถประโยชน์การบันทึกของตนเองให้สูงสุด (Kelly Criterion) ไม่ใช่ที่เร็วที่สุด แต่อยู่ในสวนลูกบอลของคนอื่น นอกจากนี้มันค่อนข้างมีการแข่งขันกับภาคสนาม (อย่างที่มันเป็นเมื่อฉันเริ่มทำงานในเรื่องนี้และดาวน์โหลดบอทอื่น ๆ )

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

    }

}

มีให้บริการที่https://gist.github.com/jkominek/dae0b3158dcd253e09e5ในกรณีที่ง่ายกว่า


2

CommunismBot

CommunismBot คิดว่าเราทุกคนควรเข้ากันและเลือกผู้สมัครที่ดีที่สุดสำหรับทุกคน

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 เลือกผู้สมัครที่ดีที่สุดเสมอ นอกเสียจากว่าพวกเขาจะสกปรก - ปาร์ตี้ - เหม็น

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 โหวตให้กับผู้สมัครที่ดีที่สุดหากว่าพวกเขาอยู่ในค่าเบี่ยงเบนมาตรฐานของผู้สมัครที่ดีที่สุดคนต่อไปเนื่องจากมีจำนวนผู้มีสิทธิ์ลงคะแนนเหลืออยู่

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

พยายามที่จะทำนายว่าบอตอื่น ๆ ทั้งหมดจะลงคะแนนอย่างไรโดยการคำนวณการจ่ายเฉลี่ยโดยเฉลี่ยสำหรับผู้อื่น คะแนนเริ่มต้นสำหรับการจ่ายผลตอบแทนที่ดีที่สุด แต่จะลงคะแนนให้คะแนนที่สองที่ดีที่สุดหากมีคะแนนเสียงที่คาดหวังมากกว่าที่ดีที่สุดการจ่ายเงินเฉลี่ยที่ดีกว่าสำหรับฉันและการจ่ายเงินที่แย่ที่สุดมีโอกาสชนะสิ่งนี้

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

แค่ปราชญ์เหงากำลังมองหา "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

แพ้ชนะ

หากคุณชนะฉันแพ้! ง่าย ๆ บอทนี้โหวตให้คนที่เขาชอบและคนอื่น ๆ ก็ไม่ชอบ

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

    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.