danielmaxx avatar danielmaxx committed 9603c8f

CEIDEC 2012 creado!

--
danielmaxx

Comments (0)

Files changed (14)

+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+import judge_tools.test_driver as jtest
+
+languages = {
+  "C":  jtest.Language(
+    name = "C",
+    extension = "c",
+    source_name = "{directory}-{solution}.{extension}",
+    executable_name = "{directory}-{solution}.exe",
+    compile_script = [["gcc", "-O2", "-o", "{executable}", "{source}"]],
+    execute_script = [["./{executable}"]]),
+
+  "C++":  jtest.Language(
+    name = "C++",
+    extension = "cpp",
+    source_name = "{directory}-{solution}.{extension}",
+    executable_name = "{directory}-{solution}.exe",
+    compile_script = [["g++", "-O2", "-o", "{executable}", "{source}"]],
+    execute_script = [["./{executable}"]]),
+
+  "Java":  jtest.Language(
+    name = "Java",
+    extension = "java",
+    source_name = "{directory}-{solution}.{extension}",
+    executable_name = "Main.class",
+    compile_script = [["javac", "-g:none", "{source}"]],
+    execute_script = [["java", "-server", "-Xss8m", "-Xmx512m", "Main", "{input}", "{output}"]]),
+
+  "python2":  jtest.Language(
+    name = "python2",
+    extension = "py2",
+    source_name = "{directory}-{solution}.{extension}",
+    execute_script = [["python2",  "{source}"]]),
+
+  "python3":  jtest.Language(
+    name = "python3",
+    extension = "py3",
+    source_name = "{directory}-{solution}.{extension}",
+    execute_script = [["python3",  "{source}"]]),
+}
+
+problems = {
+  "prison": jtest.Problem(
+    name = "prison",
+    directory = "prison",
+    generator = [["./generator-prison.py", "{problem}.in"]],
+    validator = [["./validator-prison.py", "{problem}.in"]],
+    valid_solution = jtest.Solution(
+      name = "prison",
+      language = languages["C++"],
+      redirect_stdin = True,
+      redirect_stdout = True),
+    test_solutions = (jtest.Solution(
+        name = "prison-zyx",
+        language = languages["C++"],
+        redirect_stdin = True,
+        redirect_stdout = True),
+    )),
+
+  "juice": jtest.Problem(
+    # Todo lo que diga {problem} se sustituye por esto.
+    name = "juice",
+
+    # No hace falta problems/, se incluye por defecto.
+    directory = "juice",
+
+    # Este generará un archivo llamado bed-div2.in en data/.
+    generator = [["./generator-juice.py", "{problem}.in"]],
+
+    # Si no hay validador sólo emite un warning. Pero se vería como esto.
+    validator = [["./validator-juice.py", "{problem}.in"]],
+
+    valid_solution = jtest.Solution(
+      name = "juice-emiliot",
+      language = languages["C++"],
+      redirect_stdin = True,
+      redirect_stdout = True),
+    test_solutions = (
+      # Aquí pones más objetos jtest.Solution, se construyen de igual manera
+      # que el anterior. Mientras no tengas el tester te muestra un warning.
+      jtest.Solution(
+        name = "juice-danielmaxx",
+        language = languages["C++"],
+        redirect_stdin = True,
+        redirect_stdout = True),
+      jtest.Solution(
+        name = "juice-zyx",
+        language = languages["C++"],
+        redirect_stdin = True,
+        redirect_stdout = True),
+    )),
+
+  "bankruptcy": jtest.Problem(
+    name = "bankruptcy",
+    directory = "bankruptcy",
+    generator = [["./generator-bankruptcy.py", "{problem}.in"]],
+    validator = [["./validator-bankruptcy.py", "{problem}.in"]],
+    valid_solution = jtest.Solution(
+      name = "bankruptcy-emiliot",
+      language = languages["C++"],
+      redirect_stdin = True,
+      redirect_stdout = True),
+    test_solutions = (
+      jtest.Solution(
+        name = "bankruptcy-danielmaxx",
+        language = languages["C++"],
+        redirect_stdin = True,
+        redirect_stdout = True),
+      jtest.Solution(
+        name = "bankruptcy-zyx",
+        language = languages["C++"],
+        redirect_stdin = True,
+        redirect_stdout = True),        
+    )),
+    
+  "sherlock": jtest.Problem(
+    name = "sherlock",
+    directory = "sherlock",
+    generator = [["./generator-sherlock.py", "{problem}.in"]],
+    validator = [["./validator-sherlock.py", "{problem}.in"]],
+    valid_solution = jtest.Solution(
+      name = "sherlock-emiliot",
+      language = languages["C++"],
+      redirect_stdin = True,
+      redirect_stdout = True),
+    test_solutions = (
+      jtest.Solution(
+        name = "sherlock-danielmaxx",
+        language = languages["C++"],
+        redirect_stdin = True,
+        redirect_stdout = True),
+    )),
+
+}
+jtest.test_problems(problems)

judge_tools/judge_tools/__init__.py

+# -*- coding: utf-8 -*-

judge_tools/judge_tools/case_count_generator.py

+# -*- coding: utf-8 -*-
+
+# Class used to store a file generator to append to the output file.
+class _TestCaseFile:
+  # Initialize the generator with the name of the file to append.
+  def __init__(self,*, input_file):
+    self.input_file = input_file
+
+  # Return the number of test cases inside the file.
+  def case_count(self):
+    try:
+      # Open the file and use the first line as test case count.
+      input = open(self.input_file, "rt")
+      return int(input.readline())
+    finally:
+      input.close()
+
+  # Run the generator and write all test cases to the specified output file.
+  def run(self, output):
+    try:
+      # Append all lines except the first one to the output file.
+      input = open(self.input_file, "rt")
+      for line in input.readlines()[1:]:
+        output.write(line)
+    finally:
+      input.close()
+
+# Class used to store a function to generate test cases.
+class _TestCaseFunction:
+  # Initialize the generator with the specified function and count.
+  def __init__(self, *, function, count):
+    self.function = function
+    self.count = count
+
+  # Return the number of test cases to generate.
+  def case_count(self):
+    return self.count
+
+  # Run the generator and write all test cases to the specified output file.
+  def run(self, output):
+    # Call the generator function as many times at it was specified, using the
+    # specified output file and giving the index to each call.
+    for index in range(self.count):
+      self.function(index, output)
+
+# List of generators to run when the generate_cases function is called.
+_generators = []
+
+# Add a file to the list of case files to append.
+def add_file(*, file):
+  _generators.append(_TestCaseFile(input_file = file))
+
+# Add a function generator to the list of generators.
+def add_function(*, f, n):
+  _generators.append(_TestCaseFunction(function = f, count = n))
+
+# Generate all cases and write them to the specified output file.
+def generate_cases(*, output):
+  # Write the case count at the begining of the file, the run all generators
+  # to the specified output file.
+  count = sum(generator.case_count() for generator in _generators)
+  output.write("{count}\n".format(count = count))
+  for generator in _generators: generator.run(output)
+

judge_tools/judge_tools/file_case_generator.py

+# -*- coding: utf-8 -*-
+import os
+import shutil
+
+# List of generators to run when the generate_cases function is called,
+# and counter used to number the input files.
+_generators = []
+_case_counter = 1
+
+# Class used to store a file generator to append to the output file.
+class _TestCaseFile:
+  # Initialize the generator with the name of the file to append.
+  def __init__(self, *, input_file):
+    self.input_file = input_file
+
+  def _copy_file(self, stem, dir, file_path):
+    # Generate the filename for the input file and increase the counter.
+    # Then, copy the file to the output directory.
+    global _case_counter
+    number, _case_counter = _case_counter, _case_counter + 1
+    output_filename = "{stem}.in.{n}".format(stem = stem, n = number)
+    output_path = os.path.normpath(os.path.join(dir, output_filename))
+    shutil.copyfile(file_path, output_path)
+
+  # Run the generator and write all test cases to the specified output file.
+  def run(self, stem, dir):
+    # Check if the filename points to a file or a directory.
+    if os.path.isfile(self.input_file):
+      # If a file was specified, copy it to the output directory.
+      self._copy_file(stem, dir, self.input_file)
+    elif os.path.isdir(self.input_file):
+      # If a directory was specified, copy each file into it to the output directory.
+      for dirpath, dirnames, filenames in os.walk(self.input_file):
+        for filename in filenames:
+          # Generate the complete path to the file and copy it.
+          file_path = os.path.normpath(os.path.join(dirpath, filename))
+          self._copy_file(stem, dir, file_path)
+
+# Class used to store a function to generate test cases.
+class _TestCaseFunction:
+  # Initialize the generator with the specified function and count.
+  def __init__(self, *, function, count):
+    self.function = function
+    self.count = count
+
+  # Run the generator and write all test cases to the specified output file.
+  def run(self, stem, dir):
+    # Call the generator function as many times at it was specified, with a
+    # different output file each time and giving the index to each call.
+    for index in range(self.count):
+      # Generate the filename for the input file and increase the counter.
+      global _case_counter
+      number, _case_counter = _case_counter, _case_counter + 1
+      output_filename = "{stem}.in.{n}".format(stem = stem, n = number)
+      output_path = os.path.normpath(os.path.join(dir, output_filename))
+
+      # Open the output file and make the function write in it.
+      output = open(output_path, "wt")
+      self.function(index, output)
+      output.close()
+
+# Add a file to the list of case files to append.
+def add_file(*, file):
+  _generators.append(_TestCaseFile(input_file = file))
+
+# Add a function generator to the list of generators.
+def add_function(*, f, n = 1):
+  _generators.append(_TestCaseFunction(function = f, count = n))
+
+# Generate all cases and write them to the specified output file.
+def generate_cases(*, stem, dir):
+  # Cleanse the specified directory and recreate it empty.
+  if os.path.exists(dir):
+    shutil.rmtree(dir)
+  os.makedirs(dir)
+
+  # Write the case count at the begining of the file, the run all generators
+  # to the specified output file.
+  global _case_counter
+  _case_counter = 1
+  for generator in _generators: generator.run(stem, dir)

judge_tools/judge_tools/input_validator.py

+# -*- coding: utf-8 -*-
+
+import re
+import sys
+
+# Class used for validate some input file.
+class _FormatValidator:
+  # Open the specified file and reset line counter.
+  def __init__(self, filename):
+    self.line_number = 0
+    self.file = open(filename, "rt")
+
+  # Close the opened file on destruction.
+  def __del__(self):
+    self.file.close()
+
+  # Read a line from the file and validate that it follows some regular expression.
+  def readline(self, regexp, *, desc = None):
+    # Read a line and increase line counter.
+    line = self.file.readline()
+    self.line_number += 1
+
+    # Format an error message and validate the regexp, the return the line read.
+    error_msg = "Line {line} does not match regexp '{regexp}'.".format(line = repr(line), regexp = regexp) if not desc \
+      else "Line {line} does not match regexp '{regexp}' for: {desc}.".format(line = repr(line), regexp = regexp, desc = desc)
+    self.check(re.match(regexp, line), error_msg)
+    return line
+
+  # Check some condition, if the condition does not hold,
+  # print an error message and exit.
+  def check(self, valid_flag, error_msg):
+    if not valid_flag:
+      print("Error at line #{line}: {error}.".format(line = self.line_number, error = error_msg), file = sys.stderr)
+      sys.exit(1)
+
+# Interface function used to create a format validator.
+def create_validator(filename):
+  return _FormatValidator(filename)

judge_tools/judge_tools/random_utils.py

+# -*- coding: utf-8 -*-
+import heapq
+
+# Import basic functions from the random module.
+from random import choice, random, sample, seed, shuffle, uniform
+import random
+
+# Common characters groups used to generate subsets.
+DIGITS = "".join(chr(c) for c in range(ord('0'), ord('9') + 1))
+UPPERCASE = "".join(chr(c) for c in range(ord('A'), ord('Z') + 1))
+LOWERCASE = "".join(chr(c) for c in range(ord('a'), ord('z') + 1))
+
+# Return a random integer between min_value and max_value, inclusive.
+def randrange(min_value, max_value):
+  return random.randrange(min_value, max_value + 1)
+
+# Return a subset with k elements from the specified population,
+# where order does not matter.
+def unordered_subset(population, k):
+  return sorted(random.sample(population, k))
+
+# Return a subset with k elements from the specified population,
+# where order does matter.
+def ordered_subset(population, k):
+  return random.sample(population, k)
+
+# Return a multiset with k elements from the specified population,
+# where order does matter.
+def ordered_multiset(population, k):
+  return [random.choice(population) for _ in range(k)]
+
+# Return a random tree with n nodes, using parent link representation.
+# The tree generation is done using Prufer's sequence.
+def generate_tree(n):
+  # The Prufer's sequence is invalid for tree with only one node,
+  # in this case return the only possible tree.
+  if n == 1: return []
+
+  # Generate a random Prufer's sequence for a tree with n nodes.
+  prufer = [randrange(0, n - 1) for _ in range(n - 2)]
+  degree = [prufer.count(i) + 1 for i in range(n)]
+
+  # Initialize a sorted queue to hold nodes with degree one, and list
+  # with edges for the constructed tree.
+  edges = []
+  fringe = [i for i, x in enumerate(degree) if x == 1]
+  heapq.heapify(fringe)
+
+  # Process all elements in the Prufer's sequence.
+  for x in prufer:
+    # Get the next unmatched leaf and push the new edge.
+    node = heapq.heappop(fringe)
+    edges.append((x, node))
+
+    # Update nodes degrees and push into the fringe those that
+    # became leafs (i.e.: have degree 1).
+    degree[x] -= 1
+    degree[node] -= 1
+    if degree[x] == 1:
+      heapq.heappush(fringe, x)
+
+  # Get the pair or remaining nodes, add the last edge and return.
+  a = heapq.heappop(fringe)
+  b = heapq.heappop(fringe)
+  edges.append((a, b))
+  return edges

judge_tools/judge_tools/sentinel_generator.py

+# -*- coding: utf-8 -*-
+
+# Class used to store a file generator to append to the output file.
+class _TestCaseFile:
+  # Initialize the generator with the name of the file to append.
+  def __init__(self,*, input_file):
+    self.input_file = input_file
+
+  # Run the generator and write all test cases to the specified output file.
+  def run(self, output, sentinel):
+    try:
+      # Append all lines to the output file, except the last one if
+      # there is a sentinel.
+      input = open(self.input_file, "rt")
+      lines = input.readlines()
+      if sentinel: lines.pop()
+      for line in lines: output.write(line)
+    finally:
+      input.close()
+
+# Class used to store a function to generate test cases.
+class _TestCaseFunction:
+  # Initialize the generator with the specified function and count.
+  def __init__(self, *, function, count):
+    self.function = function
+    self.count = count
+
+  # Return the number of test cases to generate.
+  def case_count(self):
+    return self.count
+
+  # Run the generator and write all test cases to the specified output file.
+  def run(self, output, _):
+    # Call the generator function as many times at it was specified, using the
+    # specified output file and giving the index to each call.
+    for index in range(self.count):
+      self.function(index, output)
+
+# List of generators to run when the generate_cases function is called.
+_generators = []
+
+# Add a file to the list of case files to append.
+def add_file(*, file):
+  _generators.append(_TestCaseFile(input_file = file))
+
+# Add a function generator to the list of generators.
+def add_function(*, f, n):
+  _generators.append(_TestCaseFunction(function = f, count = n))
+
+# Generate all cases and write them to the specified output file.
+def generate_cases(*, output, sentinel = None):
+  # Run all generators and the append the sentinel at the end.
+  # Use EOF if no sentinel was specified.
+  for generator in _generators:
+    generator.run(output, sentinel)
+  if sentinel: output.write(sentinel)
+

judge_tools/judge_tools/test_driver.py

+# -*- coding: utf-8 -*-
+import os
+import shutil
+import sys
+import subprocess
+import time
+
+# Execute a sequence of commands or a single command.
+def execute_script(script, *, stdin = None, stdout = None, **kwargs):
+  # Enclose a single line in a tuple, then call each instruction in it.
+  if isinstance(script, str): 
+    script = (script,)
+  for command in script:
+    # Show the command and execute it.
+    compiled_command = [token.format(**kwargs) for token in command]
+    print("    > {command}".format(command = ' '.join(compiled_command)))
+    subprocess.check_call(compiled_command, stdin = stdin, stdout = stdout)
+
+class Language:
+  # Construtor used to initialize a language.
+  def __init__(self, *, name, extension, source_name, executable_name = "",
+               compile_script = None, execute_script):
+    self.name = name
+    self.extension = extension
+    self.source_name = source_name
+    self.executable_name = executable_name
+    self.compile_script = compile_script
+    self.execute_script = execute_script
+
+class Solution:
+  # Constructor used to initialize a solution.
+  def __init__(self, *, name, language, redirect_stdin = False, redirect_stdout = False):
+    self.name = name
+    self.language = language
+    self.redirect_stdin = redirect_stdin
+    self.redirect_stdout = redirect_stdout
+
+  # Run this solution using the specified input and output files for the specified problem.
+  def compile_and_run(self, problem, input_name, output_name):
+    # Create the variables dictionary, including the formatted source name and executable name.
+    variables = {"problem": problem.name, "solution": self.name, "language": self.language.name,
+                 "extension": self.language.extension, "input": input_name, "output": output_name,}
+    print( variables )
+    source = variables["solution"] + "." + variables["extension"] #self.language.source_name.format(**variables)
+    variables.update([("source", source)])
+    executable = variables["solution"] #self.language.executable_name.format(**variables)
+    variables.update([("executable", executable)])
+
+    # Execute the compile command to compile this solution.
+    if self.language.compile_script is not None:
+      print("  Compiling solution '{solution}' in {language} for problem '{problem}'...".format(**variables))
+      execute_script(self.language.compile_script, **variables)
+
+    # Open the input and output files to redirect standard streams if necessary.
+    input = open(input_name, "rt") if self.redirect_stdin else None
+    output = open(output_name, "wt") if self.redirect_stdout else None
+
+    # Use the generated command to run the solution, then print the execution time.      
+    print("  Executing solution '{solution}' in {language} for problem '{problem}'...".format(
+      problem = problem.name, solution = self.name, language = self.language.name))
+    start_time = time.clock()
+    execute_script(self.language.execute_script, stdin = input, stdout = output, **variables)
+    exec_time = round(time.clock() - start_time, 2)
+    print("  Solution '{solution}' in {language} for problem '{problem}' ran in {time} seconds.".format(
+      time = exec_time, **variables))
+
+    # Remove the generated executable if there is one.
+    time.sleep(0.5)
+    if executable != "":
+      os.remove(executable)
+
+class Problem:
+  # Constructor used to initialize a problem.
+  def __init__(self, *, name, directory = "", generator = None, validator = None, valid_solution, test_solutions = ()):
+    self.name = name
+    self.generator = generator
+    self.validator = validator
+    self.valid_solution = valid_solution
+    self.test_solutions = test_solutions
+    self.directory = directory
+
+  # Generate the input file for the problem, using the generator
+  # command specified during initialization.
+  def generate_input(self):
+    # Check if there is a generator script, then execute it.
+    if self.generator is not None:
+      print("  Generating input file for problem '{problem}'...".format(problem = self.name))
+      execute_script(self.generator, problem = self.name)
+      print("  Input file for problem '{problem}' successfully generated.".format(problem = self.name))
+
+  # Validate the generated input file for the problem, using the
+  # validator command specified during initialization.
+  def validate_input(self):
+    # Check if there is a validator script, then execute it.
+    if self.validator is not None:
+      # Execute the constructed command to validate the input file.
+      print("  Validating input file for problem '{problem}'...".format(problem = self.name))
+      execute_script(self.validator, problem = self.name)
+      print("  Input file for problem '{problem}' successfully validated.".format(problem = self.name))
+    else:
+      print("  WARNING: No input validator found for problem '{problem}'".format(problem = self.name))
+
+  # Generate the correct output for the generated input file,
+  # running the valid solution specified during initialization.
+  def generate_output(self):
+    # Generate input and output file names and use them to compile
+    # and run the valid solution.
+    print("  Generating output file for problem '{problem}'...".format(problem = self.name))
+    input_name = "{problem}.in".format(problem = self.name)
+    output_name = "{problem}.out".format(problem = self.name)
+    self.valid_solution.compile_and_run(self, input_name, output_name)
+    print("  Output file for problem '{problem}' successfully generated.".format(problem = self.name))
+
+  # Validate other output using the valid output as reference.
+  def validate_output(self, solution, valid_output, other_output):
+    # Initialize error counter and read lines from the output files.
+    print("  Validating {other_output} output with correct results in {valid_output}...".format(
+      other_output = other_output, valid_output = valid_output))
+    error_count = 0
+    valid_lines = open(valid_output, "rt").readlines()
+    other_lines = open(other_output, "rt").readlines()
+
+    # Check each line in the files and look for errors.
+    for line_number, (valid_line, other_line) in enumerate(zip(valid_lines, other_lines), 1):
+      if valid_line != other_line:
+        if error_count == 0:
+          print("Diffrences found between '{valid}' and '{other}'.".format(
+            valid = valid_output, other = other_output), file = sys.stderr)
+        # Print the lines with the error and increase the counter.
+        print("{line}:< {text}".format(line = line_number, text = repr(valid_line)), file = sys.stderr)
+        print("{line}:> {text}".format(line = line_number, text = repr(other_line)), file = sys.stderr)
+        error_count += 1
+
+    # Check if there are extra lines or missing at the checked output.
+    if len(other_lines) > len(valid_lines):
+      print("{extra} extra line(s) found at {file}.".format(
+        extra = len(other_lines) - len(valid_lines), file = other_output), file = sys.stderr)
+    if len(other_lines) < len(valid_lines):
+      print("{missing} missing line(s) in {file}.".format(
+        missing = len(valid_lines) - len(other_lines), file = other_output), file = sys.stderr)
+
+    # Adjust error count by line differences and return it.
+    error_count += abs(len(other_lines) - len(valid_lines))
+    return error_count
+
+  def test_solution(self, solution):
+    # Generate input and output file names for the solution to test.
+    print("  Testing solution '{solution}' in {language} for problem '{problem}'...".format(
+      problem = self.name, solution = solution.name, language = solution.language.name))
+    input_name = "{problem}.in".format(problem = self.name)
+    valid_output_name = "{problem}.out".format(problem = self.name)
+    output_name = "{problem}-{solution}-{language}.out".format(
+      problem = self.name, solution = solution.name, language = solution.language.name)
+
+    # Compile and run solution using the input and output names, then
+    # check if the output is valid.
+    solution.compile_and_run(self, input_name, output_name)
+    error_count = self.validate_output(solution, valid_output_name, output_name)
+    if error_count == 0:
+      # Remove the output file and print success message.
+      os.remove(output_name)
+      print("  Solution '{solution}' in {language} for problem '{problem}' successfully tested.".format(
+        problem = self.name, solution = solution.name, language = solution.language.name))
+    else:
+      # Print error message and leave the output file for manual checking.
+      print("  Solution '{solution}' in {language} for problem '{problem}' had {errors} error(s).".format(
+        problem = self.name, solution = solution.name, language = solution.language.name, errors = error_count))
+
+  def test(self):
+    # Move the current directory to the problem directory.
+    print("Testing problem '{problem}'...".format(problem = self.name))
+    os.chdir("problems/{directory}".format(directory = self.directory))
+
+    # Generate the input, validate it and then run the valid
+    # solution to generate the output.
+    self.generate_input()
+    self.validate_input()
+    self.generate_output()
+
+    # Run all test solutions and validate them, and print a warning message
+    # if there are no test solutions.
+    for solution in self.test_solutions:
+      self.test_solution(solution)
+    if not self.test_solutions:
+      print("  WARNING: No test solutions found for problem '{problem}'".format(problem = self.name))
+
+    # Go back to the starting directory and move data files to the data directory.
+    os.chdir("../../")
+#    print( os.getcwd() )
+    shutil.copy("problems/{directory}/{problem}.in".format(directory = self.directory, problem = self.name), "data/")
+    shutil.copy("problems/{directory}/{problem}.out".format(directory = self.directory, problem = self.name), "data/")
+    print("Problem '{problem}' successfully tested.".format(problem = self.name))
+    print()
+
+def test_problems(problems):
+  # Get problems to test from command line, if there
+  # are no problems then test them all.
+  target_problems = [name for name in sys.argv[1:] if name in problems]
+  if not target_problems:
+    target_problems = sorted(problems.keys())
+
+  # Create the data directory and ignore any error (like directory already exists).
+  try: os.mkdir("data/")
+  except OSError: pass
+
+  # Test all problems in the array with targets.
+  for name in target_problems:
+    problems[name].test()

judge_tools/setup.py

+# -*- coding: utf-8 -*-
+
+from distutils.core import setup
+    
+'''
+IMPORTANTE: los campos que se describen a continuación deben ser rellenados en su totalidad.
+Aquellos campos que NO SE VAYAN A UTILIZAR, se deben BORRAR.
+'''
+
+setup(name='judge_tools',
+      version='1.0',
+      author='Jorge Bernadas',
+      author_email='jbernadas@gmail.com',
+      url='http://code.funvisis.gob.ve/funvisis/LoL',
+      download_url='http://code.funvisis.gob.ve/funvisis/',
+      description='A set of judge utilities',
+#      package_dir={'':'src'},
+      packages=['judge_tools'],
+      classifiers=['Development Status :: Alpha',
+                   'Intended Audience :: Developers',
+                   'Natural Language :: English',
+                   'Operating System :: OS Independent',
+                   'Programming Language :: Python :: 2.6+',
+                   'License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)',
+                   'License :: OSI Approved :: GNU Affero General Public License v3',
+                   'Topic :: Internet',
+                   'Topic :: Scientific/Engineering :: GIS',
+                  ],
+     )
+#!/bin/bash
+
+function copydir {
+  # Check that all arguments were specified.
+  if [[ -z "$1" || -z "$2" || -z "$3" ]]; then
+    echo "Bad arguments for copydir function." 1>&2
+    exit 1
+  fi
+
+  # Create the destination directory.
+  mkdir "$2" 2> /dev/null
+
+  # Process each file in the source directory.
+  for srcfile in $(ls "$1"); do
+    # Calculate the destination file name and check if it is a
+    # directory or a normal file.
+    destfile=$(echo "$srcfile" | sed "s/stem/$3/")
+    if [[ -d "$1/$srcfile" ]]; then
+      # Make a recursive call to copy the entire directory.
+      copydir "$1/$srcfile" "$2/$destfile" "$3"
+    else
+      # Copy the file from the template to the problem.
+      error=$(cp "$1/$srcfile" "$2/$destfile" 2>&1)
+      if [[ "$?" -ne 0 ]]; then
+        echo "Error while copying file \"$1/$srcfile\" to \"$2/$destfile\"" 1>&2
+        echo "$error" 1>&2
+        exit 1
+      fi
+    fi
+  done
+}
+
+# Extract arguments from the command line.
+problem=$1
+
+# Verify that all arguments where specified.
+if [[ -z "$problem" ]]; then
+  echo "Usage: $(basename $0) problem" 1>&2
+  exit 1
+fi
+
+# Check if the problems directory does not exist.
+if [[ ! -d ./problems ]]; then
+  echo -n "Creating problems directory... "
+  mkdir ./problems 2>&1
+  if [[ "$?" -eq 0 ]]; then
+    echo "[OK]"
+  else
+    echo "[FAIL]"
+    echo "Cannot create problems directory." 1>&2
+    exit 1
+  fi
+fi
+
+# Check if the specific problem directory already exists.
+#if [[ -d ./problems/$problem ]]; then
+#  echo "Problem $problem already exists."
+#  exit
+#fi
+
+# Copy the template directory into the problem.
+copydir template "./problems/$problem" "$problem"

statement/ceidec2012.sty

+\usepackage[latin1]{inputenc}
+\usepackage[spanish]{babel}
+\usepackage{ifthen}
+
+\oddsidemargin  0.0in
+\evensidemargin 0.0in
+\textwidth      6.7in
+\headsep        0.5in
+\textheight     9.5in
+\topmargin     -0.5in
+\parindent      0.0in
+\addtolength{\parskip}{0.4\baselineskip}
+
+\pagestyle{myheadings}
+\markright{OVI 2012}
+\newcounter{pcounter}\setcounter{pcounter}{0}
+\newcounter{INPUT}
+\newcounter{OUTPUT}
+
+\newcommand{\inputstd}{\setcounter{INPUT}{0}}
+\newcommand{\inputfile}{\setcounter{INPUT}{1}}
+\newcommand{\outputstd}{\setcounter{OUTPUT}{0}}
+\newcommand{\outputfile}{\setcounter{OUTPUT}{1}}
+
+\newcommand{\inputnotice}[1]
+    {\vspace{2mm}\noindent
+	  \ifthenelse{\value{INPUT}=0}
+					 {\emph{La entrada debe ser le\'ida de la entrada est\'andar.}\par}
+					 {\emph{La entrada debe ser le\'ida del archivo {\sf #1.in}.}\par}
+    }
+
+\newcommand{\outputnotice}[1]
+    {\vspace{2mm}\noindent
+	  \ifthenelse{\value{OUTPUT}=0}
+                {\emph{La salida debe ser escrita en la salida est\'andar.}\par}
+                {\emph{La salida debe ser escrita al archivo {\sf #1.out}.}\par}
+    }
+
+\newcommand{\problemdir}{problemdir}
+
+\newcommand{\problem}[2]
+    {
+    \addtocounter{pcounter}{1}
+    \newpage
+    \begin{center}
+    \huge{\bf \sf Problema \Alph{pcounter}}\\
+    \LARGE{\sf #1}\\[2mm]
+    \normalsize {\em Nombre del archivo fuente:} {\tt #2.c}, {\tt #2.cpp} {\em o} {\tt #2.java}
+    \vspace{6pt}
+    \end{center}
+   \renewcommand{\problemdir}{#2}
+    }
+
+\newcommand{\sampleio}[1]{
+
+	\vspace{12pt}
+	\noindent
+	\begin{minipage}[c]{\textwidth}
+	\begin{center}
+	\begin{tabular}{|l|l|} \hline
+	\begin{minipage}[t]{0.475\textwidth}
+
+	\bf{Entrada de ejemplo}
+
+%	\verbatimtabinput{../#1.in}
+	\verbatimtabinput{\problemdir/#1.in}
+	\vskip 12pt
+
+	\end{minipage}
+	&
+	\begin{minipage}[t]{0.475\textwidth}
+
+	\bf{Salida para la entrada de ejemplo}
+
+%	\verbatimtabinput{../#1.out}
+	\verbatimtabinput{\problemdir/#1.out}
+	\vskip 12pt
+
+	\end{minipage}\\
+	\hline
+	\end{tabular}
+	\end{center}
+	\end{minipage}
+}
+
+\renewcommand{\subsection}{\@startsection{subsection}{2}{\z@}%
+                                     {-1.0ex\@plus -1ex \@minus -.2ex}%
+                                     {1.0ex \@plus .2ex}%
+                                   {\reset@font\large\bfseries}}
+
+
+

statement/generar.sh

+#!/bin/bash
+
+latex --output-format=pdf problemas.tex
+rm -f problemas.aux problemas.log

statement/problems.tex

+% Template for a problem -- CEIMEC 2010
+
+\documentclass[12pt]{article}
+\usepackage{epsfig}
+\usepackage{ovni2012}
+\usepackage{moreverb}
+
+% Choose one of the following styles for input files
+
+\inputstd        % input from stdin
+\outputstd       % output to stdin
+%inputfile       % input from named file
+%\outputfile      % output to named file
+
+\begin{document}
+\input{<archivo>.tex}
+\end{document}
+#!/bin/bash
+
+# Check that the problems directory exists and can be read.
+if [[ ! -d problems ]]; then
+  echo "Problems directory does not exist." 1>&2
+fi
+if [[ ! -r problems || ! -x problems ]]; then
+  echo "Cannot read or enter into the problems directory." 1>&2
+fi
+
+# Preserve the starting directory and process each problem.
+for problem in $(ls ./problems); do
+  # Try to copy statement from the problem into the directory.
+  echo -n "Updating statement for problem $problem... "
+  error=$(cp ./problems/$problem/statement/$problem.tex ./statement 2>&1)
+  if [[ "$?" -eq 0 ]]; then
+    echo "[OK]"
+  else
+    echo "[FAIL]"
+    echo "Error while copying statement from problem $problem." 1>&2
+    echo "$error" 1>&2
+  fi
+
+  # Check if the directory for the sample data exists.
+  echo -n "Updating samples for problem $problem... "
+  if [[ ! -d ./statement/$problem ]]; then
+    # If the directory does not exist create it.
+    error=$(mkdir ./statement/$problem 2>&1)
+    if [[ "$?" -ne 0 ]]; then
+      echo "[FAIL]"
+      echo "Cannot create directory for problem $problem sample data." 1>&2
+      echo "$error" 1>&2
+      exit 1
+    fi
+  fi
+
+  # Copy new sample data for the problem.
+  error=$(cp ./problems/$problem/sample* ./statement/$problem 2>&1)
+  if [[ "$?" -eq 0 ]]; then
+    echo "[OK]"
+  else
+    echo "[FAIL]"
+    echo "Error while copying samples from problem $problem." 1>&2
+    echo "$error" 1>&2
+  fi
+
+  # Check if the statement has images.
+  ls ./problems/$problem/statement/*.png &> /dev/null
+  if [[ "$?" -eq 0 ]]; then
+    # Copy images from the problem.
+    echo -n "Updating images for problem $problem... "
+    error=$( cp ./problems/$problem/statement/*.png ./statement 2>&1)
+    if [[ "$?" -eq 0 ]]; then
+      echo "[OK]"
+    else
+      echo "[FAIL]"
+      echo "Error while copying images from problem $problem." 1>&2
+      echo "$error" 1>&2
+    fi
+  fi
+done
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.