কোড রানার
সুতরাং, বিষয়গুলিকে আকর্ষণীয় করে তোলার জন্য, আমি প্রতিটি পোস্ট করা উত্তর থেকে স্বয়ংক্রিয়ভাবে কোড ডাউনলোড করতে, প্রয়োজনে সংকলন করতে, এবং তারপরে নিয়ম অনুসারে সমস্ত সমাধান চালানোর জন্য একটি স্ক্রিপ্ট তৈরি করেছি। এইভাবে, লোকেরা কীভাবে করছে তা পরীক্ষা করতে পারে। এই স্ক্রিপ্টটি চালানোর জন্য সংরক্ষণ করুন_আল.পি (বিউটিফুলসপ প্রয়োজন) এবং তারপরে:
usage:
To get the latest code: 'python run_all.py get'
To run the submissions: 'python run_all.py run <optional num_runs>'
কিছু জিনিস:
- আপনি যদি আরও ভাষার জন্য সমর্থন যুক্ত করতে চান বা বিকল্পভাবে কিছুটির জন্য সমর্থন সরাতে চান তবে দেখুন
def submission_type(lang)
।
- স্ক্রিপ্টটি প্রসারিত করা মোটামুটি সহজ হওয়া উচিত, এমনকী ভাষাগুলির জন্য যা সংকলনের প্রয়োজন (দেখুন
CPPSubmission
)। ভাষা টাইপটি মেটা কোড ট্যাগ থেকে ধরা হয়েছে< !-- language: lang-java -- >
, সুতরাং আপনি যদি নিজের কোডটি চালিত করতে চান তবে এটি যোগ করার বিষয়টি নিশ্চিত করুন (<> এর আগে এবং পরে অতিরিক্ত স্থান সরিয়ে ফেলুন)।
আপডেট : ভাষাটি সংজ্ঞায়িত না হলে এখন চেষ্টা এবং সনাক্ত করার জন্য কিছু চূড়ান্ত বুনিয়াদী অনুক্রম রয়েছে।
- যদি আপনার কোডটি মোটেও চালাতে ব্যর্থ হয় বা নির্ধারিত সময়ের মধ্যে শেষ করতে ব্যর্থ হয় তবে এটি এতে যুক্ত হবে
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