4 Updated to defeat Bob and Evolved. edited Nov 22 '14 at 18:29 Zgarb 27.3k44 gold badges6363 silver badges234234 bronze badges # Team of treasure-hunting statisticians # Run with: # python3 statisticians.py num_others = None running = True while running: msg = input().split() msg_type = msg.pop(0) if msg_type == "INDEX": my_index = int(msg[0])-1 elif msg_type == "START_DAY": day, max_deaths = tuple(map(int, msg[0].split('/'))) elif msg_type == "START_TURN": turn = int(msg[0]) if day == 1: # On first day, return when two thirds of others have returned if turn == 1: print("S,S,S,S,S") elif turn == 30 or num_active <<= (num_others*5)max_deaths * 24/35: print("R,R,R,R,R") # On first day, return when 4/5 of maximum number of dying servants remain else: print("S,S,S,S,S") elif turn >= 29 or len(expected_servants[turn+1]) <<= max(2, max_deaths * 3/4) or len(expected_servants[turn]) <= max(2, max_deaths * 1/4): print("R,R,R,R,R") # If the critical number ofmany servants are expected to return next turn, returnor tosomeone campis (thesure arrayto isdie, 0-based)return to camp else: print("S,S,S,S,S") # Otherwise, keep going elif msg_type == "END_TURN": turn = int(msg.pop(0)) others_moves = [tuple(s.split(',')) for s in msg[:my_index] + msg[my_index+1:]] if num_others is None: # End of first turn, initialize variables that depend on number of servants num_others = len(others_moves) others_history = [{} for i in range(num_others)] if day == 1: num_active = sum([move.count('S') for move in others_moves]) for i, moves in enumerate(others_moves): # Log the return habits of other bots if turn == 1: others_history[i][day] = [0]*5 for j, move in enumerate(moves): if move == "R": # Only safely returned servants are taken into account others_history[i][day][j] = turn if day > 1: for future_turn in range(turn, 30): expected_servants[future_turn].discard((i,j)) elif msg_type == "END_DAY": day = int(msg.pop(0)) my_statuses = tuple(msg[my_index].split(',')) others_statuses = [tuple(s.split(',')) for s in msg[:my_index] + msg[my_index+1:]] others_averagesexpected_servants = [[][set() for i in range(num_others30)] # CalculateCompute the average return timessets of other bots expected servants expected_servantsfor =each [0]*30turn for i in range(num_others): for j in range(5): if others_statuses[i][j] == 'A': turn_sum = 0 for day_num in others_history[i]: turn_sum += others_history[i][day_num][j] for turn in range(turn_sum//day): expected_servants[turn] += 1.add((i,j)) elif msg_type == "EXIT": running = False EDIT: Fixed a bug in the check for returning home. They should perform somewhat better now.EDIT 2: The statisticians are now smarter than before: they keep track of which servants have returned to the camp in the current day, and adjust their predictions accordingly. Also, they take more risks, returning to the camp when 3/4 of the maximum number of dying servants remain. This pushes them back to the top (just barely; Bob has become very dangerous). # Team of treasure-hunting statisticians # Run with: # python3 statisticians.py num_others = None running = True while running: msg = input().split() msg_type = msg.pop(0) if msg_type == "INDEX": my_index = int(msg[0])-1 elif msg_type == "START_DAY": day, max_deaths = tuple(map(int, msg[0].split('/'))) elif msg_type == "START_TURN": turn = int(msg[0]) if day == 1: # On first day, return when two thirds of others have returned if turn == 1: print("S,S,S,S,S") elif turn == 30 or num_active < (num_others*5) * 2/3: print("R,R,R,R,R") else: print("S,S,S,S,S") elif turn >= 29 or expected_servants[turn+1] < max_deaths: print("R,R,R,R,R") # If the critical number of servants are expected to return next turn, return to camp (the array is 0-based) else: print("S,S,S,S,S") # Otherwise, keep going elif msg_type == "END_TURN": turn = int(msg.pop(0)) others_moves = [tuple(s.split(',')) for s in msg[:my_index] + msg[my_index+1:]] if num_others is None: # End of first turn, initialize variables that depend on number of servants num_others = len(others_moves) others_history = [{} for i in range(num_others)] if day == 1: num_active = sum([move.count('S') for move in others_moves]) for i, moves in enumerate(others_moves): # Log the return habits of other bots if turn == 1: others_history[i][day] = [0]*5 for j, move in enumerate(moves): if move == "R": # Only safely returned servants are taken into account others_history[i][day][j] = turn elif msg_type == "END_DAY": day = int(msg.pop(0)) my_statuses = tuple(msg[my_index].split(',')) others_statuses = [tuple(s.split(',')) for s in msg[:my_index] + msg[my_index+1:]] others_averages = [[] for i in range(num_others)] # Calculate the average return times of other bots expected_servants = [0]*30 for i in range(num_others): for j in range(5): if others_statuses[i][j] == 'A': turn_sum = 0 for day_num in others_history[i]: turn_sum += others_history[i][day_num][j] for turn in range(turn_sum//day): expected_servants[turn] += 1 elif msg_type == "EXIT": running = False EDIT: Fixed a bug in the check for returning home. They should perform somewhat better now. # Team of treasure-hunting statisticians # Run with: # python3 statisticians.py num_others = None running = True while running: msg = input().split() msg_type = msg.pop(0) if msg_type == "INDEX": my_index = int(msg[0])-1 elif msg_type == "START_DAY": day, max_deaths = tuple(map(int, msg[0].split('/'))) elif msg_type == "START_TURN": turn = int(msg[0]) if day == 1: if turn == 1: print("S,S,S,S,S") elif turn == 30 or num_active <= max_deaths * 4/5: print("R,R,R,R,R") # On first day, return when 4/5 of maximum number of dying servants remain else: print("S,S,S,S,S") elif turn >= 29 or len(expected_servants[turn+1]) <= max(2, max_deaths * 3/4) or len(expected_servants[turn]) <= max(2, max_deaths * 1/4): print("R,R,R,R,R") # If many servants are expected to return next turn or someone is sure to die, return to camp else: print("S,S,S,S,S") # Otherwise, keep going elif msg_type == "END_TURN": turn = int(msg.pop(0)) others_moves = [tuple(s.split(',')) for s in msg[:my_index] + msg[my_index+1:]] if num_others is None: # End of first turn, initialize variables that depend on number of servants num_others = len(others_moves) others_history = [{} for i in range(num_others)] if day == 1: num_active = sum([move.count('S') for move in others_moves]) for i, moves in enumerate(others_moves): # Log the return habits of other bots if turn == 1: others_history[i][day] = [0]*5 for j, move in enumerate(moves): if move == "R": # Only safely returned servants are taken into account others_history[i][day][j] = turn if day > 1: for future_turn in range(turn, 30): expected_servants[future_turn].discard((i,j)) elif msg_type == "END_DAY": day = int(msg.pop(0)) my_statuses = tuple(msg[my_index].split(',')) others_statuses = [tuple(s.split(',')) for s in msg[:my_index] + msg[my_index+1:]] expected_servants = [set() for i in range(30)] # Compute the sets of expected servants for each turn for i in range(num_others): for j in range(5): if others_statuses[i][j] == 'A': turn_sum = 0 for day_num in others_history[i]: turn_sum += others_history[i][day_num][j] for turn in range(turn_sum//day): expected_servants[turn].add((i,j)) elif msg_type == "EXIT": running = False EDIT: Fixed a bug in the check for returning home. They should perform somewhat better now.EDIT 2: The statisticians are now smarter than before: they keep track of which servants have returned to the camp in the current day, and adjust their predictions accordingly. Also, they take more risks, returning to the camp when 3/4 of the maximum number of dying servants remain. This pushes them back to the top (just barely; Bob has become very dangerous). 3 Corrected the logic for returning (was giving errors). edited Nov 19 '14 at 6:50 Zgarb 27.3k44 gold badges6363 silver badges234234 bronze badges # Team of treasure-hunting statisticians # Run with: # python3 statisticians.py num_others = None running = True while running: msg = input().split() msg_type = msg.pop(0) if msg_type == "INDEX": my_index = int(msg[0])-1 elif msg_type == "START_DAY": day, max_deaths = tuple(map(int, msg[0].split('/'))) elif msg_type == "START_TURN": turn = int(msg[0]) if day == 1: # On first day, return when two thirds of others have returned if turn == 1: print("S,S,S,S,S") elif turn == 30 or num_active < (num_others*5) * 2/3: print("R,R,R,R,R") else: print("S,S,S,S,S") elif turn ==>= 29 or expected_servants[turn+1] < max_deaths: print("R,R,R,R,R") # If the critical number of servants are expected to return next turn, return to camp (the array is 0-based) else: print("S,S,S,S,S") # Otherwise, keep going elif msg_type == "END_TURN": turn = int(msg.pop(0)) others_moves = [tuple(s.split(',')) for s in msg[:my_index] + msg[my_index+1:]] if num_others is None: # End of first turn, initialize variables that depend on number of servants num_others = len(others_moves) others_history = [{} for i in range(num_others)] if day == 1: num_active = sum([move.count('S') for move in others_moves]) for i, moves in enumerate(others_moves): # Log the return habits of other bots if turn == 1: others_history[i][day] = [0]*5 for j, move in enumerate(moves): if move == "R": # Only safely returned servants are taken into account others_history[i][day][j] = turn elif msg_type == "END_DAY": day = int(msg.pop(0)) my_statuses = tuple(msg[my_index].split(',')) others_statuses = [tuple(s.split(',')) for s in msg[:my_index] + msg[my_index+1:]] others_averages = [[] for i in range(num_others)] # Calculate the average return times of other bots expected_servants = [0]*30 for i in range(num_others): for j in range(5): if others_statuses[i][j] == 'A': turn_sum = 0 for day_num in others_history[i]: turn_sum += others_history[i][day_num][j] for turn in range(turn_sum//day): expected_servants[turn] += 1 elif msg_type == "EXIT": running = False  # Team of treasure-hunting statisticians # Run with: # python3 statisticians.py num_others = None running = True while running: msg = input().split() msg_type = msg.pop(0) if msg_type == "INDEX": my_index = int(msg[0])-1 elif msg_type == "START_DAY": day, max_deaths = tuple(map(int, msg[0].split('/'))) elif msg_type == "START_TURN": turn = int(msg[0]) if day == 1: # On first day, return when two thirds of others have returned if turn == 1: print("S,S,S,S,S") elif turn == 30 or num_active < (num_others*5) * 2/3: print("R,R,R,R,R") else: print("S,S,S,S,S") elif turn == 29 or expected_servants[turn+1] < max_deaths: print("R,R,R,R,R") # If the critical number of servants are expected to return next turn, return to camp (the array is 0-based) else: print("S,S,S,S,S") # Otherwise, keep going elif msg_type == "END_TURN": turn = int(msg.pop(0)) others_moves = [tuple(s.split(',')) for s in msg[:my_index] + msg[my_index+1:]] if num_others is None: # End of first turn, initialize variables that depend on number of servants num_others = len(others_moves) others_history = [{} for i in range(num_others)] if day == 1: num_active = sum([move.count('S') for move in others_moves]) for i, moves in enumerate(others_moves): # Log the return habits of other bots if turn == 1: others_history[i][day] = [0]*5 for j, move in enumerate(moves): if move == "R": # Only safely returned servants are taken into account others_history[i][day][j] = turn elif msg_type == "END_DAY": day = int(msg.pop(0)) my_statuses = tuple(msg[my_index].split(',')) others_statuses = [tuple(s.split(',')) for s in msg[:my_index] + msg[my_index+1:]] others_averages = [[] for i in range(num_others)] # Calculate the average return times of other bots expected_servants = [0]*30 for i in range(num_others): for j in range(5): if others_statuses[i][j] == 'A': turn_sum = 0 for day_num in others_history[i]: turn_sum += others_history[i][day_num][j] for turn in range(turn_sum//day): expected_servants[turn] += 1 elif msg_type == "EXIT": running = False  # Team of treasure-hunting statisticians # Run with: # python3 statisticians.py num_others = None running = True while running: msg = input().split() msg_type = msg.pop(0) if msg_type == "INDEX": my_index = int(msg[0])-1 elif msg_type == "START_DAY": day, max_deaths = tuple(map(int, msg[0].split('/'))) elif msg_type == "START_TURN": turn = int(msg[0]) if day == 1: # On first day, return when two thirds of others have returned if turn == 1: print("S,S,S,S,S") elif turn == 30 or num_active < (num_others*5) * 2/3: print("R,R,R,R,R") else: print("S,S,S,S,S") elif turn >= 29 or expected_servants[turn+1] < max_deaths: print("R,R,R,R,R") # If the critical number of servants are expected to return next turn, return to camp (the array is 0-based) else: print("S,S,S,S,S") # Otherwise, keep going elif msg_type == "END_TURN": turn = int(msg.pop(0)) others_moves = [tuple(s.split(',')) for s in msg[:my_index] + msg[my_index+1:]] if num_others is None: # End of first turn, initialize variables that depend on number of servants num_others = len(others_moves) others_history = [{} for i in range(num_others)] if day == 1: num_active = sum([move.count('S') for move in others_moves]) for i, moves in enumerate(others_moves): # Log the return habits of other bots if turn == 1: others_history[i][day] = [0]*5 for j, move in enumerate(moves): if move == "R": # Only safely returned servants are taken into account others_history[i][day][j] = turn elif msg_type == "END_DAY": day = int(msg.pop(0)) my_statuses = tuple(msg[my_index].split(',')) others_statuses = [tuple(s.split(',')) for s in msg[:my_index] + msg[my_index+1:]] others_averages = [[] for i in range(num_others)] # Calculate the average return times of other bots expected_servants = [0]*30 for i in range(num_others): for j in range(5): if others_statuses[i][j] == 'A': turn_sum = 0 for day_num in others_history[i]: turn_sum += others_history[i][day_num][j] for turn in range(turn_sum//day): expected_servants[turn] += 1 elif msg_type == "EXIT": running = False  2 Fixed logic for returning home. edited Nov 18 '14 at 7:27 Zgarb 27.3k44 gold badges6363 silver badges234234 bronze badges # Team of treasure-hunting statisticians # Run with: # python3 statisticians.py num_others = None running = True while running: msg = input().split() msg_type = msg.pop(0) if msg_type == "INDEX": my_index = int(msg[0])-1 elif msg_type == "START_DAY": day, max_deaths = tuple(map(int, msg[0].split('/'))) elif msg_type == "START_TURN": turn = int(msg[0]) if day == 1: # On first day, return when halftwo thirds of others have returned if turn == 1: print("S,S,S,S,S") elif turn == 30 or num_active < (num_others*5) * 2/3: print("R,R,R,R,R") else: print("S,S,S,S,S") elif turn == 3029 or expected_servants[turn]expected_servants[turn+1] < max_deaths: print("R,R,R,R,R") # If the critical number of servants are expected to return next turn, return to camp (the array is 0-based) else: print("S,S,S,S,S") # Otherwise, keep going elif msg_type == "END_TURN": turn = int(msg.pop(0)) others_moves = [tuple(s.split(',')) for s in msg[:my_index] + msg[my_index+1:]] if num_others is None: # End of first turn, initialize variables that depend on number of servants num_others = len(others_moves) others_history = [{} for i in range(num_others)] if day == 1: num_active = sum([move.count('S') for move in others_moves]) for i, moves in enumerate(others_moves): # Log the return habits of other bots if turn == 1: others_history[i][day] = [0]*5 for j, move in enumerate(moves): if move == "R": # Only safely returned servants are taken into account others_history[i][day][j] = turn elif msg_type == "END_DAY": day = int(msg.pop(0)) my_statuses = tuple(msg[my_index].split(',')) others_statuses = [tuple(s.split(',')) for s in msg[:my_index] + msg[my_index+1:]] others_averages = [[] for i in range(num_others)] # Calculate the average return times of other bots expected_servants = [0]*30 for i in range(num_others): for j in range(5): if others_statuses[i][j] == 'A': turn_sum = 0 for day_num in others_history[i]: turn_sum += others_history[i][day_num][j] for turn in range(turn_sum//day): expected_servants[turn] += 1 elif msg_type == "EXIT": running = False EDIT: Fixed a bug in the check for returning home. They should perform somewhat better now. # Team of treasure-hunting statisticians # Run with: # python3 statisticians.py num_others = None running = True while running: msg = input().split() msg_type = msg.pop(0) if msg_type == "INDEX": my_index = int(msg[0])-1 elif msg_type == "START_DAY": day, max_deaths = tuple(map(int, msg[0].split('/'))) elif msg_type == "START_TURN": turn = int(msg[0]) if day == 1: # On first day, return when half of others have returned if turn == 1: print("S,S,S,S,S") elif num_active < (num_others*5) * 2/3: print("R,R,R,R,R") else: print("S,S,S,S,S") elif turn == 30 or expected_servants[turn] < max_deaths: print("R,R,R,R,R") # If the critical number of servants are expected to return next turn, return to camp (the array is 0-based) else: print("S,S,S,S,S") # Otherwise, keep going elif msg_type == "END_TURN": turn = int(msg.pop(0)) others_moves = [tuple(s.split(',')) for s in msg[:my_index] + msg[my_index+1:]] if num_others is None: # End of first turn, initialize variables that depend on number of servants num_others = len(others_moves) others_history = [{} for i in range(num_others)] if day == 1: num_active = sum([move.count('S') for move in others_moves]) for i, moves in enumerate(others_moves): # Log the return habits of other bots if turn == 1: others_history[i][day] = [0]*5 for j, move in enumerate(moves): if move == "R": # Only safely returned servants are taken into account others_history[i][day][j] = turn elif msg_type == "END_DAY": day = int(msg.pop(0)) my_statuses = tuple(msg[my_index].split(',')) others_statuses = [tuple(s.split(',')) for s in msg[:my_index] + msg[my_index+1:]] others_averages = [[] for i in range(num_others)] # Calculate the average return times of other bots expected_servants = [0]*30 for i in range(num_others): for j in range(5): if others_statuses[i][j] == 'A': turn_sum = 0 for day_num in others_history[i]: turn_sum += others_history[i][day_num][j] for turn in range(turn_sum//day): expected_servants[turn] += 1 elif msg_type == "EXIT": running = False  # Team of treasure-hunting statisticians # Run with: # python3 statisticians.py num_others = None running = True while running: msg = input().split() msg_type = msg.pop(0) if msg_type == "INDEX": my_index = int(msg[0])-1 elif msg_type == "START_DAY": day, max_deaths = tuple(map(int, msg[0].split('/'))) elif msg_type == "START_TURN": turn = int(msg[0]) if day == 1: # On first day, return when two thirds of others have returned if turn == 1: print("S,S,S,S,S") elif turn == 30 or num_active < (num_others*5) * 2/3: print("R,R,R,R,R") else: print("S,S,S,S,S") elif turn == 29 or expected_servants[turn+1] < max_deaths: print("R,R,R,R,R") # If the critical number of servants are expected to return next turn, return to camp (the array is 0-based) else: print("S,S,S,S,S") # Otherwise, keep going elif msg_type == "END_TURN": turn = int(msg.pop(0)) others_moves = [tuple(s.split(',')) for s in msg[:my_index] + msg[my_index+1:]] if num_others is None: # End of first turn, initialize variables that depend on number of servants num_others = len(others_moves) others_history = [{} for i in range(num_others)] if day == 1: num_active = sum([move.count('S') for move in others_moves]) for i, moves in enumerate(others_moves): # Log the return habits of other bots if turn == 1: others_history[i][day] = [0]*5 for j, move in enumerate(moves): if move == "R": # Only safely returned servants are taken into account others_history[i][day][j] = turn elif msg_type == "END_DAY": day = int(msg.pop(0)) my_statuses = tuple(msg[my_index].split(',')) others_statuses = [tuple(s.split(',')) for s in msg[:my_index] + msg[my_index+1:]] others_averages = [[] for i in range(num_others)] # Calculate the average return times of other bots expected_servants = [0]*30 for i in range(num_others): for j in range(5): if others_statuses[i][j] == 'A': turn_sum = 0 for day_num in others_history[i]: turn_sum += others_history[i][day_num][j] for turn in range(turn_sum//day): expected_servants[turn] += 1 elif msg_type == "EXIT": running = False EDIT: Fixed a bug in the check for returning home. They should perform somewhat better now. 1 answered Nov 17 '14 at 20:55 Zgarb 27.3k44 gold badges6363 silver badges234234 bronze badges