Cái thiện đấu với cái ác


112

Kết quả - ngày 19 tháng 7 năm 2014

King of the Hill hiện tại là Mercenary bởi người dùng Fabigler ! Tiếp tục gửi bài dự thi và đánh bật ngai vàng của anh ấy!

Nhấn vào đây để xem Bảng điểm.

Các chương trình được gửi vào hoặc trước ngày 19 tháng 7 năm 2014 đã được bao gồm. Tất cả các đệ trình khác sẽ được bao gồm trong các thử nghiệm trong tương lai. Kết quả mới sẽ được đăng vào khoảng ngày 9 tháng 8, vì vậy sẽ mang lại cho bạn nhiều thời gian.


Minh họa được vẽ bởi anh trai Minh họa bởi Chris Rainbolt, anh trai tôi và một sinh viên mới tốt nghiệp từ trường Cao đẳng Nghệ thuật và Thiết kế Savannah

Giới thiệu

Các thiên thần và ác quỷ đang chiến đấu và, như thường lệ, sử dụng trái đất làm chiến trường của họ. Con người bị mắc kẹt ở giữa và bị buộc phải đứng về phía. Một lực lượng trung lập không xác định thưởng cho những người luôn chiến đấu cho phe thua cuộc.

Tro choi

Mỗi thử nghiệm, bạn sẽ được ghép giả ngẫu nhiên và sau đó được xáo trộn với từ 20 đến 30 bài nộp khác. Mỗi thử nghiệm sẽ bao gồm 1000 vòng. Mỗi vòng, bạn sẽ được thông qua một đầu vào và dự kiến ​​sẽ tạo ra đầu ra. Đầu ra của bạn sẽ được ghi lại và ghi điểm. Quá trình này sẽ được lặp lại 1000 lần.

Đầu vào

Bạn sẽ nhận được một đối số duy nhất thể hiện số phiếu trong quá khứ của mỗi người chơi. Các vòng được phân định bằng dấu phẩy. A 0đại diện cho một người chơi đứng về phía Ác ma đó. A 1đại diện cho một người chơi đứng về phía Tốt. Trong một thử nghiệm, người chơi sẽ luôn theo thứ tự. Phiếu bầu của riêng bạn sẽ được bao gồm, nhưng không được xác định rõ ràng. Ví dụ:

101.100.100

Trong ví dụ này, ba vòng đã được hoàn thành và ba người chơi đang thi đấu. Người chơi luôn luôn đứng về phía Tốt. Người chơi hai luôn sát cánh với Evil. Người chơi ba đổi từ Tốt ở vòng 1 sang Ác ở vòng 2 và 3. Một trong những người chơi đó là bạn.

Đầu ra

Đệ trình Java

  • Trả về chuỗi goodnếu bạn muốn bên cạnh Tốt.
  • Trả lại chuỗi evilnếu bạn muốn phụ với Evil.

Đệ trình không phải Java

  • Xuất chuỗi goodthành thiết bị xuất chuẩn nếu bạn muốn phụ với Tốt.
  • Đầu ra chuỗi evilstdout nếu bạn muốn sang bên kia với Ác.

Nếu chương trình của bạn xuất hoặc trả lại bất cứ thứ gì khác, ném ngoại lệ, không biên dịch hoặc mất nhiều hơn một giây để xuất bất cứ thứ gì trên máy chính xác này , thì nó sẽ bị loại.

Chấm điểm

Điểm số sẽ được đăng trong bảng tính tài liệu của Google để dễ dàng xem ngay khi tôi có thể biên dịch tất cả các mục hiện tại. Đừng lo lắng - Tôi sẽ tiếp tục chạy thử miễn là các bạn tiếp tục gửi chương trình!

  • Bạn nhận được 3 điểm cho siding với đa số trong một vòng.
  • Bạn nhận được n - 1 điểm khi đứng về phía thiểu số trong một vòng, trong đó n là số lần liên tiếp bạn đứng về phía thiểu số.

Điểm của bạn sẽ là trung bình của 5 thử nghiệm. Mỗi thử nghiệm bao gồm 1000 vòng.

Sản phẩm bàn giao

Đệ trình không phải Java

Bạn phải gửi một tiêu đề duy nhất, một chương trình và chuỗi dòng lệnh Windows sẽ chạy chương trình của bạn. Hãy nhớ rằng một đối số có thể được thêm vào chuỗi đó. Ví dụ:

  • python Angel.py
    • Lưu ý rằng cái này không có đối số. Đây là vòng một! Hãy chuẩn bị cho việc này.
  • python Angel.py 11011,00101,11101,11111,00001,11001,11001

Đệ trình Java

Bạn phải gửi một tiêu đề duy nhất và một lớp Java mở rộng lớp Con người trừu tượng được viết dưới đây.

public abstract class Human {
    public abstract String takeSides(String history) throws Exception;
}

Kiểm tra

Nếu bạn muốn kiểm tra trình của riêng bạn, hãy làm theo các hướng dẫn ở đây .

Ghi chú bổ sung

Bạn có thể gửi nhiều bài nộp khác nhau như bạn muốn. Những bài nộp có vẻ thông đồng sẽ bị loại. Tác giả của thử thách này sẽ là thẩm phán duy nhất về vấn đề đó.

Một phiên bản mới của chương trình hoặc lớp Java của bạn sẽ được tạo mỗi khi nó được gọi. Bạn có thể lưu thông tin bằng cách viết vào một tập tin. Bạn không thể sửa đổi cấu trúc hoặc hành vi của bất cứ điều gì ngoại trừ lớp của riêng bạn.

Người chơi sẽ được xáo trộn trước khi bắt đầu thử nghiệm. Quỷ và Thiên thần sẽ tham gia vào mọi thử nghiệm. Nếu số lượng người chơi là chẵn, Petyr Baelish cũng sẽ tham gia. Ác quỷ chiến đấu vì Ác ma, Thiên thần tốt lành và Petyr Baelish chọn phe giả danh.


2
Bình luận bị thanh trừng, vì chúng đã lỗi thời và theo yêu cầu của OP. Vui lòng thông báo cho tôi về bất kỳ ý kiến ​​cần phải được xóa.
Doorknob

7
Woah, OP thay đổi tên người dùng của mình. Ok, vậy khi nào kết quả sẽ được hiển thị?
justhalf

6
@Rainbolt Đây phải là một công việc quái dị, chạy thử thách này! Lý do cho sự chú ý này là sự đơn giản của giao thức và các quy tắc, làm cho nó có thể truy cập được trong khi cũng cho phép các mục đơn giản, hoạt động . TL; DR: Thử thách của bạn quá hay! : D
tomsmeding

3
@dgel Tôi sẽ đăng dữ liệu thô, trên, dưới, trung bình và có thể là biểu đồ đường để chúng tôi có thể biết ai đã làm tốt hơn khi cuộc thi kéo dài.
Rainbolt

6
Một trong những nhóm kết thúc với 10 mục được bình chọn theo cùng một cách mỗi lần. Do đó, hai người dùng đã kết thúc với số điểm hoàn hảo hoặc "một vòng ngắn hoàn hảo" khoảng 450.000. Các mục tương tự ghi được khoảng 1900 trong các thử nghiệm khác. Điểm trung bình gần với năm 2000. Vì sự mất cân bằng cực độ trong kết quả, tôi quyết định rằng một con số có ý nghĩa hơn sẽ là trung bình. Tôi đã chỉnh sửa thử thách để sau 5 thử nghiệm, người chiến thắng sẽ là người nộp bài với điểm trung bình cao nhất. Nếu bất cứ ai nghĩ rằng chuyển từ trung bình sang trung bình là không công bằng hoặc nếu không thì là một lựa chọn kém, xin vui lòng bình luận.
Rainbolt

Câu trả lời:


11

Lính đánh thuê

Luôn luôn bên cạnh người trả nhiều tiền nhất vòng trước.

Có tính đến việc những người tốt kiếm được nhiều hơn theo thống kê.

package Humans;
public class Mercenary extends Human {
    public String takeSides(String history) {
        // first round random!
        if (history.length() == 0) {
            return Math.random() >= 0.5 ? "good" : "evil";
        }

        String[] rounds = history.split(",");
        String lastRound = rounds[rounds.length - 1];

        double goodMoneyPaid = 0;
        double evilMoneyPaid = 0;
        for (char c : lastRound.toCharArray()) {
                switch (c) {
                case '0':
                    goodMoneyPaid = goodMoneyPaid + 0.2; //statistically proven: good people have more reliable incomes
                    break;
                case '1':
                    evilMoneyPaid++; 
                    break;
                default:
                    break;
                }
        }

        if (goodMoneyPaid > evilMoneyPaid)
        {
            return "good";
        } else {
            return "evil";
        }
    }
}

2
Đây là bài viết thứ hai để nói điều gì đó về tiền. Tôi đang thiếu một tài liệu tham khảo hay cái gì đó?
Rainbolt

Đúng, nhưng anh chàng này là một tên khốn thậm chí còn xấu xa hơn. Bỏ rơi bạn bè của mình mỗi lượt, chỉ vì tiền.
fabigler

Câu lệnh chuyển đổi của bạn bị thiếu một câu lệnh return cho trường hợp mặc định, khiến nó không được biên dịch. Tôi đã thêm một cái ngẫu nhiên.
Rainbolt

4
Xin chúc mừng, Vua của Đồi! Tôi không hiểu làm thế nào mục này chiến thắng. Muốn thêm một lời giải thích, bây giờ nó có 300 tiền thưởng danh tiếng kèm theo nó?
Rainbolt

4
Có thể là một lỗi, hoặc tôi đã hiểu nhầm các bình luận và mô tả, nhưng Mercenary không thực sự làm những gì nó có nghĩa là làm. Ngoại trừ vòng ngẫu nhiên đầu tiên, anh ta sẽ luôn sát cánh với cái ác trừ khi chưa đến 1/6 số người bỏ phiếu cho cái ác ở vòng trước.
jaybz

39

Hipster, Ruby

if ARGV.length == 0
    puts ["good", "evil"].sample
else
    last_round = ARGV[0].split(',').last
    n_players = last_round.length
    puts last_round.count('1') > n_players/2 ? "evil" : "good"
end

Đơn giản chỉ cần đi với thiểu số của vòng cuối cùng, chỉ vì mọi thứ khác là chủ đạo.

Chạy như

ruby hipster.rb

30

Petyr Baelish

Bạn không bao giờ biết Petyr Baelish đứng về phía ai.

package Humans;

/**
 * Always keep your foes confused. If they are never certain who you are or 
 * what you want, they cannot know what you are likely to do next.
 * @author Rusher
 */
public class PetyrBaelish extends Human {

    /**
     * Randomly take the side of good or evil.
     * @param history The past votes of every player
     * @return A String "good" or "evil
     */
    public String takeSides(String history) {
        return Math.random() < 0.5 ? "good" : "evil";
    }
}

Mục này sẽ chỉ được bao gồm nếu số lượng người chơi là chẵn. Điều này đảm bảo rằng sẽ luôn có đa số.


28
Về phía Petyr Baelish, rõ ràng.
Cthulhu

2
@Kevin Nó liên tục đánh bại hầu hết các bot. Nó thường đạt 27ish.
cjfaure

3
@Kevin Mục này đã được gửi bởi tác giả của thử thách. Nó không có nghĩa là làm tốt. Nó tồn tại để đảm bảo rằng sẽ luôn có đa số, bởi vì với số lượng người chơi chẵn, có thể có một sự ràng buộc.
Rainbolt

4
Tại sao trời ơi tại sao cái này lại được nhiều phiếu nhất? Thật không công bằng .
tomsmeding

3
@tomsmeding Không. Đó là một trích dẫn từ Game of Thrones lol.
Rainbolt

29

C ++, Nhà khoa học Meta

Cái này về cơ bản giống như Nhà khoa học, nhưng không hoạt động trên các vòng như toàn bộ mà trên từng người chơi. Nó cố gắng ánh xạ một sóng (hoặc một hàm không đổi) cho từng người chơi và dự đoán di chuyển của họ trong vòng tiếp theo. Từ dự đoán vòng kết quả, Nhà khoa học Meta chọn bất kỳ bên nào có vẻ như chiếm đa số.

#include <iostream>
#include <utility>
#include <cstdlib>
#include <cstring>
#if 0
#define DBG(st) {st}
#else
#define DBG(st)
#endif

#define WINDOW (200)

using namespace std;

int main(int argc,char **argv){
    if(argc==1){
        cout<<(rand()%2?"good":"evil")<<endl;
        return 0;
    }
    DBG(cerr<<"WINDOW="<<WINDOW<<endl;)
    int nump,numr;
    nump=strchr(argv[1],',')-argv[1];
    numr=(strlen(argv[1])+1)/(nump+1);
    int period,r,p;
    int score,*scores=new int[WINDOW];
    int max; //some score will always get above 0, because if some score<0, the inverted wave will be >0.
    int phase,phasemax;
    int predicted=0; //The predicted number of goods for the next round
    int fromround=numr-WINDOW;
    if(fromround<0)fromround=0;
    pair<int,int> maxat; //period, phase
    DBG(cerr<<"Players:"<<endl;)
    for(p=0;p<nump;p++){
        DBG(cerr<<" p"<<p<<": ";)
        for(r=fromround;r<numr;r++)if(argv[1][r*(nump+1)+p]!=argv[1][p])break;
        if(r==numr){
            DBG(cerr<<"All equal! prediction="<<argv[1][p]<<endl;)
            predicted+=argv[1][(numr-1)*(nump+1)+p]-'0';
            continue;
        }
        max=0;
        maxat={-1,-1};
        for(period=1;period<=WINDOW;period++){
            scores[period-1]=0;
            phasemax=-1;
            for(phase=0;phase<2*period;phase++){
                score=0;
                for(r=fromround;r<numr;r++){
                    if(argv[1][r*(nump+1)+p]-'0'==1-(r+phase)%(2*period)/period)score++;
                    else score--;
                }
                if(score>scores[period-1]){
                    scores[period-1]=score;
                    phasemax=phase;
                }
            }
            if(scores[period-1]>max){
                max=scores[period-1];
                maxat.first=period;
                maxat.second=phasemax;
            }
            DBG(cerr<<scores[period-1]<<" ";)
        }
        DBG(cerr<<"(max="<<max<<" at {"<<maxat.first<<","<<maxat.second<<"})"<<endl;)
        DBG(cerr<<"     prediction: 1-("<<numr<<"+"<<maxat.second<<")%(2*"<<maxat.first<<")/"<<maxat.first<<"="<<(1-(numr+maxat.second)%(2*maxat.first)/maxat.first)<<endl;)
        predicted+=(1-(numr+maxat.second)%(2*maxat.first)/maxat.first);
    }
    DBG(cerr<<"Predicted outcome: "<<predicted<<" good + "<<(nump-predicted)<<" evil"<<endl;)
    if(predicted>nump/2)cout<<"evil"<<endl; //pick minority
    else cout<<"good"<<endl;
    delete[] scores;
    return 0;
}

Nếu bạn muốn bật các câu lệnh gỡ lỗi, hãy thay đổi dòng đọc #if 0thành #if 1.

Biên dịch với g++ -O3 -std=c++0x -o MetaScientist MetaScientist.cpp(bạn không cần cảnh báo, vì vậy không -Wall) và chạy với MetaScientist.exe(có thể bao gồm cả đối số của khóa học). Nếu bạn hỏi thực sự độc đáo tôi có thể cung cấp cho bạn một tệp thực thi Windows.

EDIT: Rõ ràng, phiên bản trước đã hết thời gian khoảng 600 vòng vào trò chơi. Điều này không nên làm điều đó. Tiêu thụ thời gian của nó được kiểm soát bởi #define WINDOW (...)dòng, nhiều hơn là chậm hơn nhưng nhìn xa hơn.


2
Tôi khiêm tốn đề nghị bạn thử chọn bên thua cuộc. Nếu bạn luôn có thể đoán chính xác, bạn sẽ nhận được nhiều hơn 3 điểm mỗi vòng.
Kevin

1
@Kevin Điều đó đúng, nhưng tôi đoán rằng nó có thể đoán được mặt sai khá nhanh, và bạn cần đoán chính xác mặt thua hơn bảy lần liên tiếp để cải thiện luôn luôn chiếm đa số. Tôi có thể thay đổi nó mặc dù.
tomsmeding

1
@Kevin Ngoài ra, trước tiên tôi muốn xem những người này làm như thế nào (Nhà khoa học và Nhà khoa học Meta) khi Rizer đưa chúng tôi một bảng điểm vào cuối tuần này, như anh ấy đã nêu trong các nhận xét cho OP. Xin lỗi, xin lỗi, nhưng tôi quá lười để tự biên dịch tất cả mọi thứ ... :)
tomsmeding

3
Đừng lo lắng! Có lẽ không an toàn để chạy những cái này. Chỉ cần để tôi làm hỏng máy của tôi với mã được viết bởi 50 người lạ trên Internet.
Rainbolt

1
@Kevin Nhưng đó là NHIỀU ! Tôi có thể, thực sự, nhưng tôi không thích nó. Tôi sẽ xem giá vé như thế nào.
tomsmeding

26

Thiên thần

Người chơi thuần túy nhất trong tất cả.

Chương trình

print "good"

Chỉ huy

python Angel.py

22
Python là một ngôn ngữ tốt. Có vẻ như chỉ có tự nhiên rằng Thiên thần nên sử dụng nó.
jpmc26

23
Tôi có thể nhắc nhở mọi người rằng Python là Rắn. Một con rắn.
Ông Lister

3
@MrLister Tôi có thể nhắc nhở bạn rằng Lucifer là một Thiên thần vĩ đại trước khi Chúa đuổi anh ta ra khỏi thiên đường?
Zibbobz

1
@Zibbobz Vâng ... thật xấu hổ, rằng họ đã rơi ra. Họ có thể đã đạt được rất nhiều cùng nhau.
Ông Lister

24

Gà chọi

package Humans;

public class ArtemisFowl extends Human {
    public final String takeSides(String history) {
        int good = 0, evil = 0;
        for(int i = 0; i < history.length(); i++)   {
            switch(history.charAt(i))   {
                case '0': evil++; break;
                case '1': good++; break;
            }
        }
        if(good % 5 == 0){
           return "good";
        } else if (evil % 5 == 0){
           return "evil";
        } else {
           if(good > evil){
              return "good";
           } else if(evil > good){
              return "evil";
           } else {
              return Math.random() >= 0.5 ? "good" : "evil";
           }
        }
    }
}

Trong quyển 7, Khu phức hợp Atlantis , Artemis Fowl mắc phải một căn bệnh tâm lý (gọi là phức hợp Atlantis) buộc anh phải làm mọi thứ trong bội số của 5 (nói, hành động, v.v.). Khi anh không thể làm điều đó trong bội số của 5, anh đã hoảng loạn. Về cơ bản, tôi làm điều đó: xem tốt hay xấu (thiên vị cố ý) chia hết cho 5, nếu không, thì tôi hoảng loạn và xem cái nào lớn hơn & chạy với điều đó hoặc hoảng sợ hơn nữa và chọn ngẫu nhiên.


4
Khi tôi đọc Artemis Fowl ở Junior High, chỉ có hai cuốn sách tồn tại. Thật vui khi thấy bây giờ đã có bảy, và Disney đang biến nó thành một bộ phim.
Rainbolt

1
Thực tế có 8 cuốn sách.
Kyle Kanos

7
Càng nhiều càng tốt (trừ khi bạn đang đọc The Wheel of Time)
Rainbolt

1
Và bạn đã quên break;trong của bạn switch.
johnchen902

1
@ johnchen902, @ Manu: Tôi không có nhiều kinh nghiệm về java (Tôi sử dụng Fortran90 + và chỉ thấy java ở đây), do đó lỗi của tôi. Tôi sẽ sửa chúng khi tôi vào văn phòng sau một tiếng nữa.
Kyle Kanos

19

Khác biệt

Những con số kỳ lạ thật đáng sợ.

package Humans;

public class Disparnumerophobic extends Human {
    public final String takeSides(String history) {
        int good = 0, evil = 0;
        for(int i = 0; i < history.length(); i++)   {
            switch(history.charAt(i))   {
                case '0': evil++; break;
                case '1': good++;
            }
        }
        if(good%2 == 1 && evil%2 == 0)  return "evil";
        if(evil%2 == 1 && good%2 == 0)  return "good";
        // well shit.... 
        return Math.random() >= 0.5 ? "good" : "evil";
    }
}

17
Nhận xét làm tôi cười / khịt mũi.
phyrfox

17

Linus, Ruby

Tìm cách gây bối rối cho các nhà phân tích bằng cách luôn phá vỡ mô hình .

num_rounds = ARGV[0].to_s.count(',')
LINUS_SEQ = 0xcb13b2d3734ecb4dc8cb134b232c4d3b2dcd3b2d3734ec4d2c8cb134b234dcd3b2d3734ec4d2c8cb134b23734ecb4dcd3b2c4d232c4d2c8cb13b2d3734ecb4dcb232c4d2c8cb13b2d3734ecb4dc8cb134b232c4d3b2dcd3b2d3734ec4d2c8cb134b234dcd3b2d3734ec4d2c8cb134b23734ecb4dcd3b2c4d2c8cb134b2
puts %w[good evil][LINUS_SEQ[num_rounds]]

Lưu dưới dạng linus.rbvà chạy vớiruby linus.rb


16

BackPacker

Xác định một người chơi đã chọn thiểu số phù hợp nhất và chọn phiếu bầu cuối cùng của mình.

package Humans;

public class BackPacker extends Human {
    // toggles weather the BackPacker thinks majority is better vs. minority is better
    private static final boolean goWithMajority = false;

    @Override
    public final String takeSides(String history)  {
        if (history == null || history.equals(""))
            return "evil";
        String[] roundVotes = history.split(",");
        int players = roundVotes[0].length();
        int[] winningPlayers = new int[players];
        for (String nextRound : roundVotes) {
            boolean didGoodWin = didGoodWin(nextRound, players);
            for (int player = 0; player < nextRound.length(); player++) {
                boolean playerVotedGood = nextRound.charAt(player) == '1';
                winningPlayers[player] += didPlayerWin(didGoodWin, playerVotedGood);
            }
        }
        int bestScore = -1;
        for (int nextPlayer : winningPlayers)
            if (bestScore < nextPlayer)
                bestScore = nextPlayer;
        int bestPlayer = 0;
        for (int ii = 0; ii < players; ii++) {
            if (winningPlayers[ii] == bestScore) {
                bestPlayer = ii;
                break;
            }
        }
        if (roundVotes[roundVotes.length - 1].charAt(bestPlayer) == '1')
            return "good";
        return "evil";
    }

    private int didPlayerWin(boolean didGoodWin, boolean playerVotedGood) {
        if(goWithMajority) {
            return ((didGoodWin && playerVotedGood) || (!didGoodWin && !playerVotedGood)) ? 1 : 0;
        } else {
            return ((!didGoodWin && playerVotedGood) || (didGoodWin && !playerVotedGood)) ? 1 : 0;
        }
    }

    private boolean didGoodWin(String round, int players) {
        int good = 0;
        for (char next : round.toCharArray())
            good += next == '1' ? 1 : 0;
        return (good * 2) > players;
    }
}

The CrowdFollower

Xác định một người chơi đã chọn đa số phù hợp nhất và chọn phiếu bầu cuối cùng của mình.

package Humans;

public class CrowdFollower extends Human {
    // toggles weather the FrontPacker thinks majority is better vs. minority is better
    private static final boolean goWithMajority = true;

    @Override
    public final String takeSides(String history)  {
        if (history == null || history.equals(""))
            return "evil";
        String[] roundVotes = history.split(",");
        int players = roundVotes[0].length();
        int[] winningPlayers = new int[players];
        for (String nextRound : roundVotes) {
            boolean didGoodWin = didGoodWin(nextRound, players);
            for (int player = 0; player < nextRound.length(); player++) {
                boolean playerVotedGood = nextRound.charAt(player) == '1';
                winningPlayers[player] += didPlayerWin(didGoodWin, playerVotedGood);
            }
        }
        int bestScore = -1;
        for (int nextPlayer : winningPlayers)
            if (bestScore < nextPlayer)
                bestScore = nextPlayer;
        int bestPlayer = 0;
        for (int ii = 0; ii < players; ii++) {
            if (winningPlayers[ii] == bestScore) {
                bestPlayer = ii;
                break;
            }
        }
        if (roundVotes[roundVotes.length - 1].charAt(bestPlayer) == '1')
            return "good";
        return "evil";
    }

    private int didPlayerWin(boolean didGoodWin, boolean playerVotedGood) {
        if(goWithMajority) {
            return ((didGoodWin && playerVotedGood) || (!didGoodWin && !playerVotedGood)) ? 1 : 0;
        } else playerVotedGood                return ((!didGoodWin && good) || (didGoodWin && !playerVotedGood)) ? 1 : 0;
        }
    }

    private boolean didGoodWin(String round, int players) {
        int good = 0;
        for (char next : round.toCharArray())
            good += next == '1' ? 1 : 0;
        return (good * 2) > players;
    }
}

Chương trình rất sạch sẽ!
Rainbolt

Rất tiếc, tôi nghĩ rằng tôi có thể đã sao chép chương trình của bạn bằng một ngôn ngữ khác.
PyRulez

@Rizer Tôi đã cập nhật mã và muốn thêm mã này dưới dạng hai mục nhập, một mục nhập goWithMajority = truevà một mục nhập false. Điều đó có ổn không, hay tôi cần thêm BackPacker thứ hai cho việc này?
Fuchs Angelo

@AngeloNeuschitzer Tôi đã chỉnh sửa bài đăng này. Bằng cách này, tôi sẽ không quên thêm cả hai bài nộp. Tôi đề nghị bạn thay đổi tên thực sự không sáng tạo mà tôi đã đặt cho nó và có thể thêm một mô tả cho cả hai nếu bạn muốn.
Rainbolt

1
@Rainbolt Tôi thực sự thích FrontPacker của bạn hơn. Lol'd.
tomsmeding

15

Thầy bói

Đây vẫn là công việc đang tiến triển. Tôi chưa thử nó. Tôi chỉ muốn xem liệu OP có nghĩ rằng nó vi phạm quy tắc hay không.

Ý tưởng là mô phỏng vòng tiếp theo bằng cách thực hiện tất cả những người tham gia khác một vài lần để có xác suất về kết quả và hành động tương ứng.

package Humans;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import sun.net.www.protocol.file.FileURLConnection;

public class FortuneTeller extends Human {

/**
 * Code from http://stackoverflow.com/a/22462785 Private helper method
 *
 * @param directory The directory to start with
 * @param pckgname The package name to search for. Will be needed for
 * getting the Class object.
 * @param classes if a file isn't loaded but still is in the directory
 * @throws ClassNotFoundException
 */
private static void checkDirectory(File directory, String pckgname,
        ArrayList<Class<?>> classes) throws ClassNotFoundException {
    File tmpDirectory;

    if (directory.exists() && directory.isDirectory()) {
        final String[] files = directory.list();

        for (final String file : files) {
            if (file.endsWith(".class")) {
                try {
                    classes.add(Class.forName(pckgname + '.'
                            + file.substring(0, file.length() - 6)));
                } catch (final NoClassDefFoundError e) {
                // do nothing. this class hasn't been found by the
                    // loader, and we don't care.
                }
            } else if ((tmpDirectory = new File(directory, file))
                    .isDirectory()) {
                checkDirectory(tmpDirectory, pckgname + "." + file, classes);
            }
        }
    }
}

/**
 * Private helper method.
 *
 * @param connection the connection to the jar
 * @param pckgname the package name to search for
 * @param classes the current ArrayList of all classes. This method will
 * simply add new classes.
 * @throws ClassNotFoundException if a file isn't loaded but still is in the
 * jar file
 * @throws IOException if it can't correctly read from the jar file.
 */
private static void checkJarFile(JarURLConnection connection,
        String pckgname, ArrayList<Class<?>> classes)
        throws ClassNotFoundException, IOException {
    final JarFile jarFile = connection.getJarFile();
    final Enumeration<JarEntry> entries = jarFile.entries();
    String name;

    for (JarEntry jarEntry = null; entries.hasMoreElements()
            && ((jarEntry = entries.nextElement()) != null);) {
        name = jarEntry.getName();

        if (name.contains(".class")) {
            name = name.substring(0, name.length() - 6).replace('/', '.');

            if (name.contains(pckgname)) {
                classes.add(Class.forName(name));
            }
        }
    }
}

/**
 * Attempts to list all the classes in the specified package as determined
 * by the context class loader
 *
 * @param pckgname the package name to search
 * @return a list of classes that exist within that package
 * @throws ClassNotFoundException if something went wrong
 */
private static ArrayList<Class<?>> getClassesForPackage(String pckgname)
        throws ClassNotFoundException {
    final ArrayList<Class<?>> classes = new ArrayList<Class<?>>();

    try {
        final ClassLoader cld = Thread.currentThread()
                .getContextClassLoader();

        if (cld == null) {
            throw new ClassNotFoundException("Can't get class loader.");
        }

        final Enumeration<URL> resources = cld.getResources(pckgname
                .replace('.', '/'));
        URLConnection connection;

        for (URL url = null; resources.hasMoreElements()
                && ((url = resources.nextElement()) != null);) {
            try {
                connection = url.openConnection();

                if (connection instanceof JarURLConnection) {
                    checkJarFile((JarURLConnection) connection, pckgname,
                            classes);
                } else if (connection instanceof FileURLConnection) {
                    try {
                        checkDirectory(
                                new File(URLDecoder.decode(url.getPath(),
                                                "UTF-8")), pckgname, classes);
                    } catch (final UnsupportedEncodingException ex) {
                        throw new ClassNotFoundException(
                                pckgname
                                + " does not appear to be a valid package (Unsupported encoding)",
                                ex);
                    }
                } else {
                    throw new ClassNotFoundException(pckgname + " ("
                            + url.getPath()
                            + ") does not appear to be a valid package");
                }
            } catch (final IOException ioex) {
                throw new ClassNotFoundException(
                        "IOException was thrown when trying to get all resources for "
                        + pckgname, ioex);
            }
        }
    } catch (final NullPointerException ex) {
        throw new ClassNotFoundException(
                pckgname
                + " does not appear to be a valid package (Null pointer exception)",
                ex);
    } catch (final IOException ioex) {
        throw new ClassNotFoundException(
                "IOException was thrown when trying to get all resources for "
                + pckgname, ioex);
    }

    return classes;
}

private static boolean isRecursiveCall = false;
private static ArrayList<Class<?>> classes;

static {
    if (classes == null) {
        try {
            classes = getClassesForPackage("Humans");
        } catch (ClassNotFoundException ex) {

        }
    }    
}

private String doThePetyrBaelish() {
    return Math.random() >= 0.5 ? "good" : "evil";
}

@Override
public String takeSides(String history) {
    if (isRecursiveCall) {
        return doThePetyrBaelish();
    }
    isRecursiveCall = true;

    int currentRoundGoodCount = 0;
    float probabilityOfGood = 0;
    int roundCount = 0;
    int voteCount = 0;



    do {
        for (int i = 0; i < classes.size(); i++) {
            try {
                if (classes.get(i).getName() == "Humans.FortuneTeller") {
                    continue;
                }

                Human human = (Human) classes.get(i).newInstance();
                String response = human.takeSides(history);
                switch (response) {
                    case "good":
                        currentRoundGoodCount++;
                        voteCount++;
                        break;
                    case "evil":
                        voteCount++;
                        break;
                    default:
                        break;
                }
            } catch (Exception e) {
            }
        }

        probabilityOfGood = (probabilityOfGood * roundCount
                + (float) currentRoundGoodCount / voteCount) / (roundCount + 1);

        roundCount++;
        currentRoundGoodCount = 0;
        voteCount = 0;

    } while (roundCount < 11);

    isRecursiveCall = false;
    if (probabilityOfGood > .7) {
        return "evil";
    }
    if (probabilityOfGood < .3) {
        return "good";
    }

    return doThePetyrBaelish();
}

}

Nếu bot của bạn chạy tất cả các bot khác mỗi lượt trước khi trả lời, bạn sẽ không mất hơn 1 giây để trả lời chứ?
plannapus

@plannapus Tôi sẽ đoán giả định với bot này là mọi người khác sẽ cảnh giác và tránh mọi thứ đáng để chờ đợi trong 1 giây. Tôi nghĩ rằng có thể đáng để gửi và nhập cảnh bao gồm 0,9 giây chờ đợi, trước khi trả lại "tốt", chỉ để gây rối với anh ta. Trên thực tế, SBoss đã đánh bại tôi: D
scragar

Yahhh! Sau đó, tôi sẽ phải đưa vào danh sách đen bot đó trong mã của tôi. Điều đó sẽ gây nản lòng ... Ngoài ra với các mục khác nhau trong các môi trường khác nhau như Python hoặc Perl, việc tải lại trình thông dịch có thể đủ để đưa mã này vượt quá giới hạn thời gian.
Andris

16
Nếu ai đó làm điều tương tự như thế này, bạn sẽ có một vòng lặp vô hạn.
Brilliand

4
Trình đã hết thời gian. Tôi đã đính kèm một hồ sơ, và gần nửa giây được dành để gọi một số bài nộp. Nó ít nhất hoạt động mặc dù, vì vậy xin chúc mừng cho điều đó.
Rainbolt

15

C ++, Nhà khoa học

Điều này cố gắng, với lịch sử của những gì đa số đã chọn cho mỗi vòng wave( majority()đưa ra lựa chọn của đa số trên một vòng), phù hợp với sóng với dữ liệu, về bước sóng 2*periodvà pha phase. Do đó, cho 0,1,1,1,0,1,0,1,1,1,0,0,0,1,0nó chọn period=3, phase=5( maxat=={3,5}): điểm số của nó trở thành 9 3 11 5 5 3 5 7 9 7 7 7 7 7 7. Nó lặp lại trong tất cả các khoảng thời gian có thể và nếu trong khoảng thời gian đó, điểm số cao hơn mức tối đa hiện tại, nó lưu trữ {period,phase}cho điều đó xảy ra.

Sau đó, nó ngoại suy sóng tìm thấy vào vòng tiếp theo và chiếm đa số dự đoán.

#include <iostream>
#include <utility>
#include <cstdlib>
#include <cstring>
#if 0
#define DBG(st) {st}
#else
#define DBG(st)
#endif

#define WINDOW (700)

using namespace std;

int majority(const char *r){
    int p=0,a=0,b=0;
    while(true){
        if(r[p]=='1')a++;
        else if(r[p]=='0')b++;
        else break;
        p++;
    }
    return a>b;
}

int main(int argc,char **argv){
    if(argc==1){
        cout<<(rand()%2?"good":"evil")<<endl;
        return 0;
    }
    DBG(cerr<<"WINDOW="<<WINDOW<<endl;)
    int nump,numr;
    nump=strchr(argv[1],',')-argv[1];
    numr=(strlen(argv[1])+1)/(nump+1);
    int fromround=numr-30;
    if(fromround<0)fromround=0;
    int period,r;
    int *wave=new int[WINDOW];
    bool allequal=true;
    DBG(cerr<<"wave: ";)
    for(r=fromround;r<numr;r++){
        wave[r-fromround]=majority(argv[1]+r*(nump+1));
        if(wave[r-fromround]!=wave[0])allequal=false;
        DBG(cerr<<wave[r]<<" ";)
    }
    DBG(cerr<<endl;)
    if(allequal){
        DBG(cerr<<"All equal!"<<endl;)
        if(wave[numr-1]==1)cout<<"evil"<<endl; //choose for minority
        else cout<<"good"<<endl;
        return 0;
    }
    int score,*scores=new int[WINDOW];
    int max=0; //some score will always get above 0, because if some score<0, the inverted wave will be >0.
    int phase,phasemax;
    pair<int,int> maxat(-1,-1); //period, phase
    DBG(cerr<<"scores: ";)
    for(period=1;period<=WINDOW;period++){
        scores[period-1]=0;
        phasemax=-1;
        for(phase=0;phase<2*period;phase++){
            score=0;
            for(r=fromround;r<numr;r++){
                if(wave[r]==1-(r+phase)%(2*period)/period)score++;
                else score--;
            }
            if(score>scores[period-1]){
                scores[period-1]=score;
                phasemax=phase;
            }
        }
        if(scores[period-1]>max){
            max=scores[period-1];
            maxat.first=period;
            maxat.second=phasemax;
        }
        DBG(cerr<<scores[period-1]<<" ";)
    }
    DBG(cerr<<"(max="<<max<<" at {"<<maxat.first<<","<<maxat.second<<"})"<<endl;)
    DBG(cerr<<" max: ("<<numr<<"+"<<maxat.second<<")%(2*"<<maxat.first<<")/"<<maxat.first<<"=="<<((numr+maxat.second)%(2*maxat.first)/maxat.first)<<endl;)
    if(1-(numr+maxat.second)%(2*maxat.first)/maxat.first==1)cout<<"evil"<<endl; //choose for minority
    else cout<<"good"<<endl;
    delete[] wave;
    delete[] scores;
    return 0;
}

Biên dịch với g++ -O3 -std=c++0x -o Scientist Scientist.cpp(bạn không cần cảnh báo, vì vậy không -Wall) và chạy với Scientist.exe(có thể bao gồm cả đối số của khóa học). Nếu bạn hỏi thực sự độc đáo tôi có thể cung cấp cho bạn một tệp thực thi Windows.

Ồ, và không dám lộn xộn với định dạng đầu vào. Nó sẽ làm những điều kỳ lạ khác.

EDIT: Rõ ràng, phiên bản trước đã hết thời gian khoảng 600 vòng vào trò chơi. Điều này không nên làm điều đó. Tiêu thụ thời gian của nó được kiểm soát bởi #define WINDOW (...)dòng, nhiều hơn là chậm hơn nhưng nhìn xa hơn.


8
Tải xuống các tệp thực thi được viết bởi sáu mươi + người lạ trên Internet có vẻ như là một ý tưởng tồi.
Rainbolt

@Raser Tôi hoàn toàn đồng ý. Nếu bạn muốn có vấn đề, đó là bước một trong hướng dẫn "cho người giả". Ưu đãi của tôi là đứng :)
tomsmeding

2
Có cái này để biên dịch (và cạnh tranh) tốt.
Rainbolt

14

Người chạy mã

Vì vậy, để làm cho mọi thứ trở nên thú vị, tôi đã tạo một tập lệnh để tự động tải xuống mã từ mỗi câu trả lời được đăng, biên dịch nó nếu cần thiết, sau đó chạy tất cả các giải pháp theo quy tắc. Bằng cách này, mọi người có thể kiểm tra cách họ đang làm. Chỉ cần lưu tập lệnh này vào run_all.py (yêu cầu BeautifulSoup) và sau đó:

usage:
To get the latest code: 'python run_all.py get'
To run the submissions: 'python run_all.py run <optional num_runs>'

Một vài thứ:

  1. Nếu bạn muốn thêm hỗ trợ cho nhiều ngôn ngữ hơn hoặc thay thế loại bỏ hỗ trợ cho một số ngôn ngữ, hãy xem def submission_type(lang).
  2. Việc mở rộng tập lệnh nên khá dễ dàng, ngay cả đối với các ngôn ngữ yêu cầu biên dịch (xem CPPSubmission). Loại ngôn ngữ được lấy từ thẻ mã meta < !-- language: lang-java -- >, vì vậy hãy đảm bảo thêm nó nếu bạn muốn mã của mình được chạy (Xóa các khoảng trắng thừa trước và sau <>). CẬP NHẬT : Hiện tại có một số suy luận cực kỳ cơ bản để thử và phát hiện ngôn ngữ nếu nó không được xác định.
  3. Nếu mã của bạn hoàn toàn không chạy hoặc không hoàn thành trong thời gian quy định, nó sẽ được thêm vào blacklist.textvà sẽ tự động bị xóa khỏi các thử nghiệm trong tương lai. Nếu bạn sửa mã của mình, chỉ cần xóa mục nhập của bạn khỏi danh sách đen và chạy lại get,

Các ngôn ngữ hiện được hỗ trợ:

 submission_types =  {
    'lang-ruby': RubySubmission,
    'lang-python': PythonSubmission,
    'lang-py': PythonSubmission,
    'lang-java': JavaSubmission,
    'lang-Java': JavaSubmission,
    'lang-javascript': NodeSubmission,
    'lang-cpp': CPPSubmission,
    'lang-c': CSubmission,
    'lang-lua': LuaSubmission,
    'lang-r': RSubmission,
    'lang-fortran': FortranSubmission,
    'lang-bash': BashSubmission
}

Nếu không có thêm rắc rối:

import urllib2
import hashlib
import os
import re
import subprocess
import shutil
import time
import multiprocessing
import tempfile
import sys
from bs4 import BeautifulSoup

__run_java__ = """
public class Run {
    public static void main(String[] args) {
        String input = "";
        Human h = new __REPLACE_ME__();
        if(args.length == 1)
            input = args[0];
        try {
            System.out.println(h.takeSides(input));
        }
        catch(Exception e) {
        }
    }
}
"""

__human_java__ = """
public abstract class Human {
    public abstract String takeSides(String history) throws Exception;
}
"""

class Submission():
    def __init__(self, name, code):
        self.name = name
        self.code = code

    def submissions_dir(self):
        return 'submission'

    def base_name(self):
        return 'run'

    def submission_path(self):
        return os.path.join(self.submissions_dir(), self.name)

    def extension(self):
        return ""

    def save_submission(self):
        self.save_code()

    def full_command(self, input):
        return []

    def full_path(self):
        file_name = "%s.%s" % (self.base_name(), self.extension())
        full_path = os.path.join(self.submission_path(), file_name)
        return full_path

    def save_code(self):    
        if not os.path.exists(self.submission_path()):
            os.makedirs(self.submission_path())

        with open(self.full_path(), 'w') as f:
            f.write(self.code)

    def write_err(self, err):
        with open(self.error_log(), 'w') as f:
            f.write(err)

    def error_log(self):
        return os.path.join(self.submission_path(), 'error.txt')

    def run_submission(self, input):
        command = self.full_command()
        if input is not None:
            command.append(input)
        try:
            output,err,exit_code = run(command,timeout=1)
            if len(err) > 0:
                self.write_err(err)
            return output
        except Exception as e:
            self.write_err(str(e))
            return ""

class CPPSubmission(Submission):
    def bin_path(self):
        return os.path.join(self.submission_path(), self.base_name())

    def save_submission(self):
        self.save_code()
        compile_cmd = ['g++', '-O3', '-std=c++0x', '-o', self.bin_path(), self.full_path()]
        errout = open(self.error_log(), 'w')
        subprocess.call(compile_cmd, stdout=errout, stderr=subprocess.STDOUT)

    def extension(self):
        return 'cpp'

    def full_command(self):
        return [self.bin_path()]

class CSubmission(Submission):
    def bin_path(self):
        return os.path.join(self.submission_path(), self.base_name())

    def save_submission(self):
        self.save_code()
        compile_cmd = ['gcc', '-o', self.bin_path(), self.full_path()]
        errout = open(self.error_log(), 'w')
        subprocess.call(compile_cmd, stdout=errout, stderr=subprocess.STDOUT)

    def extension(self):
        return 'c'

    def full_command(self):
        return [self.bin_path()]

class FortranSubmission(Submission):
    def bin_path(self):
        return os.path.join(self.submission_path(), self.base_name())

    def save_submission(self):
        self.save_code()
        compile_cmd = ['gfortran', '-fno-range-check', '-o', self.bin_path(), self.full_path()]
        errout = open(self.error_log(), 'w')
        subprocess.call(compile_cmd, stdout=errout, stderr=subprocess.STDOUT)

    def extension(self):
        return 'f90'

    def full_command(self):
        return [self.bin_path()]

class JavaSubmission(Submission):   
    def base_name(self):
        class_name = re.search(r'class (\w+) extends', self.code)
        file_name = class_name.group(1)
        return file_name

    def human_base_name(self):
        return 'Human'

    def run_base_name(self):
        return 'Run'

    def full_name(self, base_name):
        return '%s.%s' % (base_name, self.extension())

    def human_path(self):
        return os.path.join(self.submission_path(), self.full_name(self.human_base_name()))

    def run_path(self):
        return os.path.join(self.submission_path(), self.full_name(self.run_base_name()))

    def replace_in_file(self, file_name, str_orig, str_new):
        old_data = open(file_name).read()
        new_data = old_data.replace(str_orig, str_new)

        with open(file_name, 'w') as f:
            f.write(new_data)

    def write_code_to_file(self, code_str, file_name):
        with open(file_name, 'w') as f:
            f.write(code_str)

    def save_submission(self):
        self.save_code()
        self.write_code_to_file(__human_java__, self.human_path())
        self.write_code_to_file(__run_java__, self.run_path())

        self.replace_in_file(self.run_path(), '__REPLACE_ME__', self.base_name())
        self.replace_in_file(self.full_path(), 'package Humans;', '')

        compile_cmd = ['javac', '-cp', self.submission_path(), self.run_path()]
        errout = open(self.error_log(), 'w')
        subprocess.call(compile_cmd, stdout=errout, stderr=subprocess.STDOUT)

    def extension(self):
        return 'java'

    def full_command(self):
        return ['java', '-cp', self.submission_path(), self.run_base_name()]

class PythonSubmission(Submission):
    def full_command(self):
        return ['python', self.full_path()]

    def extension(self):
        return 'py'

class RubySubmission(Submission):
    def full_command(self):
        return ['ruby', self.full_path()]

    def extension(self):
        return 'rb'

class NodeSubmission(Submission):
    def full_command(self):
        return ['node', self.full_path()]

    def extension(self):
        return 'js'

class LuaSubmission(Submission):
    def full_command(self):
        return ['lua', self.full_path()]

    def extension(self):
        return 'lua'

class RSubmission(Submission):
    def full_command(self):
        return ['Rscript', self.full_path()]

    def extension(self):
        return 'R'

class BashSubmission(Submission):
    def full_command(self):
        return [self.full_path()]

    def extension(self):
        return '.sh'

class Scraper():
    def download_page(self, url, use_cache = True, force_cache_update = False):
        file_name = hashlib.sha1(url).hexdigest()

        if not os.path.exists('cache'):
            os.makedirs('cache')

        full_path = os.path.join('cache', file_name)
        file_exists = os.path.isfile(full_path)

        if use_cache and file_exists and not force_cache_update:
            html = open(full_path, 'r').read()
            return html

        opener = urllib2.build_opener()
        opener.addheaders = [('User-agent', 'Mozilla/5.0')]
        response = opener.open(url)
        html = response.read()

        if use_cache:
            f = open(full_path, 'w')
            f.write(html)
            f.close()

        return html

    def parse_post(self, post):
        name = post.find(text=lambda t: len(t.strip()) > 0)
        pre = post.find('pre')
        lang = pre.attrs['class'][0] if pre.has_attr('class') else None
        code = pre.find('code').text
        user = post.find(class_='user-details').find(text=True)
        return {'name':name,'lang':lang,'code':code,'user':user}

    def parse_posts(self, html):
        soup = BeautifulSoup(html)
        # Skip the first post
        posts = soup.find_all(class_ = 'answercell')
        return [self.parse_post(post) for post in posts]

    def get_submissions(self,  page = 1, force_cache_update = False):
        url = "http://codegolf.stackexchange.com/questions/33137/good-versus-evil?page=%i&tab=votes#tab-top" % page
        html = self.download_page(url, use_cache = True, force_cache_update = force_cache_update)
        submissions = self.parse_posts(html)
        return submissions

class Timeout(Exception):
    pass

def run(command, timeout=10):
    proc = subprocess.Popen(command, bufsize=0, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    poll_seconds = .250
    deadline = time.time()+timeout
    while time.time() < deadline and proc.poll() == None:
        time.sleep(poll_seconds)

    if proc.poll() == None:
        if float(sys.version[:3]) >= 2.6:
            proc.terminate()
        raise Timeout()

    stdout, stderr = proc.communicate()
    return stdout, stderr, proc.returncode


def guess_lang(code):
    if re.search(r'class .* extends Human', code):
        return 'lang-java'
    if re.search(r'import sys', code):
        return 'lang-python'
    if re.search(r'puts', code) and (re.search(r'ARGV', code) or re.search(r'\%w', code)):
        return 'lang-ruby'
    if re.search(r'console\.log', code):
        return 'lang-javascript'
    if re.search(r'program', code) and re.search(r'subroutine', code):
        return 'lang-fortran'
    if re.search(r'@echo off', code):
        return 'lang-bash'
    return None


def submission_type(lang, code):
    submission_types =  {
        'lang-ruby': RubySubmission,
        'lang-python': PythonSubmission,
        'lang-py': PythonSubmission,
        'lang-java': JavaSubmission,
        'lang-Java': JavaSubmission,
        'lang-javascript': NodeSubmission,
        'lang-cpp': CPPSubmission,
        'lang-c': CSubmission,
        'lang-lua': LuaSubmission,
        'lang-r': RSubmission,
        'lang-fortran': FortranSubmission,
        'lang-bash': BashSubmission
    }

    klass = submission_types.get(lang)

    if klass is None:
        lang = guess_lang(code)
        klass = submission_types.get(lang)

    return klass

def instantiate(submission):
    lang = submission['lang']
    code = submission['code']
    name = submission['name']

    klass = submission_type(lang, code)
    if klass is not None:
        instance = klass(name, code)
        return instance
    print "Entry %s invalid - lang not supported: %s" % (name, lang)
    return None

def get_all_instances(force_update):
    scraper = Scraper()

    print 'Scraping Submissions..'

    pages = [1,2,3]
    submissions_by_page = [scraper.get_submissions(page=i, force_cache_update=force_update) for i in pages]
    submissions = [item for sublist in submissions_by_page for item in sublist]

    # Get instances
    raw_instances = [instantiate(s) for s in submissions]
    instances = [i for i in raw_instances if i]

    print "Using %i/%i Submissions" % (len(instances), len(submissions))

    return instances

def save_submissions(instances):
    print 'Saving Submissions..'

    for instance in instances:
        instance.save_submission()

def init_game(save=True, force_update=False):
    instances = get_all_instances(force_update)
    if save:
        save_submissions(instances)
    return instances

def one_run(instances, input):
    valid = {
        'good': 1,
        'evil': 0
    }

    disqualified = []
    results = []

    for instance in instances:
        out = instance.run_submission(input)
        res = out.strip().lower()
        if res not in valid:
            disqualified.append(instance)
        else:
            results.append(valid[res])

    return (results, disqualified)

def get_winner(scores, instances):
    max_value = max(scores)
    max_index = scores.index(max_value)
    instance = instances[max_index]
    return (instance.name, max_value)

def update_scores(results, scores, minority_counts, minority_num):
    for i in range(len(results)):
        if results[i] == minority_num:
            minority_counts[i] += 1
            scores[i] += (minority_counts[i] - 1)
        else:
            minority_counts[i] = 0
            scores[i] += 3

def try_run_game(instances, num_runs = 1000, blacklist = None):
    current_input = None
    minority_str = None
    num_instances = len(instances)
    scores = [0] * num_instances
    minority_counts = [0] * num_instances

    print "Running with %i instances..." % num_instances

    for i in range(num_runs):
        print "Round: %i - Last minority was %s" % (i, minority_str)
        results, disqualified = one_run(instances, current_input)

        if len(disqualified) > 0:
            for instance in disqualified:
                print "Removing %s!" % instance.name
                instances.remove(instance)

                if blacklist is not None:
                    with open(blacklist, 'a') as f:
                        f.write("%s\n" % instance.name)

            return False

        latest_result = "".join(map(str,results))
        current_input = "%s,%s" % (current_input, latest_result)

        minority_num = 1 if results.count(1) < results.count(0) else 0
        minority_str = 'good' if minority_num == 1 else 'evil'

        update_scores(results, scores, minority_counts, minority_num)
        name, score = get_winner(scores, instances)
        print "%s is currently winning with a score of %i" % (name, score)

    print "The winner is %s with a score of %i!!!" % (name, score)
    return True

def find_instance_by_name(instances, name):
    for instance in instances:
        if instance.name == name:
            return instance
    return None

def maybe_add_or_remove_baelish(instances, baelish):
    num_instances = len(instances)

    if num_instances % 2 == 0:
        print 'There are %i instances.' % num_instances
        try:
            instances.remove(baelish)
            print 'Baelish Removed!'
        except:
            instances.append(baelish)
            print 'Baelish Added!'

def remove_blacklisted(blacklist, instances):
    blacklisted = []

    try:
        blacklisted = open(blacklist).readlines()
    except:
        return

    print 'Removing blacklisted entries...'

    for name in blacklisted:
        name = name.strip()
        instance = find_instance_by_name(instances, name)
        if instance is not None:
            print 'Removing %s' % name
            instances.remove(instance)

def run_game(instances, num_runs):
    blacklist = 'blacklist.txt'
    remove_blacklisted(blacklist, instances)

    baelish = find_instance_by_name(instances, 'Petyr Baelish') 
    maybe_add_or_remove_baelish(instances, baelish)

    while not try_run_game(instances, num_runs = num_runs, blacklist = blacklist):
        print "Restarting!"
        maybe_add_or_remove_baelish(instances, baelish)

    print "Done!"

if __name__ == '__main__':
    param = sys.argv[1] if len(sys.argv) >= 2 else None

    if param == 'get':
        instances = init_game(save=True, force_update=True)
    elif param == 'run':
        instances = init_game(save=False, force_update=False)
        num_runs = 50
        if len(sys.argv) == 3:
            num_runs = int(sys.argv[2])
        run_game(instances, num_runs)
    else:
        self_name = os.path.basename(__file__)
        print "usage:"
        print "To get the latest code: 'python %s get'" % self_name
        print "To run the submissions: 'python %s run <optional num_runs>'" % self_name

Tại sao không có ngôn ngữ Fortran ??
Kyle Kanos

@KyleKanos - Tôi đã thêm hỗ trợ cho nó, sẽ cập nhật mã sớm.
WhatAWorld

Yay! Tôi (sorta) đã làm việc chăm chỉ trong việc gửi Fortran của mình và Raser không thể làm cho nó hoạt động được vì vậy tôi muốn ai đó có được nó :)
Kyle Kanos

1
@Rizer: Tôi đồng ý với PeterTaylor về điều này: đánh dấu cú pháp là chỉnh sửa được đề xuất duy nhất nên bị từ chối. Chỉnh sửa nên được sử dụng để sửa chữa đáng kể , không phải thứ nhỏ.
Kyle Kanos

1
Bạn xứng đáng được đại diện cho điều này, nhưng vì đây không chính xác là câu trả lời cho câu hỏi (và có thể có lợi từ cộng đồng thêm nội dung cho các ngôn ngữ khác) Tôi nghĩ rằng về mặt kỹ thuật nên là một wiki cộng đồng.
Martin Ender

13

Tâm trí đẹp, Ruby

Đưa ra quyết định dựa trên các mẫu có ý nghĩa nghi vấn trong biểu diễn bit của vòng cuối cùng

require 'prime'

if ARGV.length == 0
    puts ["good", "evil"].sample
else
    last_round = ARGV[0].split(',').last
    puts Prime.prime?(last_round.to_i(2)) ? "good" : "evil"
end

Chạy như

ruby beautiful-mind.rb

13

Mạnh mẽ, Lua

Một chương trình mê tín tin vào Dấu hiệu và Kỳ quan.

history = arg[1]

if history == nil then
    print("good")
else
    local EvilSigns, GoodSigns = 0,0
    local SoulSpace = ""

    for i in string.gmatch(history, "%d+") do
         SoulSpace = SoulSpace .. i 
    end

    if string.match(SoulSpace, "1010011010")  then -- THE NUBMER OF THE BEAST!
        local r = math.random(1000)
        if r <= 666 then print("evil") else print("good") end
    else
        for i in string.gmatch(SoulSpace, "10100") do -- "I'M COMING" - DEVIL
            EvilSigns = EvilSigns + 1
        end
        for i in string.gmatch(SoulSpace, "11010") do -- "ALL IS WELL" - GOD
            GoodSigns = GoodSigns + 1
        end

        if EvilSigns > GoodSigns then 
            print("evil")
        elseif GoodSigns > EvilSigns then
            print("good")
        elseif GoodSigns == EvilSigns then
            local r = math.random(1000)
            if r <= 666 then print("good") else print("evil") end
        end
    end
end

chạy nó với:

lua Piustitious.lua

tiếp theo là đầu vào.


11

Nhà máy rượu

Sam và Dean đều tốt (hầu hết thời gian).

package Humans;

public class TheWinchesters extends Human {

    @Override
    public String takeSides(String history) throws Exception {
        return Math.random() < 0.1 ? "evil" : "good";
    }

}

Bạn có chắc 9:1là tỷ lệ đúng? Có lẽ chúng ta nên thực hiện một số khai thác dữ liệu và có được một tỷ lệ chính xác hơn?
đệ

1
@awashburn Tôi bắt đầu xem Supernatural 2 tháng trước (hiện đang bị kẹt trong phần 9) và 9:1có vẻ ổn với tôi;)
CommonGuy

10

Thống kê

public class Statistician extends Human{
    public final String takeSides(String history) { 
        int side = 0;
        String[] hist = history.split(",");
        for(int i=0;i<hist.length;i++){
            for(char c:hist[i].toCharArray()){
                side += c == '1' ? (i + 1) : -(i + 1);
            }
        }
        if(side == 0) side += Math.round(Math.random());
        return side > 0 ? "good" : "evil";
    }
}

5
Dòng cuối cùng thứ hai đó thật tuyệt vời
cjfaure

5
@Undeserved Thay Math.ceil(Math.random()-Math.random())bạn cũng có thể làm Math.round(Math.random()).
tomsmeding

10

R, một bot Bayesian

Sử dụng bảng tần suất cho mỗi người dùng làm xác suất trước của đầu ra của người dùng khác.

args <- commandArgs(TRUE)
if(length(args)!=0){
    history <- do.call(rbind,strsplit(args,","))
    history <- do.call(rbind,strsplit(history,""))
    tabulated <- apply(history,2,function(x)table(factor(x,0:1)))
    result <- names(which.max(table(apply(tabulated, 2, function(x)sample(0:1,1, prob=x)))))
    if(result=="1"){cat("good")}else{cat("evil")}
}else{
    cat("good")
    }

Được gọi bằng cách sử dụng Rscript BayesianBot.Rtheo sau bởi đầu vào.

Chỉnh sửa : Chỉ cần làm rõ những gì đang làm, đây là từng bước với đầu vào ví dụ:

> args
[1] "11011,00101,11101,11111,00001,11001,11001"
> history #Each player is a column, each round a row
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    1    0    1    1
[2,]    0    0    1    0    1
[3,]    1    1    1    0    1
[4,]    1    1    1    1    1
[5,]    0    0    0    0    1
[6,]    1    1    0    0    1
[7,]    1    1    0    0    1

> tabulated #Tally of each player previous decisions.
  [,1] [,2] [,3] [,4] [,5]
0    2    2    4    5    0
1    5    5    3    2    7

Sau đó, dòng bắt đầu bằng result<-, đối với mỗi người chơi, chọn ngẫu nhiên 0 hoặc 1 bằng cách sử dụng bảng cuối cùng này làm trọng số (tức là đối với người chơi 1, xác suất chọn 0 là 2/7, chọn 1 5/7, v.v.). Nó chọn một kết quả cho mỗi người chơi / cột và cuối cùng trả về số kết thúc là phổ biến nhất.


10

Thụy Sĩ

Luôn duy trì tính trung lập. Doomed để không bao giờ chiến thắng.

package Humans;

/**
 * Never choosing a side, sustaining neutrality
 * @author Fabian
 */
public class Swiss extends Human {   
    public String takeSides(String history) {
        return "neutral"; // wtf, how boring is that?
    }
}

Tôi đã không viết điều này!
Rainbolt

Đó là sự trớ trêu. Tính trung lập không bao giờ thắng
fabigler

2
@Rizer ah Tôi hiểu rồi: D
fabigler

1
Nó thậm chí không biên dịch - có một dấu chấm phẩy bị thiếu.
Paŭlo Ebermann

9

HAL 9000

#!/usr/bin/env perl
print eval("evil")

Chỉnh sửa: có thể điều này phù hợp hơn với HAL 9000, nhưng hãy cẩn thận! Nó rất xấu xa. Tôi khuyên bạn nên cdđể thư mục trống trước khi chạy nó.

#!/usr/bin/env perl
print eval {
    ($_) = grep { -f and !/$0$/ } glob('./*');
    unlink;
    evil
}

Điều này loại bỏ một tập tin từ cwdmỗi lần gọi!

Lời mời không quá rõ ràng:

Bằng M $

D:\>copy con hal_9000.pl
#!/usr/bin/env perl
print eval("evil")
^Z
        1 file(s) copied.

D:>hal_9000.pl
evil

Trong * nix

[core1024@testing_pc ~]$ tee hal_9000.pl
#!/usr/bin/env perl
print eval("evil")
# Press C-D here
[core1024@testing_pc ~]$ chmod +x $_
[core1024@testing_pc ~]$ ./$_
evil[core1024@testing_pc ~]$

Bạn cần cung cấp một lệnh có thể được sử dụng để chạy chương trình của bạn. Xem phần "Sản phẩm giao" của thử thách để biết thêm thông tin.
Rainbolt

@Raser Xong;)
core1024

9

Ý chí của đa số

import sys
import random

if len(sys.argv)==1:
    print(random.choice(['good','evil']))
else:
    rounds=sys.argv[1].split(',')
    last_round=rounds[-1]
    zeroes=last_round.count('0')
    ones=last_round.count('1')
    if ones>zeroes:
        print('good')
    elif zeroes>ones:
        print('evil')
    elif ones==zeroes:
        print(random.choice(['good','evil']))

Lưu nó dưới dạng WotM.py, chạy python3 WotM.pytheo sau bởi đầu vào.

Một chương trình đơn giản, chỉ để xem nó sẽ làm như thế nào. Đi với bất cứ điều gì đa số nói lần trước, hoặc người khác ngẫu nhiên.


Bạn cần cung cấp một lệnh có thể được sử dụng để chạy chương trình của bạn. Xem phần "Sản phẩm giao" của thử thách để biết thêm thông tin.
Rainbolt

Chết tiệt, điều đó làm cho tôi một bản sao. : D Thay đổi mỏ thành thiểu số.
Martin Ender

@Rizer Đã thêm lệnh. Đó là những gì bạn đang tìm kiếm?
isaacg

@isaacg Hoàn hảo!
Rainbolt

1
Tôi đã tính thứ hạng trung bình từ điểm số trong bảng điểm và mục này thắng theo cách đó.
Brilliand

9

Alan Shearer

Lặp lại bất cứ điều gì người anh ấy ngồi bên cạnh vừa nói. Nếu người đó tỏ ra sai lầm, anh ta chuyển sang người tiếp theo và lặp lại những gì họ nói thay vào đó.

package Humans;

/**
 * Alan Shearer copies someone whilst they're right; if they get predict
 * wrongly then he moves to the next person and copies whatever they say.
 *
 * @author Algy
 * @url http://codegolf.stackexchange.com/questions/33137/good-versus-evil
 */
public class AlanShearer extends Human {

    private char calculateWinner(String round) {
        int good = 0, evil = 0;

        for (int i = 0, L = round.length(); i < L; i++) {
            if (round.charAt(i) == '1') {
                good++;
            } else {
                evil++;
            }
        }

        return (good >= evil) ? '1' : '0';
    }

    /**
     * Take the side of good or evil.
     * @param history The past votes of every player
     * @return A String "good" or "evil
     */
    public String takeSides(String history) {
        String[] parts = history.split(",");
        String lastRound = parts[parts.length() - 1];

        if (parts.length() == 0 || lastRound.length() == 0) {
            return "good";
        } else {
            if (parts.length() == 1) {
                return lastRound.charAt(0) == '1' ? "good" : "evil";
            } else {
                int personToCopy = 0;

                for (int i = 0, L = parts.length(); i < L; i++) {
                    if (parts[i].charAt(personToCopy) != calculateWinner(parts[i])) {
                        personToCopy++;

                        if (personToCopy >= L) {
                            personToCopy = 0;
                        }
                    }
                }
            }

            return lastRound.charAt(personToCopy) == '1' ? "good" : "evil";
        }
    }
}

Bạn tham chiếu một biến được gọi lastRoundtrước khi bạn khai báo nó. Ngoài ra, bạn đã thêm dấu ngoặc đơn cho tất cả String.lengthnhưng đây không phải là chức năng. Bạn có thể nhận được trình của bạn đến một điểm mà nó sẽ biên dịch?
Rainbolt

@Rizer - xong :)
Algy Taylor

@Algy: lastRound.lengthvẫn được truy cập (trong if đầu tiên) trước khi lastRoundđược khai báo (trong đó nếu khác). Vui lòng thử biên dịch (và có thể chạy) mã của bạn trước khi gửi nó ở đây.
Paŭlo Ebermann

@ PaŭloEbermann - xin lỗi, tôi không ở trong môi trường mà tôi có thể chạy nó - mặc dù vậy, sửa đổi được thực hiện
Algy Taylor

Bây giờ bạn đang tham khảo một biến có tên là "personToCopy" khi nó nằm ngoài phạm vi. Tôi chỉ di chuyển nó vào bên trong khối khác để nó biên dịch, nhưng tôi không biết đó có phải là điều bạn muốn không.
Rainbolt

8

Sau này là Evil, JavaScript ( node.js )

Đo lượng thời gian giữa các lần thực hiện. Nếu chênh lệch thời gian lớn hơn lần trước thì phải là ác. Nếu không, tốt.

var fs = require('fs'),
currentTime = (new Date).getTime();

try {
    var data = fs.readFileSync('./laterisevil.txt', 'utf8');
} catch (e) { data = '0 0'; } // no file? no problem, let's start out evil at epoch

var parsed = data.match(/(\d+) (\d+)/),
lastTime = +parsed[1],
lastDifference = +parsed[2],
currentDifference = currentTime - lastTime;

fs.writeFileSync('./laterisevil.txt', currentTime + ' ' + currentDifference, 'utf8');
console.log(currentDifference > lastDifference? 'evil' : 'good');

Chạy với: node laterisevil.js


8

Trình tìm mẫu, Python

Tìm kiếm một mô hình định kỳ và nếu nó không thể tìm thấy một mô hình, chỉ cần đi với đa số.

import sys

if len(sys.argv) == 1: 
    print('good')
    quit()

wins = ''.join(
    map(lambda s: str(int(s.count('1') > s.count('0'))),
        sys.argv[1].split(',')
    )
)

# look for a repeating pattern
accuracy = []

for n in range(1, len(wins)//2+1):
    predicted = wins[:n]*(len(wins)//n)
    actual    = wins[:len(predicted)]
    n_right = 0
    for p, a in zip(predicted, actual):
        n_right += (p == a)
    accuracy.append(n_right/len(predicted))

# if there's a good repeating pattern, use it
if accuracy:
    best = max(accuracy)
    if best > 0.8:
        n = accuracy.index(best)+1
        prediction = wins[:n][(len(wins))%n]
        # good chance of success by going with minority
        if prediction == '1':
            print('evil')
        else:
            print('good')
        quit()

# if there's no good pattern, just go with the majority
if wins.count('1') > wins.count('0'):
    print('good')
else:
    print('evil')

chạy với

python3 pattern_finder.py

1
Tôi yêu mã này rất nhiều, khi tôi chạy nó, nó luôn nhận được 3000 điểm, bằng cách nào đó.
Realdeo

8

Áo khoác

Turncoat tin rằng vì các chiến binh khác cho đến nay, phần lớn sẽ luân phiên thay đổi sau mỗi vòng đấu giữa thiện và ác thường xuyên hơn là ở cùng một phía. Do đó, anh ta bắt đầu vòng đầu tiên bằng cách tùy tiện đứng về phía tốt, sau đó luân phiên mỗi vòng trong một nỗ lực để ở lại đội chiến thắng hoặc thua thường xuyên hơn không.

package Humans;

public class Turncoat extends Human {
    public final String takeSides(String history) {
        String[] hist = history.split(",");

        return (hist.length % 2) == 0 ? "good" : "evil";
    }
}

Sau khi viết bài này, tôi nhận ra rằng do các mục dựa trên phân tích thống kê, động lượng sẽ khiến phần lớn chuyển đổi ít hơn khi nhiều vòng đã được hoàn thành. Do đó, các Turncoat lười biếng.

Áo khoác lười

Lazy Turncoat bắt đầu giống như Turncoat, nhưng khi vòng quay trôi qua, anh trở nên lười hơn và lười hơn để chuyển sang phía bên kia.

package Humans;

public class LazyTurncoat extends Human {
    public final String takeSides(String history) {
        int round = history.length() == 0 ? 0 : history.split(",").length;
        int momentum = 2 + ((round / 100) * 6);
        int choice = round % momentum;
        int between = momentum / 2;

        return choice < between ? "good" : "evil";
    }
}

2
Áo khoác lười là tuyệt vời!
Fuchs

Tôi bao gồm cả hai nếu bạn không phiền.
Rainbolt

Đi về phía trước. Tôi tò mò muốn xem cả hai sẽ làm thế nào, đặc biệt là so với những người tổng hợp số liệu thống kê bầu chọn.
jaybz

@Rainbolt Tôi chỉ nhận thấy một lỗi ngu ngốc với Turncoat. Không cần phải sửa nó mặc dù. Nó vẫn hoạt động, không hoàn toàn như dự định và ngay cả khi chưa quá muộn để sửa nó, việc sửa nó sẽ chỉ khiến nó hoạt động chính xác như một trong những mục mới hơn. Vui lòng bao gồm / loại trừ nếu bạn muốn.
jaybz

8

Người viết tiểu sử, Ruby

rounds = ARGV[0].split(',') rescue []

if rounds.length < 10
  choice = 1
else
  outcome_history = ['x',*rounds.map{|r|['0','1'].max_by{|s|r.count s}.tr('01','ab')}]
  player_histories = rounds.map{|r|r.chars.to_a}.transpose.map{ |hist| outcome_history.zip(hist).join }
  predictions = player_histories.map do |history|
    (10).downto(0) do |i|
      i*=2
      lookbehind = history[-i,i]
      @identical_previous_behavior = history.scan(/(?<=#{lookbehind})[10]/)
      break if @identical_previous_behavior.any?
    end
    if @identical_previous_behavior.any?
      (@identical_previous_behavior.count('1')+1).fdiv(@identical_previous_behavior.size+2)
    else
      0.5
    end
  end
  simulations = (1..1000).map do
    votes = predictions.map{ |chance| rand < chance ? 1 : 0 }
    [0,1].max_by { |i| votes.count(i) }
  end
  choice = case simulations.count(1)/10
    when 0..15
      1
    when 16..50
      0
    when 51..84
      1
    when 85..100
      0
  end
end

puts %w[evil good][choice]

Nỗ lực của tôi tại một mục gần như thông minh (một mục thực sự thông minh sẽ yêu cầu thử nghiệm đối với lĩnh vực này). Được viết bằng Ruby, vì vậy có khả năng điều này sẽ quá chậm, nhưng trên máy của tôi dù sao cũng mất 0,11 giây để tính vòng cuối cùng khi có 40 người chơi ngẫu nhiên, vì vậy tôi hy vọng nó sẽ hoạt động đủ tốt.

lưu dưới dạng biographer.rb, chạy nhưruby biographer.rb

Ý tưởng là đối với mỗi người chơi, họ ước tính cơ hội chọn "tốt" của họ bằng cách xem xét cả hai lựa chọn của họ trong mười vòng cuối cùng, và kết quả chung và tìm ra các trường hợp trong quá khứ có hoàn cảnh giống hệt nhau (phiếu bầu của họ + tổng thể kết quả) xảy ra. Nó chọn độ dài dài nhất, lên tới 10 vòng, sao cho có bất kỳ tiền lệ nào và sử dụng tần số đó để tạo tần số (được điều chỉnh theo Luật kế thừa của Laplace, để chúng tôi không bao giờ tin tưởng 100% về bất kỳ ai).

Sau đó, nó chạy một số mô phỏng và xem tần suất Tốt thắng. Nếu các mô phỏng hóa ra gần như giống nhau, thì có lẽ nó sẽ dự đoán tốt nói chung để nó chọn ra thiểu số dự đoán. Nếu nó không tự tin, nó chọn đa số dự đoán.


8

Giu-đa

Giuđa là một người thực sự tốt. Thật đáng tiếc anh ta sẽ phản bội những người tốt trong một vài đồng xu.

package Humans;

public class Judas extends Human {

    private static final String MONEY = ".*?0100110101101111011011100110010101111001.*?";

    public String takeSides(String history) {
       return history != null && history.replace(",","").matches(MONEY) ? "evil" : "good";
    }
}

1
Điều này chỉ bao giờ bỏ phiếu ác nếu có đủ người tham gia, bạn có thể muốn loại bỏ ,ra khỏi history, thậm chí nhiều hơn như vậy như Rusher sẽ chia ra các trò chơi theo nhóm.
Fuchs Angelo

Tôi không biết anh ấy sẽ chia trò chơi theo nhóm. Tôi thực sự đã đợi câu hỏi này để có đủ bài nộp trước khi đăng câu trả lời của mình vì kích thước chuỗi. Cảm ơn vì đã cho tôi biết.
William Barbosa

Nếu bạn biết cách truyền đối số 60000 ký tự cho một tiến trình trong Windows, hãy cho tôi biết. Nếu không, xin lỗi vì đã làm hỏng mục nhập của bạn và cảm ơn bạn đã sửa nó! Tôi đã không dự đoán sẽ nhận được rất nhiều bài nộp.
Rainbolt

7

Người đánh bạc ngu ngốc (Python)

Nếu một bên giành được đa số nhiều lần liên tiếp, con bạc nhận ra rằng bên kia có nhiều khả năng là đa số vòng tiếp theo (phải không?) Và điều này ảnh hưởng đến lá phiếu của anh ta. Anh ta nhắm đến nhóm thiểu số, bởi vì nếu anh ta biến nó thành thiểu số một khi anh ta có khả năng sẽ đến đó một số lần (phải không?) Và nhận được rất nhiều điểm.

import sys
import random

def whoWon(round):
    return "good" if round.count("1") > round.count("0") else "evil"

if len(sys.argv) == 1:
    print random.choice(["good", "evil"])
else:
    history = sys.argv[1]
    rounds = history.split(",")
    lastWin = whoWon(rounds[-1])
    streakLength = 1
    while streakLength < len(rounds) and whoWon(rounds[-streakLength]) == lastWin:
        streakLength += 1
    lastLoss = ["good", "evil"]
    lastLoss.remove(lastWin)
    lastLoss = lastLoss[0] 
    print lastWin if random.randint(0, streakLength) > 1 else lastLoss  

Sử dụng

Đối với vòng đầu tiên:

python gambler.py

và sau đó:

python gambler.py 101,100,001 etc.

4
Tôi thích cách bạn có vẻ chắc chắn về mã của bạn, phải không? : P
IEatBagels

7

Máy tự động

Điều này sử dụng các quy tắc thông thường cho Trò chơi cuộc sống của Conway để chọn một bên. Đầu tiên, một lưới 2D được tạo ra từ các phiếu bầu trước đó. Sau đó, "thế giới" được tiến lên một giai đoạn và tổng số tế bào sống còn lại được tính toán. Nếu con số này lớn hơn một nửa tổng số ô, "tốt" được chọn. Nếu không, "cái ác" được chọn.

Xin vui lòng tha thứ cho bất kỳ sai lầm, điều này đã được đập tan trong giờ ăn trưa của tôi. ;)

package Humans;

public class CellularAutomaton extends Human {

    private static final String GOOD_TEXT = "good";

    private static final String EVIL_TEXT = "evil";

    private int numRows;

    private int numColumns;

    private int[][] world;

    @Override
    public String takeSides(String history) {
        String side = GOOD_TEXT;

        if (history.isEmpty()) {
            side = Math.random() <= 0.5 ? GOOD_TEXT : EVIL_TEXT;
        }

        else {
            String[] prevVotes = history.split(",");

            numRows = prevVotes.length;

            numColumns = prevVotes[0].length();

            world = new int[numRows][numColumns];

            for (int i = 0; i < numColumns; i++) {
                for (int j = 0; j < numRows; j++) {
                    world[j][i] =
                        Integer.parseInt(Character.toString(prevVotes[j].charAt(i)));
                }
            }

            int totalAlive = 0;
            int total = numRows * numColumns;
            for (int i = 0; i < numColumns; i++) {
                for (int j = 0; j < numRows; j++) {
                    totalAlive += getAlive(world, i, j);
                }
            }
            if (totalAlive < total / 2) {
                side = EVIL_TEXT;
            }
        }

        return side;
    }

    private int getAlive(int[][] world, int i, int j) {
        int livingNeighbors = 0;

        if (i - 1 >= 0) {
            if (j - 1 >= 0) {
                livingNeighbors += world[j - 1][i - 1];
            }
            livingNeighbors += world[j][i - 1];
            if (j + 1 < numRows) {
                livingNeighbors += world[j + 1][i - 1];
            }
        }
        if (j - 1 >= 0) {
            livingNeighbors += world[j - 1][i];
        }
        if (j + 1 < numRows) {
            livingNeighbors += world[j + 1][i];
        }
        if (i + 1 < numColumns) {
            if (j - 1 >= 0) {
                livingNeighbors += world[j - 1][i + 1];
            }
            livingNeighbors += world[j][i + 1];
            if (j + 1 < numRows) {
                livingNeighbors += world[j + 1][i + 1];
            }
        }

        return livingNeighbors > 1 && livingNeighbors < 4 ? 1 : 0;
    }
}

1
Tôi đã xóa dòng in khỏi mã để kiểm tra .. Các mục nhập Java chỉ cần trả về tốt hay xấu, không in nó.
Rainbolt

7

Giáo sư

Tôi hy vọng việc sử dụng thư viện được cho phép, đừng cảm thấy muốn làm điều này mà không có ai =)

Ý tưởng cơ bản là đào tạo một bộ phân loại hồi quy sườn cho mỗi người tham gia vào các vòng cuối cùng, sử dụng 30 kết quả trước mỗi vòng làm tính năng. Ban đầu bao gồm cả vòng kết quả cuối cùng để tất cả người chơi dự đoán kết quả cho từng người chơi, nhưng điều đó đã cắt giảm khá gần với thời gian khi số lượng người tham gia ngày càng lớn hơn (giả sử, khoảng 50).

#include <iostream>
#include <string>
#include <algorithm>
#include "Eigen/Dense"

using Eigen::MatrixXf;
using Eigen::VectorXf;
using Eigen::IOFormat;
using std::max;

void regress(MatrixXf &feats, VectorXf &classes, VectorXf &out, float alpha = 1) {
    MatrixXf featstrans = feats.transpose();
    MatrixXf AtA = featstrans * feats;

    out = (AtA + (MatrixXf::Identity(feats.cols(), feats.cols()) * alpha)).inverse() * featstrans * classes;
}

float classify(VectorXf &weights, VectorXf &feats) {
    return weights.transpose() * feats;
}

size_t predict(MatrixXf &train_data, VectorXf &labels, VectorXf &testitem) {
    VectorXf weights;
    regress(train_data, labels, weights);
    return (classify(weights, testitem) > 0 ? 1 : 0);
}

static const int N = 30;
static const int M = 10;
// use up to N previous rounds worth of data to predict next round
// train on all previous rounds available
size_t predict(MatrixXf &data, size_t prev_iters, size_t n_participants) {
    MatrixXf newdata(data.rows(), data.cols() + max(N, M));
    newdata << MatrixXf::Zero(data.rows(), max(N, M)), data;

    size_t n_samples = std::min(500ul, prev_iters);
    if (n_samples > (8 * max(N, M))) {
        n_samples -= max(N,M);
    }
    size_t oldest_sample = prev_iters - n_samples;
    MatrixXf train_data(n_samples, N + M + 1);
    VectorXf testitem(N + M + 1);
    VectorXf labels(n_samples);
    VectorXf averages = newdata.colwise().mean();
    size_t n_expected_good = 0;
    for (size_t i = 0; i < n_participants; ++i) {
        for (size_t iter = oldest_sample; iter < prev_iters; ++iter) {
            train_data.row(iter - oldest_sample) << newdata.row(i).segment<N>(iter + max(N, M) - N)
                                  , averages.segment<M>(iter + max(N, M) - M).transpose()
                                  , 1; 
        }
        testitem.transpose() << newdata.row(i).segment<N>(prev_iters + max(N, M) - N)
                  , averages.segment<M>(prev_iters + max(N, M) - M).transpose()
                  , 1;
        labels = data.row(i).segment(oldest_sample, n_samples);
        n_expected_good += predict(train_data, labels, testitem);
    }
    return n_expected_good;
}


void fill(MatrixXf &data, std::string &params) {
    size_t pos = 0, end = params.size();
    size_t i = 0, j = 0;
    while (pos < end) {
        switch (params[pos]) {
            case ',':
                i = 0;
                ++j;
                break;
            case '1':
                data(i,j) = 1;
                ++i;
                break;
            case '0':
                data(i,j) = -1;
                ++i;
                break;
            default:
                std::cerr << "Error in input string, unexpected " << params[pos] << " found." << std::endl;
                std::exit(1);
                break;
        }
        ++pos;
    }
}

int main(int argc, char **argv) {
    using namespace std;

    if (argc == 1) {
        cout << "evil" << endl;
        std::exit(0);
    }

    string params(argv[1]);
    size_t n_prev_iters = count(params.begin(), params.end(), ',') + 1;
    size_t n_participants = find(params.begin(), params.end(), ',') - params.begin();

    MatrixXf data(n_participants, n_prev_iters);
    fill(data, params);

    size_t n_expected_good = predict(data, n_prev_iters, n_participants);

    if (n_expected_good > n_participants/2) {
        cout << "evil" << endl;
    } else {
        cout << "good" << endl;
    }
}

Để biên dịch

Lưu mã nguồn trong một tệp có tên ridge_professor.cc, tải xuống thư viện Eigen và giải nén thư mục Eigen được tìm thấy bên trong cùng thư mục với tệp nguồn. Biên dịch với g++ -I. -O3 -ffast-math -o ridge_professor ridge_professor.cc.

Chạy

gọi ridge_profigator.exe và cung cấp đối số khi cần thiết.

Câu hỏi

Vì tôi chưa thể nhận xét ở bất kỳ đâu, tôi sẽ hỏi ở đây: không giới hạn kích thước đối số trên các cửa sổ khiến cho không thể gọi các nhị phân kết quả với toàn bộ lịch sử ở vài trăm lượt? Tôi nghĩ bạn không thể có hơn ~ 9000 ký tự trong cuộc tranh luận ...


Cảm ơn bạn đã thu hút sự chú ý của tôi về điều này . Tôi sẽ tìm ra một số cách để làm cho nó hoạt động nếu nó không hoạt động tốt trong Java. Nếu Java không thể làm điều đó, nghiên cứu cho tôi biết rằng C ++ có thể và tôi sẽ tận dụng cơ hội để học lại C ++. Tôi sẽ trở lại ngay với kết quả kiểm tra.
Rainbolt

Hóa ra, Java không chịu sự giới hạn của dấu nhắc lệnh. Có vẻ như chỉ các lệnh lớn hơn 32k gây ra vấn đề. Đây là bằng chứng của tôi (tôi đã tự viết): docs.google.com/document/d/ . Một lần nữa, tôi thực sự đánh giá cao bạn đưa ra điều này trước khi thử nghiệm bắt đầu vào ngày mai.
Rainbolt

@Rizer Đã có 57 bot và bạn lên kế hoạch cho mỗi lần chạy gồm 1000 vòng. Điều đó sẽ làm cho chuỗi ký tự 57k của bạn (do đó> 32k), phải không?
plannapus

1
@Rizer Tôi nghĩ có thể tốt hơn để kéo dài dòng thời gian thêm một tuần nữa và yêu cầu người tham gia thay đổi chương trình của họ để đọc stdin thay vì sử dụng chuỗi đối số. Sẽ là tầm thường đối với hầu hết các chương trình để thay đổi
dgel

@dgel Dòng thời gian cho thử thách là vô cùng dài, nhưng tôi không muốn thay đổi các quy tắc theo cách mà mọi người phải viết lại câu trả lời của họ. Tôi khá chắc chắn rằng quy tắc tôi đã thêm vào tối qua sẽ chỉ vượt qua một lần gửi và tôi dự định giúp đỡ người đó nếu anh ta đưa chương trình của mình đến điểm mà nó biên dịch.
Rainbolt

6

Quạ

Bởi vì Winchesters ít thú vị hơn nếu không có người bạn này. Anh ta rõ ràng phải đối mặt với cái ác ... trừ khi cần phải chăm sóc một kẻ ác lớn hơn.

package Humans;

public class Crowley extends Human {
public String takeSides(String history) {
    int gd = 0, j=history.length(), comma=0, c=0, z=0;
    while(comma < 2 && j>0)   {
        j--;
        z++;
        if (history.charAt(j) == ',') {
            comma++;
            if(c> z/2) {gd++;}
            z=0;
            c=0;
        } else if (history.charAt(j)=='1') {
            c++;
        } else {
        }
    }
    if(gd == 0){
        return "good";
    } else {
        return "evil";
    }
}}

Tôi nhìn vào hai lượt cuối cùng (0 dấu phẩy cho đến nay và 1 dấu phẩy cho đến nay) và nếu cả hai đều để ác chiến thắng, tôi sẽ bỏ phiếu tốt. Nếu không thì tôi bỏ phiếu ác.


Tôi có được điều này đúng không? Bạn nhìn vào lượt cuối cùng và nếu dưới 50% là phiếu "tốt" thì bạn đứng về phía "tốt" với ác? (Vì tò mò: Bạn có thích tên biến khó hiểu hay đó là một tai nạn?)
Angelo Fuchs

1
@AngeloNeuschitzer Tôi nhìn vào hai lượt cuối cùng (0 dấu phẩy cho đến nay và 1 dấu phẩy cho đến nay) và nếu cả hai đều để ác chiến thắng, tôi sẽ bỏ phiếu tốt. Nếu không thì tôi bỏ phiếu ác. Tôi thích các tên biến ngắn để gõ nếu mã đủ ngắn, mục đích của mã sẽ không bị nhầm lẫn. Tôi không phải là một lập trình viên chuyên nghiệp và đây là lần đầu tiên tôi lập trình bằng java hoặc một cái gì đó mà người khác đã thấy mã trong 6,5 năm. Tôi đã viết điều này để làm mới bộ nhớ của mình. (TLDR họ không khó hiểu với tôi và tôi là người duy nhất tôi thường mã hóa.)
kaine

Để rõ ràng ... Crowley khởi nghiệp như một con người nên anh ta cố tình bắt đầu tốt ... Không hy vọng anh ta sẽ sống tốt trong tất cả các vòng mặc dù ... chết tiệt
kaine
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.