ดีกับความชั่วร้าย


112

ผลลัพธ์ - 19 กรกฎาคม 2014

King of the Hill ปัจจุบันคือMercenaryโดยผู้ใช้Fabigler ! ส่งผลงานต่อไปและผลักเขาออกจากบัลลังก์ของเขา!

คลิกที่นี่เพื่อดูกระดานคะแนน

โปรแกรมที่ส่งในวันที่หรือก่อนวันที่ 19 กรกฎาคม 2014 รวมอยู่ด้วย การส่งอื่น ๆ ทั้งหมดจะรวมอยู่ในการทดลองในอนาคต ผลลัพธ์ใหม่ควรโพสต์เมื่อวันที่ 9 สิงหาคมเพื่อให้คุณมีเวลาเหลือเฟือ


ภาพประกอบที่วาดโดยพี่ชาย ภาพประกอบโดย Chris Rainbolt น้องชายของฉันและบัณฑิตใหม่จากวิทยาลัยศิลปะและการออกแบบ Savannah

บทนำ

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

เกม

การทดลองแต่ละครั้งคุณจะได้รับการจับคู่แบบสุ่มโดยการสุ่มระหว่าง 20 ถึง 30 รายการ การทดลองแต่ละครั้งจะประกอบด้วย 1,000 รอบ ในแต่ละรอบคุณจะถูกส่งผ่านอินพุตและถูกคาดหวังให้สร้างเอาต์พุต ผลลัพธ์ของคุณจะถูกบันทึกและให้คะแนน กระบวนการนี้จะทำซ้ำ 1,000 ครั้ง

อินพุต

คุณจะได้รับการโต้แย้งเดียวที่แสดงถึงคะแนนเสียงที่ผ่านมาของผู้เล่นแต่ละคน รอบถูกคั่นด้วยเครื่องหมายจุลภาค A 0หมายถึงผู้เล่นที่เข้าข้างกับ Evil รอบนั้น A 1หมายถึงผู้เล่นที่เข้าข้างกับ Good ภายในการทดลองผู้เล่นจะอยู่ในลำดับเดียวกันเสมอ คะแนนของคุณจะถูกรวมไว้ แต่ไม่ได้ระบุอย่างชัดเจน ตัวอย่างเช่น:

101100100

ในตัวอย่างนี้มีสามรอบแล้วและผู้เล่นสามคนกำลังแข่งขัน ผู้เล่นคนหนึ่งเข้าข้างดีเสมอ ผู้เล่นสองคนเข้าข้างกับ Evil เสมอ ผู้เล่นสามคนเปลี่ยนจาก Good ในรอบที่ 1 เป็น Evil ในรอบที่ 2 และ 3 หนึ่งในผู้เล่นเหล่านั้นคือคุณ

เอาท์พุต

การส่ง Java

  • ส่งคืนสตริงgoodถ้าคุณต้องการด้านด้วยดี
  • ส่งคืนสตริงevilหากคุณต้องการเข้าข้างกับ Evil

การส่งที่ไม่ใช่ Java

  • ส่งออกสตริงgoodเพื่อ stdout ถ้าคุณต้องการที่จะเข้าข้างกับดี
  • ส่งออกสตริงevilเพื่อ stdout ถ้าคุณต้องการที่จะเข้าข้างกับความชั่วร้าย

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

เกณฑ์การให้คะแนน

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

  • คุณได้รับ 3 คะแนนสำหรับการเข้าข้างส่วนใหญ่ระหว่างรอบ
  • คุณได้รับคะแนน n - 1 สำหรับการเข้าร่วมกับชนกลุ่มน้อยในระหว่างรอบโดยที่ n คือจำนวนครั้งติดต่อกันที่คุณเข้าข้างชนกลุ่มน้อย

คะแนนของคุณจะเป็นค่ามัธยฐานของการทดลอง 5 ครั้ง การทดลองแต่ละครั้งประกอบด้วย 1,000 รอบ

การส่งมอบ

การส่งที่ไม่ใช่ Java

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

  • python Angel.py
    • โปรดทราบว่าอันนี้ไม่มีความหมาย นี่คือรอบที่หนึ่ง! เตรียมพร้อมสำหรับสิ่งนี้
  • python Angel.py 11011,00101,11101,11111,00001,11001,11001

การส่ง Java

คุณต้องส่งชื่อที่ไม่ซ้ำและคลาส Java ที่ขยายคลาส Human นามธรรมที่เขียนด้านล่าง

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

การทดสอบ

หากคุณต้องการที่จะทดสอบการส่งของคุณเองทำตามคำแนะนำที่นี่

หมายเหตุเพิ่มเติม

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

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

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


2
ล้างความคิดเห็นเนื่องจากล้าสมัยแล้วและเมื่อมีการร้องขอจาก OP โปรดแจ้งความคิดเห็นใด ๆ ที่จำเป็นต้องถูกลบทิ้ง
Doorknob

7
ว้าว OP เปลี่ยนชื่อผู้ใช้ของเขา ตกลงดังนั้นผลลัพธ์จะปรากฏเมื่อใด
justhalf

6
@Rainbolt งานนี้ต้องเป็นงานของคนบ้างานสักคนเดียวที่ใช้ความท้าทายนี้! เหตุผลสำหรับจำนวนเงินที่ให้ความสนใจในเรื่องนี้ก็คือความเรียบง่ายของโปรโตคอลและกฎระเบียบที่ทำให้สามารถเข้าถึงได้ในขณะที่ยังช่วยให้ง่ายในการทำงานรายการ TL; DR: ความท้าทายของคุณดีเกินไป! : D
tomsmeding

3
@dgel ฉันจะโพสต์ข้อมูลดิบ, สูงสุด, ต่ำกว่า, ค่าเฉลี่ยและอาจเป็นแผนภูมิเส้นเพื่อให้เราเห็นว่าใครทำได้ดีกว่าเมื่อการแข่งขันลากไป
Rainbolt

6
หนึ่งในพ็อดจบลงด้วย 10 รายการที่โหวตแบบเดียวกันทุกครั้ง ดังนั้นผู้ใช้สองคนจึงจบลงด้วยคะแนนสมบูรณ์แบบหรือ "หนึ่งรอบสั้นของคะแนนสมบูรณ์" ประมาณ 450,000 รายการเดียวกันได้คะแนนประมาณ 1900 ในการทดลองอื่น ๆ คะแนนเฉลี่ยอยู่ใกล้กับปี 2000 เนื่องจากผลลัพธ์ที่ไม่สมดุลอย่างมากฉันจึงตัดสินใจว่าจำนวนที่มีความหมายมากกว่านี้จะเป็นค่ามัธยฐาน ฉันแก้ไขความท้าทายเพื่อให้หลังจากผ่านการทดสอบ 5 ครั้งผู้ชนะจะได้รับการยอมรับจากค่ามัธยฐานสูงสุด หากใครคิดว่าการย้ายจากค่าเฉลี่ยไปสู่ค่ามัธยฐานนั้นไม่ยุติธรรมหรือเป็นทางเลือกที่แย่โปรดแสดงความคิดเห็น
Rainbolt

คำตอบ:


11

ทหารรับจ้าง

เข้าข้างคนที่จ่ายเงินมากที่สุดในรอบสุดท้ายเสมอ

โดยคำนึงถึงว่าคนดีมีรายได้ทางสถิติมากขึ้น

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
นี่คือโพสต์ที่สองที่พูดอะไรเกี่ยวกับเงิน ฉันไม่มีข้อมูลอ้างอิงหรืออะไรบางอย่าง?
Rainbolt

จริง แต่ผู้ชายคนนี้เป็นไอ้เลวร้ายยิ่งกว่านี้อีก ปล่อยเพื่อนของเขาทุก ๆ ทางเพื่อเงินเท่านั้น
fabigler

คำสั่ง switch ของคุณไม่มีคำสั่งส่งคืนสำหรับเคสที่เป็นค่าเริ่มต้นทำให้คำสั่งนั้นไม่คอมไพล์ ฉันเพิ่มแบบสุ่ม
Rainbolt

4
ขอแสดงความยินดี King of the Hill! ฉันไม่เข้าใจว่ารายการนี้ชนะ สนใจที่จะเพิ่มคำอธิบายตอนนี้มันมี 300 รางวัลชื่อเสียงติดอยู่กับมันหรือไม่?
Rainbolt

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

เพียงแค่ไปกับชนกลุ่มน้อยรอบสุดท้ายเพียงเพราะทุกอย่างอื่นเป็นกระแสหลัก

วิ่งเหมือน

ruby hipster.rb

30

Petyr Baelish

คุณไม่มีทางรู้ว่า Petyr Baelish อยู่ฝ่ายใด

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

รายการนี้จะถูกรวมไว้หากจำนวนผู้เล่นเท่ากัน สิ่งนี้ทำให้มั่นใจได้ว่าจะมีคนส่วนใหญ่อยู่เสมอ


28
ในด้านของ Petyr Baelish อย่างชัดเจน
คธูลู

2
@ Kevin มันเต้นแบบบอทเกือบตลอดเวลา มันมักจะได้คะแนน 27ish
cjfaure

3
@Kevin รายการนี้ถูกส่งโดยผู้เขียนของความท้าทาย มันไม่ได้หมายความว่าจะทำได้ดี มันมีอยู่เพื่อให้แน่ใจว่าจะมีคนส่วนใหญ่อยู่เสมอเพราะด้วยจำนวนผู้เล่นที่เท่ากันอาจมีการเสมอกัน
Rainbolt

4
ทำไมโอ้พระเจ้าทำไมคนนี้ถึงได้คะแนนมากที่สุด? มันไม่ยุติธรรมเลย
tomsmeding

3
@tomsmeding ไม่มันเป็นคำพูดจาก Game of Thrones lol
Rainbolt

29

C ++ นักวิทยาศาสตร์ Meta

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

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

หากคุณต้องการที่จะเปิดต่องบแก้ปัญหาเปลี่ยนบรรทัดอ่านไป#if 0#if 1

คอมไพล์ด้วยg++ -O3 -std=c++0x -o MetaScientist MetaScientist.cpp(คุณไม่ต้องการคำเตือนดังนั้นจึงไม่มี-Wall) และทำงานด้วยMetaScientist.exe(อาจรวมถึงการโต้แย้งแน่นอน) ถ้าคุณถามอย่างดีจริงๆฉันสามารถให้ Windows ที่ปฏิบัติการได้

แก้ไข:เห็นได้ชัดว่ารุ่นก่อนหน้าหมดเวลาประมาณ 600 รอบในเกม นี่ไม่ควรทำอย่างนั้น เวลาที่ใช้จะถูกควบคุมโดย#define WINDOW (...)สายการผลิตมากขึ้นช้าลง แต่มองย้อนกลับไป


2
ฉันขอแนะนำให้คุณลองเลือกฝ่ายแพ้ หากคุณสามารถคาดเดาได้อย่างถูกต้องคุณจะได้รับมากกว่า 3 คะแนนต่อรอบ
Kevin

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

1
@ เควินนอกจากนี้ก่อนอื่นฉันต้องการที่จะเห็นว่าสิ่งเหล่านี้ทำอย่างไร (นักวิทยาศาสตร์และนักวิทยาศาสตร์ Meta) เมื่อ Rusher ทำให้เราได้รับสกอร์บอร์ดวันหยุดสุดสัปดาห์นี้ตามที่เขาระบุไว้ในความคิดเห็นต่อ OP Rusher ขอโทษ แต่ฉันขี้เกียจเกินกว่าจะรวบรวมสิ่งของทั้งหมด ... :)
tomsmeding

3
ไม่ต้องห่วง! มันอาจจะไม่ปลอดภัยที่จะเรียกใช้สิ่งเหล่านี้ แค่ให้ฉันไขรหัสของฉันกับคนแปลกหน้า 50 คนทางอินเทอร์เน็ต
Rainbolt

1
@ Kevin แต่นั่นดังนั้นหลาย ! แน่นอนฉันทำได้ แต่ไม่ชอบ ฉันจะดูว่าค่าโดยสารเหล่านี้เป็นอย่างไร
tomsmeding

26

นางฟ้า

ผู้เล่นที่บริสุทธิ์ที่สุดของทั้งหมด

โครงการ

print "good"

คำสั่ง

python Angel.py

22
Python เป็นภาษาที่ดี ดูเหมือนเป็นเรื่องธรรมดาที่ทูตสวรรค์ควรใช้มัน
jpmc26

23
ฉันขอเตือนผู้คนว่างูใหญ่เป็นงูได้ไหม งู
นาย Lister

3
@MrLister ฉันขอเตือนคุณได้ไหมว่าลูซิเฟอร์เป็นทูตสวรรค์ที่ยิ่งใหญ่ก่อนที่พระเจ้าจะขับเขาออกจากสวรรค์?
Zibbobz

1
@Zibbobz ใช่ ... น่าอายจริง ๆ ที่พวกเขาหลุดออกมา พวกเขาสามารถประสบความสำเร็จอย่างมากด้วยกัน
นาย Lister

24

อาร์ทิมิสไก่

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

ในเล่ม 7, แอตแลนติคอมเพล็กซ์ , Artemis Fowlและเป็นโรคทางจิตวิทยา (เรียกว่าแอตแลนติซับซ้อน) ที่บังคับให้เขาต้องทำทุกอย่างในหลายรายการที่ 5 (การพูดการกระทำ ฯลฯ ) เมื่อเขาไม่สามารถทำได้ในหลาย ๆ 5 เขาก็ตื่นตระหนก ฉันทำโดยทั่วไปว่า: ดูว่าดีหรือชั่ว (อคติเจตนา) หารด้วย 5 ได้ไหมถ้าไม่ใช่ทั้งคู่ฉันก็ตกใจและดูว่าอะไรดีกว่า & วิ่งด้วยความตื่นตระหนก


4
เมื่อฉันอ่าน Artemis Fowl ในระดับมัธยมศึกษาตอนต้นมีหนังสือเพียงสองเล่มเท่านั้น มันเป็นเรื่องดีที่ได้เห็นว่าตอนนี้มีอยู่เจ็ดตอนและดิสนีย์กำลังทำให้มันกลายเป็นภาพยนตร์
Rainbolt

1
มีหนังสือ 8 เล่ม
Kyle Kanos

7
ยิ่ง merrier (เว้นแต่คุณกำลังอ่าน The Wheel of Time)
Rainbolt

1
และคุณลืมในของคุณbreak; switch
johnchen902

1
@ johnchen902, @ มนู: ฉันไม่ค่อยมีประสบการณ์เกี่ยวกับ java (ฉันใช้ Fortran90 + และเห็นเฉพาะ java ที่นี่) ดังนั้นข้อผิดพลาดของฉัน ฉันจะซ่อมพวกเขาเมื่อฉันเข้าไปในสำนักงานในอีกหนึ่งชั่วโมง
Kyle Kanos

19

Disparnumerophobic

ตัวเลขแปลก ๆ ที่น่ากลัว

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
ความคิดเห็นทำให้ฉันหัวเราะ / เสียงดัง
phyrfox

17

ไลนัสทับทิม

พยายามที่จะทำให้สับสนนักวิเคราะห์โดยทำลายรูปแบบเสมอ

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

บันทึกเป็นlinus.rbและเรียกใช้ด้วยruby linus.rb


16

BackPacker

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

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

ผู้ติดตาม Crowd

พิจารณาผู้เล่นที่เลือกเสียงข้างมากที่สุดและเลือกคะแนนสุดท้ายของเขา

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

โปรแกรมสะอาดมาก!
Rainbolt

อ๊ะฉันคิดว่าฉันอาจคัดลอกโปรแกรมของคุณเป็นภาษาอื่น
PyRulez

@Rusher ฉันปรับปรุงรหัสและต้องการที่จะเพิ่มเป็นสองรายการหนึ่งที่มีและเป็นหนึ่งในที่ของมันgoWithMajority = true falseไม่เป็นไรหรือฉันต้องเพิ่ม BackPacker อันที่สองสำหรับสิ่งนี้?
Angelo Fuchs

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

1
@ เรนโบลต์ฉันชอบ FrontPacker ของคุณดีกว่าจริง ๆ Lol'd
tomsmeding

15

หมอดู

ยังคงทำงานอยู่ ฉันยังไม่ได้ทดสอบ ฉันแค่อยากจะดูว่า OP คิดว่ามันผิดกฎหรือไม่

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

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

}

หากบอทของคุณทำงานบอทอื่น ๆ ทุกรอบก่อนที่จะตอบจะใช้เวลามากกว่า 1 วินาทีในการตอบไหม
plannapus

@plannapus ฉันจะเดาว่าสมมุติว่าบอทนี้คือคนอื่น ๆ จะทำผิดในด้านของความระมัดระวังและหลีกเลี่ยงสิ่งใดก็ตามที่อยู่ใกล้ 1 วินาทีที่คุ้มค่ากับการรอคอย ฉันคิดว่ามันอาจจะคุ้มค่ากับการส่งและการเข้ามาซึ่งประกอบไปด้วยการรอคอย 0.9 วินาทีก่อนจะกลับมา "ดี" เพียงเพื่อยุ่งกับเขา ที่จริงแล้ว SBoss ได้เอาชนะฉันไปแล้ว: D
scragar

Yahhh! จากนั้นฉันจะต้องขึ้นบัญชีดำบอทนั้นในรหัสของฉัน นั่นน่าผิดหวัง ... ด้วยรายการที่แตกต่างกันในสภาพแวดล้อมที่แตกต่างกันเช่น Python หรือ Perl การโหลดล่ามที่ถูกพิมพ์ซ้ำอาจเพียงพอที่จะทำให้โค้ดนี้เกินขีด จำกัด เวลา
Andris

16
หากคนอื่นทำสิ่งเดียวกันกับสิ่งนี้คุณจะได้รับการวนซ้ำไม่สิ้นสุด
Brilliand

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

15

C ++ นักวิทยาศาสตร์

หนึ่งในนี้พยายามที่จะมีประวัติของสิ่งที่คนส่วนใหญ่เลือกที่จะต่อรอบในwave( majority()ให้ทางเลือกของเสียงข้างมากในรอบ) พอดีกับคลื่นกับข้อมูลที่มีความยาวคลื่นและเฟส2*period phaseดังนั้นให้0,1,1,1,0,1,0,1,1,1,0,0,0,1,0มันเลือกperiod=3, phase=5( maxat=={3,5}): 9 3 11 5 5 3 5 7 9 7 7 7 7 7 7คะแนนกลายเป็น มันวนรอบช่วงเวลาที่เป็นไปได้ทั้งหมดและหากในช่วงเวลานั้นคะแนนสูงกว่าค่าสูงสุดในปัจจุบันซึ่งจะเก็บคะแนน{period,phase}ที่เกิดขึ้น

จากนั้นจะประมาณคลื่นที่พบในรอบถัดไปและรับเสียงส่วนใหญ่ที่คาดการณ์ไว้

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

คอมไพล์ด้วยg++ -O3 -std=c++0x -o Scientist Scientist.cpp(คุณไม่ต้องการคำเตือนดังนั้นจึงไม่มี-Wall) และทำงานด้วยScientist.exe(อาจรวมถึงการโต้แย้งแน่นอน) ถ้าคุณถามอย่างดีจริงๆฉันสามารถให้ Windows ที่ปฏิบัติการได้

โอ้และไม่กล้ายุ่งกับรูปแบบการป้อนข้อมูล มันจะทำสิ่งแปลก ๆ

แก้ไข:เห็นได้ชัดว่ารุ่นก่อนหน้าหมดเวลาประมาณ 600 รอบในเกม นี่ไม่ควรทำอย่างนั้น เวลาที่ใช้จะถูกควบคุมโดย#define WINDOW (...)สายการผลิตมากขึ้นช้าลง แต่มองย้อนกลับไป


8
การดาวน์โหลดไฟล์โปรแกรมที่เขียนโดยคนแปลกหน้ากว่า 60 คนบนอินเทอร์เน็ตดูเหมือนจะเป็นความคิดที่ไม่ดี
Rainbolt

@Rusher ฉันเห็นด้วยทั้งหมด หากคุณต้องการมีปัญหานั่นคือขั้นตอนที่หนึ่งในคู่มือ "for dummies" ข้อเสนอของฉันยังคงอยู่ :)
ย้ำ

2
เตรียมพร้อมสำหรับการคอมไพล์ (และแข่งขัน) นี้
Rainbolt

14

นักวิ่งรหัส

ดังนั้นเพื่อให้สิ่งที่น่าสนใจฉันสร้างสคริปต์เพื่อดาวน์โหลดรหัสจากคำตอบที่โพสต์โดยอัตโนมัติรวบรวมถ้าจำเป็นแล้วเรียกใช้การแก้ไขทั้งหมดตามกฎ ด้วยวิธีนี้ผู้คนสามารถตรวจสอบวิธีการที่พวกเขากำลังทำ เพียงบันทึกสคริปต์นี้เพื่อ run_all.py (ต้องใช้ BeautifulSoup) จากนั้น:

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

บางสิ่ง:

  1. ถ้าคุณต้องการที่จะเพิ่มการสนับสนุนสำหรับภาษาอื่น ๆ def submission_type(lang)หรือหรือลบการสนับสนุนสำหรับบางคนเห็น
  2. การขยายสคริปต์ควรง่ายพอสมควรแม้สำหรับภาษาที่ต้องมีการรวบรวม (ดูCPPSubmission) ประเภทภาษาถูกคว้าจากเมตาแท็กโค้ด< !-- language: lang-java -- >ดังนั้นอย่าลืมเพิ่มถ้าคุณต้องการให้โค้ดของคุณทำงาน (ลบช่องว่างเพิ่มเติมก่อนและหลัง <>) UPDATE : ขณะนี้มีการอนุมานขั้นพื้นฐานบางอย่างเพื่อพยายามตรวจหาภาษาหากไม่ได้กำหนดไว้
  3. หากรหัสของคุณล้มเหลวในการทำงานเลยหรือไม่สำเร็จภายในเวลาที่กำหนดรหัสนั้นจะถูกเพิ่มเข้าไปblacklist.textและจะถูกลบออกจากการทดลองในอนาคตโดยอัตโนมัติ หากคุณแก้ไขรหัสของคุณเพียงลบรายการของคุณออกจากบัญชีดำและเรียกใช้getใหม่

ภาษาที่รองรับในปัจจุบัน:

 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
}

โดยไม่ต้องกังวลใจเพิ่มเติม:

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

ทำไมไม่มีภาษา Fortran ??
Kyle Kanos

@KyleKanos - ฉันเพิ่มการสนับสนุนแล้วจะอัปเดตรหัสในไม่ช้า
WhatAWorld

เย้! ฉัน (sorta) ทำงานอย่างหนักกับการยอม Fortran ของฉัน & Rusher ไม่สามารถทำงานได้ดังนั้นฉันต้องการให้ใครซักคนได้รับมัน :)
Kyle Kanos

1
@Rusher: ฉันเห็นด้วยกับ PeterTaylor ในเรื่องนี้: การเน้นไวยากรณ์เนื่องจากการแก้ไขที่แนะนำเท่านั้นควรถูกปฏิเสธ ควรใช้การแก้ไขเพื่อการแก้ไขที่สำคัญไม่ใช่สิ่งเล็กน้อย
Kyle Kanos

1
คุณสมควรได้รับตัวแทนจากเรื่องนี้ แต่เนื่องจากนี่ไม่ใช่คำตอบที่แน่นอนสำหรับคำถาม (และอาจได้รับประโยชน์จากชุมชนที่เพิ่มเนื้อหาสำหรับภาษาอื่น ๆ ) ฉันคิดว่านี่น่าจะเป็น wiki ชุมชนทางเทคนิค
Martin Ender

13

จิตใจที่สวยงาม, ทับทิม

ทำให้การตัดสินใจขึ้นอยู่กับรูปแบบของความสำคัญที่น่าสงสัยในการเป็นตัวแทนของรอบสุดท้าย

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

วิ่งเหมือน

ruby beautiful-mind.rb

13

ลื้อ

โปรแกรมที่เชื่อโชคลางที่เชื่อในเครื่องหมายและสิ่งมหัศจรรย์

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

รันด้วย:

lua Piustitious.lua

ตามด้วยอินพุต


11

Winchesters

แซมและคณบดีเป็นคนดี (ส่วนใหญ่แล้ว)

package Humans;

public class TheWinchesters extends Human {

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

}

คุณแน่ใจหรือว่า9:1อัตราส่วนที่ถูกต้อง? บางทีเราควรทำdata miningและรับอัตราส่วนที่แม่นยำยิ่งขึ้น?
recursion.ninja

1
@awashburn ฉันเริ่มดูเรื่องเหนือธรรมชาติ 2 เดือนที่ผ่านมา (ตอนนี้ติดอยู่ในฤดูกาลที่ 9) และ9:1ดูเหมือนว่าฉันกับฉัน;)
CommonGuy

10

นักสถิติ

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
บรรทัดสุดท้ายที่สองนั้นยอดเยี่ยมมาก
cjfaure

5
@Undeserved แทนที่จะเป็นMath.ceil(Math.random()-Math.random())คุณก็สามารถทำได้เช่นMath.round(Math.random())กัน
tomsmeding

10

R บอทเบย์ค่อนข้าง

ใช้ตารางความถี่สำหรับผู้ใช้แต่ละคนเป็นความน่าจะเป็นก่อนหน้านี้ของผู้ใช้รายอื่น

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

เรียกใช้Rscript BayesianBot.Rตามด้วยอินพุต

แก้ไข : เพียงชี้แจงสิ่งที่กำลังทำนี่คือขั้นตอนโดยป้อนตัวอย่าง:

> 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

จากนั้นบรรทัดที่เริ่มต้นโดยresult<-สำหรับผู้เล่นแต่ละคนจะสุ่มเลือก 0 หรือ 1 โดยใช้ตารางสุดท้ายนี้เป็นน้ำหนัก (เช่นสำหรับผู้เล่น 1 ความน่าจะเป็นที่จะเลือก 0 คือ 2 / 7th ของการเลือก 1 5 / 7th เป็นต้น) มันเลือกผลลัพธ์หนึ่งรายการสำหรับผู้เล่นแต่ละคน / คอลัมน์และในที่สุดก็ส่งกลับหมายเลขที่สิ้นสุดแล้วว่าเป็นเรื่องธรรมดาที่สุด


10

สวิส

ค้ำจุนความเป็นกลางเสมอ ถึงวาระที่จะไม่ชนะ

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

ฉันไม่ได้เขียนสิ่งนี้!
Rainbolt

นั่นคือการประชด ความเป็นกลางไม่เคยชนะ
fabigler

2
@Rusher อ่าฉันเข้าใจแล้วตอนนี้: D
fabigler

1
มันไม่ได้คอมไพล์ด้วยเซมิโคลอนที่หายไป
Paŭlo Ebermann

9

HAL 9000

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

แก้ไข:นี่อาจจะเหมาะกว่าสำหรับ HAL 9000 แต่ระวังด้วย! มันชั่วร้ายมาก ฉันแนะนำcdให้ล้างไดเรกทอรีก่อนเรียกใช้

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

วิธีนี้จะลบไฟล์หนึ่งไฟล์cwdสำหรับแต่ละการเรียก!

การร้องขอไม่ชัดเจน:

ใน M $

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

D:>hal_9000.pl
evil

ใน * ระวัง

[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 ~]$

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

@Rusher Done;)
core1024

9

ความประสงค์ของคนส่วนใหญ่

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

บันทึกเป็นWotM.pyเรียกใช้python3 WotM.pyตามด้วยอินพุต

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


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

นั่นมันทำให้ฉันซ้ำซ้อน : D เปลี่ยนของฉันเป็นชนกลุ่มน้อย
Martin Ender

@Rusher เพิ่มคำสั่ง นั่นคือสิ่งที่คุณกำลังมองหา?
isaacg

@isaacg สมบูรณ์แบบ!
Rainbolt

1
ฉันคำนวณการจัดอันดับโดยเฉลี่ยจากคะแนนในกระดานคะแนนและรายการนี้ชนะโดยการวัดนั้น
Brilliand

9

Alan Shearer

ทำซ้ำในสิ่งที่คนที่เขานั่งถัดจากพูดไป หากบุคคลนั้นผิดพลาดเขาจะย้ายไปยังบุคคลถัดไปและทำซ้ำสิ่งที่พวกเขาพูดแทน

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

คุณอ้างอิงตัวแปรที่เรียกว่าlastRoundก่อนที่คุณจะประกาศ นอกจากนี้คุณยังเพิ่มวงเล็บในทั้งหมดของคุณString.lengthแต่มันไม่ใช่ฟังก์ชั่น คุณช่วยนำเสนอของคุณไปยังจุดที่จะรวบรวม?
Rainbolt

@Rusher - เสร็จแล้ว :)
Algy Taylor

@Algy: lastRound.lengthยังคงเข้าถึง (ในครั้งแรกถ้า) ก่อนที่จะlastRoundมีการประกาศ (ในกรณีที่เป็นอย่างอื่น) โปรดลองรวบรวม (และอาจเรียกใช้) โค้ดของคุณก่อนส่งที่นี่
Paŭlo Ebermann

@ PaŭloEbermann - ขอโทษฉันไม่ได้อยู่ในสภาพแวดล้อมที่ฉันสามารถเรียกใช้ - แก้ไขได้แม้ว่า
Algy Taylor

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

8

ต่อมาคือ Evil, JavaScript ( node.js )

วัดระยะเวลาระหว่างการประหารชีวิต หากความแตกต่างของเวลามากกว่าครั้งที่แล้วมันจะต้องเป็นความชั่วร้าย เป็นอย่างอื่นดี

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

ทำงานด้วย: node laterisevil.js


8

ตัวค้นหารูปแบบ, Python

มองหารูปแบบที่เกิดซ้ำและหากไม่สามารถหาได้ให้ไปที่ส่วนใหญ่

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

ทำงานด้วย

python3 pattern_finder.py

1
ฉันรักรหัสนี้มากเมื่อฉันเรียกใช้มันจะได้รับ 3000 แต้มอย่างใด
Realdeo

8

The Turncoat

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

package Humans;

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

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

หลังจากเขียนสิ่งนี้ฉันรู้ว่าเนื่องจากรายการที่อยู่บนพื้นฐานของการวิเคราะห์ทางสถิติโมเมนตัมจะทำให้คนส่วนใหญ่เปลี่ยนข้างน้อยลงเมื่อรอบเสร็จสมบูรณ์มากขึ้น ดังนั้น Lazy Turncoat

ขี้เกียจ Turncoat

Lazy Turncoat เริ่มต้นเหมือน Turncoat แต่เมื่อผ่านไปเขาก็จะกลายเป็นคนขี้เกียจและคนขี้เกียจเพื่อสลับไปอีกด้านหนึ่ง

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
Lazy Turncoat นั้นยอดเยี่ยมมาก!
Angelo Fuchs

ฉันรวมทั้งถ้าคุณไม่รังเกียจ
Rainbolt

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

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

8

นักเขียนชีวประวัติ 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]

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

บันทึกเป็นbiographer.rbเรียกใช้เป็นruby biographer.rb

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

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


8

ผู้ทรยศ

ยูดาสเป็นคนดีมาก มันน่าเสียดายที่เขาจะทรยศคนดีให้สักสองสามเพนนี

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
นี่เป็นเพียงการลงคะแนนเสียงที่ชั่วร้ายหากมีผู้เข้าร่วมมากพอคุณอาจต้องการลบ,ออกhistoryมากยิ่งขึ้นดังนั้นเมื่อ Rusher กำลังจะแบ่งเกมออกเป็นกลุ่ม
Angelo Fuchs

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

หากคุณรู้วิธีส่งอาร์กิวเมนต์ตัวอักษร 60000 ให้กระบวนการใน Windows แจ้งให้เราทราบ มิฉะนั้นขออภัยที่ทำให้ข้อความของคุณยุ่งและขอบคุณสำหรับการแก้ไข! ฉันไม่ได้คาดหวังว่าจะได้รับผลงานมากมาย
Rainbolt

7

นักพนันที่ล้มเหลว (Python)

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

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  

การใช้

สำหรับรอบแรก:

python gambler.py

และหลังจากนั้น:

python gambler.py 101,100,001 etc.

4
ฉันชอบที่คุณแน่ใจเกี่ยวกับรหัสของคุณใช่ไหม? : P
IEatBagels

7

เซลลูล่าร์อัตโนมัติ

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

โปรดยกโทษให้กับความผิดพลาดใด ๆ ซึ่งถูกทุบในช่วงเวลาอาหารกลางวันของฉัน ;)

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
ฉันลบบรรทัดการพิมพ์ออกจากรหัสเพื่อทำการทดสอบ .. รายการ Java จำเป็นต้องส่งคืนสิ่งที่ดีหรือไม่ดีเท่านั้นไม่ใช่พิมพ์
Rainbolt

7

ศาสตราจารย์สันเขา

ฉันหวังว่าการใช้ห้องสมุดจะได้รับอนุญาตไม่รู้สึกอยากทำสิ่งนี้หากไม่มีหนึ่ง =)

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

เพื่อรวบรวม

บันทึกซอร์สโค้ดในไฟล์ชื่อridge_professor.ccดาวน์โหลดไลบรารีEigenและคลายซิปโฟลเดอร์ Eigen ที่พบภายในเข้าไปในโฟลเดอร์เดียวกับไฟล์ต้นฉบับ g++ -I. -O3 -ffast-math -o ridge_professor ridge_professor.ccคอมไพล์ด้วย

วิ่ง

โทร ridge_professor.exe และจัดหาอาร์กิวเมนต์ตามต้องการ

คำถาม

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


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

ตามที่ปรากฎว่า Java ไม่ได้อยู่ภายใต้ข้อ จำกัด ของพรอมต์คำสั่ง ปรากฏว่าคำสั่งที่ใหญ่กว่า 32k เท่านั้นทำให้เกิดปัญหา นี่คือหลักฐานของฉัน (ฉันเขียนด้วยตัวเอง): docs.google.co.th/document/d/… . ฉันขอขอบคุณที่คุณนำเรื่องนี้ขึ้นมาก่อนที่การทดลองจะเริ่มในวันพรุ่งนี้
Rainbolt

@Rusher มีอยู่แล้ว 57 บอทและคุณวางแผนในการวิ่งแต่ละครั้งซึ่งประกอบด้วย 1,000 รอบ นั่นจะทำให้สตริง 57k ของคุณ (ดังนั้น> 32k) ใช่ไหม?
plannapus

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

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

6

ลี่ย์

เพราะ Winchesters นั้นน่าสนใจน้อยกว่าถ้าไม่มีเพื่อนคนนี้ เห็นได้ชัดว่าเขาเข้าข้างชั่ว ... เว้นแต่จะต้องดูแลความชั่วที่ใหญ่กว่า

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

ฉันดูสองรอบสุดท้าย (0 คอมม่าจนถึง 1 คอมม่า) และหากทั้งคู่ปล่อยให้ชนะอย่างชั่วร้ายฉันก็โหวตดี มิฉะนั้นฉันจะลงคะแนนความชั่วร้าย


ฉันจะได้รับสิทธินี้หรือไม่? คุณดูที่เทิร์นสุดท้ายและถ้าน้อยกว่า 50% เป็นคะแนน "ดี" คุณเข้าข้าง "ดี" กับความชั่วร้ายอีกไหม? (ออกจากความอยากรู้: คุณชอบชื่อตัวแปรลับหรือเป็นอุบัติเหตุหรือไม่)
Angelo Fuchs

1
@AngeloNeuschitzer ฉันดูสองรอบสุดท้าย (0 คอมม่าจนถึง 1 คอมม่า) และถ้าทั้งคู่ปล่อยให้ชนะอย่างชั่วร้ายฉันลงคะแนนได้ดี มิฉะนั้นฉันจะลงคะแนนความชั่วร้าย ฉันชอบชื่อตัวแปรที่สั้นในการพิมพ์ถ้ารหัสสั้นพอที่วัตถุประสงค์ของรหัสจะไม่สับสน ฉันไม่ใช่โปรแกรมเมอร์มืออาชีพและนี่เป็นครั้งแรกที่ฉันได้เขียนโปรแกรมด้วยจาวาหรือสิ่งที่คนอื่นเห็นรหัสใน 6.5 ปี ฉันเขียนสิ่งนี้เพื่อรีเฟรชหน่วยความจำของฉัน (TLDR ไม่ใช่รหัสลับสำหรับฉันและฉันเป็นรหัสเดียวที่ฉันมักจะใช้)
kaine

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