def __init__(self, name, is_first):
     self.first_resp_recv = False
     self.name = name
     self.client = SocketClient(HOST, PORT)
     self.client.send_data(json.dumps({'name': self.name, 'is_first': is_first}))
     response = json.loads(self.client.receive_data())
     self.board_length = response['board_length']
     self.num_weights = response['num_weights']
Example #2
0
 def __init__(self, name, is_player):
     self.name = name
     self.is_player = is_player
     self.client = SocketClient(HOST, PORT)
     self.client.send_data(
         json.dumps({
             'name': self.name,
             'is_player': self.is_player
         }))
Example #3
0
 def __init__(self, name, is_first):
     self.first_resp_recv = False
     self.name = name
     self.client = SocketClient(HOST, PORT)
     self.client.send_data(json.dumps({'name': self.name, 'is_first': is_first}))
     response = json.loads(self.client.receive_data())
     self.board_length = response['board_length']
     self.num_weights = response['num_weights']
     self.myWeight = dict()
     for i in range(1, int(self.num_weights)):
         self.myWeight[i] = 1;
     self.gameState = game.PyGameState()
Example #4
0
class Player(object):
    def __init__(self, name, is_player):
        self.name = name
        self.is_player = is_player
        self.client = SocketClient(HOST, PORT)
        self.client.send_data(
            json.dumps({
                'name': self.name,
                'is_player': self.is_player
            }))

    @abstractclassmethod
    def play_game(self):
        pass
class NoTippingClient(object):
    def __init__(self, name, is_first):
        self.first_resp_recv = False
        self.name = name
        self.client = SocketClient(HOST, PORT)
        self.client.send_data(json.dumps({'name': self.name, 'is_first': is_first}))
        response = json.loads(self.client.receive_data())
        self.board_length = response['board_length']
        self.num_weights = response['num_weights']

    def play_game(self):
        # pass
        response = {}
        while True:
            response = json.loads(self.client.receive_data())
            if 'game_over' in response and response['game_over'] == "1":
                print("Game Over!")
                exit(0)

            board_state = map(lambda x: int(x), response['board_state'].split(' '))

            if response['move_type'] == 'place':
                position, weight = self.place(board_state)
                self.client.send_data(json.dumps({"position": position, "weight": weight}))
            else:
                position = self.remove(board_state)
                self.client.send_data(json.dumps({"position": position}))
                
            
            

    def place(self, current_board_state):
        """
        PLACE YOUR PLACING ALGORITHM HERE
        
        Inputs:
        current_board_state - array of what weight is at a given position on the board

        Output:
        position (Integer), weight (Integer)
        """

        return 1, 1

    def remove(self, current_board_state):
        """
        PLACE YOUR REMOVING ALGORITHM HERE
        
        Inputs:
        current_board_state - array of what weight is at a given position on the board

        Output:
        position (Integer)
        """
        return 1
Example #6
0
    def __init__(self, name, is_first):
        self.first_resp_recv = False
        self.name = name
        self.client = SocketClient(HOST, PORT)
        self.client.send_data(
            json.dumps({
                'name': self.name,
                'is_first': is_first
            }))
        response = json.loads(self.client.receive_data())
        self.board_length = response['board_length']
        self.num_weights = response['num_weights']
        self.magic_point = min(int(self.num_weights),
                               min(5, math.floor(int(self.num_weights) / 2)))
        self.myWeight = dict()
        self.place_turn = 0  #self turns
        self.remove_turn = 0  #self turns

        for i in range(1, int(self.num_weights) + 1):
            self.myWeight[i] = 1
Example #7
0
    def __init__(self, name, is_first):
        self.first_resp_recv = False
        self.name = name
        self.client = SocketClient(HOST, PORT)
        self.client.send_data(
            json.dumps({
                'name': self.name,
                'is_first': is_first
            }))
        response = json.loads(self.client.receive_data())
        self.board_length = int(response['board_length'])
        self.num_weights = int(response['num_weights'])
        self.myWeight = dict()
        self.is_first = is_first
        for i in range(1, int(self.num_weights) + 1):
            self.myWeight[i] = 1

        if is_first:
            self.position = -1
        else:
            self.position = -2

        self.nextWeight = 1
Example #8
0
class NoTippingClient(object):
    def __init__(self, name, is_first):
        self.first_resp_recv = False
        self.name = name
        self.client = SocketClient(HOST, PORT)
        self.client.send_data(json.dumps({'name': self.name, 'is_first': is_first}))
        response = json.loads(self.client.receive_data())
        self.board_length = response['board_length']
        self.num_weights = response['num_weights']
        self.myWeight = dict()
        for i in range(1, int(self.num_weights)):
            self.myWeight[i] = 1;
        self.gameState = game.PyGameState()

    def play_game(self):
        # pass
        response = {}
        while True:
            response = json.loads(self.client.receive_data())
            if 'game_over' in response and response['game_over'] == "1":
                print("Game Over!")
                exit(0)
            if not response:
                self.board_state = [0]*60
            else:
                self.board_state = board_state = [int(state) for state in filter(None,list(response['board_state'].split(' ')))]

            self.gameState.absorb(self.board_state)
            if response['move_type'] == 'place':
                position, weight = self.gameState.play(2)
                print("sending " + str(position) + " " + str(weight))
                self.client.send_data(json.dumps({"position": position, "weight": weight}))
            else:
                position = self.gameState.play(6)
                print("sending " + str(position))
                self.client.send_data(json.dumps({"position": position}))
 def __init__(self, name):
     self.name = name
     self.client = SocketClient(HOST, PORT)
     self.client.send_data(json.dumps({'name': self.name}))
Example #10
0
class Player(object):
    def __init__(self, name):
        self.name = name
        self.client = SocketClient(HOST, PORT)
        self.client.send_data(json.dumps({'name': self.name}))

    def play_game(self):
        buffer_size_message = json.loads(self.client.receive_data(size=2048))
        buffer_size = int(buffer_size_message['buffer_size'])
        game_state = json.loads(self.client.receive_data(size=buffer_size))
        self.patients = {
            int(key): value
            for key, value in game_state['patients'].items()
        }
        self.hospitals = {
            int(key): value
            for key, value in game_state['hospitals'].items()
        }
        self.ambulances = {
            int(key): value
            for key, value in game_state['ambulances'].items()
        }

        # Get hospital locations and ambulance routes
        (hos_locations, amb_routes) = self.your_algorithm()
        response = {
            'hospital_loc': hos_locations,
            'ambulance_moves': amb_routes
        }
        print('sending data')
        min_buffer_size = sys.getsizeof(json.dumps(response))
        print(min_buffer_size)
        print(response)

        buff_size_needed = 1 << (min_buffer_size - 1).bit_length()
        buff_size_needed = max(buff_size_needed, 2048)
        buff_size_message = {'buffer_size': buff_size_needed}
        self.client.send_data(json.dumps(buff_size_message))
        time.sleep(2)
        self.client.send_data(json.dumps(response))

        # Get results of game
        game_result = json.loads(self.client.receive_data(size=8192))
        if game_result['game_completed']:
            print(game_result['message'])
            print('Patients that lived:')
            print(game_result['patients_saved'])
            print('---------------')
            print('Number of patients saved = ' +
                  str(game_result['number_saved']))
        else:
            print('Game failed run/validate ; reason:')
            print(game_result['message'])

    def your_algorithm(self):
        def get_pos_list():
            pos_list = []
            for p in self.patients:
                pos_list.append(
                    [self.patients[p]['xloc'], self.patients[p]['yloc']])
            return pos_list

        def parse_clusters(pos_list, labels):
            clusters = [[], [], [], [], []]
            for p in range(len(pos_list)):
                index = labels[p]
                clusters[index].append(pos_list[p] +
                                       [self.patients[p]['rescuetime']] + [p])
            return clusters

        def get_total_urgency(clusters, centroids):
            urgency = []
            for c in range(5):
                centroid = centroids[c]
                cluster = clusters[c]
                distance = 0
                survival = 0
                for p in cluster:
                    distance += abs(p[0] - centroid[0]) + abs(p[1] -
                                                              centroid[1])
                    #survival += p[2]
                    survival += p[2] / len(cluster)
                urgency.append(distance / float(survival))
            return urgency

        def distance(pos1, pos2):
            return abs(pos1[0] - pos2[0]) + abs(pos1[1] - pos2[1])

        def get_next_patient(cluster, amb_pos, hosp_pos, riders, t, dis_bool,
                             death_bool):
            if len(riders) == 4:
                return 0
            possibles = []
            distance_list = []
            death_list = []
            for patient in cluster:
                pos = [patient[0], patient[1]]
                d = distance(amb_pos, pos)
                time_to_save = d + distance(pos, hosp_pos) + 2
                rescue_times = [r[2] for r in riders] + [patient[2]]
                possible = True
                for rt in rescue_times:
                    if rt < time_to_save + t:
                        possible = False
                if possible:
                    possibles.append(patient)
                    distance_list.append(d)
                    death_list.append(patient[2] - t)

            if len(possibles) == 0:
                return 0
            if min(distance_list) < 3:
                return possibles[np.argmin(distance_list)]

            if dist_bool and not death_bool:
                return possibles[np.argmin(distance_list)]

            if death_bool and not dist_bool:
                return possibles[np.argmin(death_list)]

            if death_bool and dist_bool:
                index = np.random.choice([0, 1], 1, [.6, .4])[0]
                return [
                    possibles[np.argmin(distance_list)],
                    possibles[np.argmin(death_list)]
                ][index]
            if len(possibles) > 30:
                dist_index = np.argsort(distance_list)[-15:]
                death_index = np.argsort(death_list)[-15:]
                index_list = list(dist_index) + list(death_index)
                possibles = [possibles[i] for i in index_list]
            #MESS AROUND WITH PROB_LIST
            prob_list = np.array([
                1 / float(((distance_list[i]) * death_list[i]))
                for i in range(len(possibles))
            ])
            prob_list = list(prob_list / float(np.sum(prob_list)))
            index_list = list(range(len(possibles)))
            index = np.random.choice(index_list, 1, prob_list)[0]
            #index = random.choice(index_list)
            return possibles[index]

        def converge(my_list, thresh):
            bool = True
            for l in my_list:
                for other in my_list:
                    if abs(l - other) > thresh:
                        bool = False
            return bool

        def get_u2a_ratio(cluster_urgency, hospitals_sorted, urgency,
                          amb_num_list):

            u2a_ratio = []
            for i in range(5):
                index = list(cluster_urgency).index(i)
                hosp = hospitals_sorted[index]
                u2a_ratio.append(urgency[i] / float(amb_num_list[hosp]))
            return u2a_ratio

        def adjust_clusters(clusters, centroids, urgency, cluster_urgency,
                            amb_num_list, hospitals_sorted):

            u2a_ratio = get_u2a_ratio(cluster_urgency, hospitals_sorted,
                                      urgency, amb_num_list)
            clusters_new = copy.deepcopy(clusters)

            bool = False
            t0 = time.time()
            while not bool:
                mean_u = np.mean(u2a_ratio)
                index_list = [i for i in range(5) if u2a_ratio[i] < mean_u]
                for c in index_list:
                    clust = clusters_new[c]
                    others = copy.deepcopy(clusters_new)
                    min_dist = 2000
                    for o in range(len(others)):
                        if o == c or o in index_list:
                            continue
                        for p in range(len(others[o])):
                            dist = distance(others[o][p], centroids[c])
                            if dist < min_dist:
                                min_index = [o, p]
                                min_dist = dist
                    clusters_new[c].append(
                        copy.deepcopy(
                            clusters_new[min_index[0]][min_index[1]]))
                    del clusters_new[min_index[0]][min_index[1]]

                urgency = get_total_urgency(clusters_new, centroids)
                cluster_urgency = np.argsort(urgency)
                u2a_ratio = get_u2a_ratio(cluster_urgency, hospitals_sorted,
                                          urgency, amb_num_list)
                bool = converge(u2a_ratio, .1)
                if time.time() - t0 > 1:
                    break

            return clusters_new

        res_hos = {}
        res_amb = {}

        res_hos_max_outer = {}
        res_amb_max_outer = {}
        off_count = 0
        saved_max_outer = 0
        previous_centroids = []
        for trials in range(40):
            res_hos_temp = {}
            pos_list = get_pos_list()
            kmeans = KMeans(init='k-means++', n_clusters=5, n_init=1)
            kmeans.fit(pos_list)
            centroids = np.empty(shape=(5, 2))
            centroids_d = kmeans.cluster_centers_
            for i in range(len(centroids_d)):
                for j in range(len(centroids_d[i])):
                    centroids[i, j] = int(round(centroids_d[i][j]))
            clusters = parse_clusters(pos_list, kmeans.labels_)

            urgency = get_total_urgency(clusters, centroids)
            cluster_urgency = np.argsort(urgency)
            amb_num_list = []
            for i in range(5):
                amb_num_list.append(
                    len(self.hospitals[i]['ambulances_at_start']))
            hospitals_sorted = np.argsort(amb_num_list)
            for i in range(5):
                centroid_x = int(centroids[cluster_urgency[i], 0])
                centroid_y = int(centroids[cluster_urgency[i], 1])
                int(centroids[cluster_urgency[i], 1])
                res_hos_temp[int(hospitals_sorted[i])] = {
                    'xloc': centroid_x,
                    'yloc': centroid_y
                }

            max_rescue = 0
            for p in self.patients:
                if self.patients[p]['rescuetime'] > max_rescue:
                    max_rescue = self.patients[p]['rescuetime']

            print(cluster_urgency)
            print(hospitals_sorted)
            print()

            #u2a_ratio = get_u2a_ratio(cluster_urgency,hospitals_sorted,urgency,amb_num_list)

            for i in range(5):
                '''
                print("hospital location :" ,res_hos_temp[i])
                print("hospital amb number: " , amb_num_list[i])
                index = list(hospitals_sorted).index(i)
                clust_num = cluster_urgency[index]
                print("cluster number: " , clust_num)
                print("centroid:" , centroids[clust_num])
                print("urgency at loction: " , urgency[clust_num])
                #print("u2a: " , u2a_ratio[clust_num])
                print()
                '''

            cluster_urgency_copy = copy.deepcopy(cluster_urgency)
            print(len(clusters[0]))
            centroids_new = copy.deepcopy(centroids)
            urgency_new = copy.deepcopy(urgency)
            cluster_urgency_new = copy.deepcopy(cluster_urgency)
            amb_num_list_new = copy.deepcopy(amb_num_list)
            hospitals_sorted_new = copy.deepcopy(hospitals_sorted)

            clusters_new = copy.deepcopy(clusters)

            if trials < 20:
                clusters_new = adjust_clusters(clusters_new,centroids_new\
                ,urgency_new,cluster_urgency_new,amb_num_list_new,hospitals_sorted_new)

            print(len(clusters_new[0]))
            '''
            for i in range(5):
                print("hospital location :" ,res_hos_temp[i])
                print("hospital amb number: " , amb_num_list[i])
                index = list(hospitals_sorted).index(i)
                clust_num = cluster_urgency[index]
                print("cluster number: " , clust_num)
                print("centroid:" , centroids[clust_num])
                print("urgency at loction: " , urgency[clust_num])
                #print("u2a: " , u2a_ratio[clust_num])
                print()
            '''

            res_amb_max = {}
            saved_max = 0
            t0 = time.time()
            t1 = 0
            max_time = 2
            count = 0

            while t1 < max_time:
                if count < 5:
                    dist_bool = True
                    death_bool = False
                elif count < 10:
                    dist_bool = False
                    death_bool = True
                elif t1 < 2 * max_time / float(4):
                    dist_bool = False
                    death_bool = False
                else:
                    dist_bool = True
                    death_bool = True
                count += 1
                res_amb_temp = {}
                saved = 0
                saved_riders = []
                for i in range(5):
                    clusters_copy = copy.deepcopy(clusters_new)
                    hosp = self.hospitals[hospitals_sorted[i]]
                    clust = clusters_copy[cluster_urgency_new[i]]
                    hosp_pos = centroids[cluster_urgency_new[i]]
                    for amb in hosp['ambulances_at_start']:
                        t = 0
                        route = []
                        riders = []
                        amb_pos = hosp_pos
                        while t < max_rescue:
                            while True:
                                next_patient = get_next_patient(
                                    clust, amb_pos, hosp_pos, riders, t,
                                    dist_bool, death_bool)
                                if next_patient == 0:
                                    break
                                riders.append(next_patient)
                                route.append('p' + str(next_patient[-1]))
                                clust.remove(next_patient)
                                t += distance(amb_pos, next_patient[0:2]) + 1
                                amb_pos = next_patient[0:2]
                            if len(riders) == 0:
                                break
                            route.append('h' + str(hospitals_sorted[i]))
                            t += distance(amb_pos, hosp_pos) + len(riders)
                            amb_pos = hosp_pos
                            saved += len(riders)
                            saved_riders += riders
                            riders = []

                        if route == []:
                            route = ['h0']
                        res_amb_temp[amb] = route

                #print("saved: ", saved)
                saved_riders = [r[-1] for r in saved_riders]
                #print(saved_riders)
                #print("number saved: " , len(saved_riders))

                if saved > saved_max:
                    saved_max = saved
                    res_amb_max = res_amb_temp
                t1 = time.time() - t0

            print("max saved with this cluster: ", saved_max)
            print("previous max: ", saved_max_outer)
            if saved_max > saved_max_outer:
                saved_max_outer = saved_max
                res_amb_max_outer = res_amb_max
                res_hos_max_outer = res_hos_temp

        res_amb = res_amb_max_outer
        res_hos = res_hos_max_outer

        return (res_hos, res_amb)
class Player(object):
    def __init__(self, name):
        self.name = name
        self.client = SocketClient(HOST, PORT)
        self.client.send_data(json.dumps({'name': self.name}))

    def play_game(self):
        buffer_size_message = json.loads(self.client.receive_data(size=2048))
        buffer_size = int(buffer_size_message['buffer_size'])
        game_state = json.loads(self.client.receive_data(size=buffer_size))
        self.patients = game_state['patients']
        self.hospitals = game_state['hospitals']
        self.ambulances = game_state['ambulances']

        # Get hospital locations and ambulance routes
        (hos_locations, amb_routes) = self.your_algorithm()

        response = {
            'hospital_loc': hos_locations,
            'ambulance_moves': amb_routes
        }

        print('sending data')
        min_buffer_size = sys.getsizeof(json.dumps(response))
        print(min_buffer_size)
        print(response)

        buff_size_needed = 1 << (min_buffer_size - 1).bit_length()
        buff_size_needed = max(buff_size_needed, 2048)
        buff_size_message = {'buffer_size': buff_size_needed}
        self.client.send_data(json.dumps(buff_size_message))
        time.sleep(2)
        self.client.send_data(json.dumps(response))

        # Get results of game
        game_result = json.loads(self.client.receive_data(size=8192))
        if game_result['game_completed']:
            print(game_result['message'])
            print('Patients that lived:')
            print(game_result['patients_saved'])
            print('---------------')
            print('Number of patients saved = ' +
                  str(game_result['number_saved']))
        else:
            print('Game failed run/validate ; reason:')
            print(game_result['message'])

    def your_algorithm(self):
        """
        PLACE YOUR ALGORITHM HERE

        You have access to the dictionaries 'patients', 'hospitals', and 'ambulances'
        These dictionaries are structured as follows:
            patients[patient_id] = {'xloc': x, 'yloc': y, 'rescuetime': rescuetime}

            hospitals[hospital_id] = {'xloc': None, 'yloc': None, 'ambulances_at_start': [array of ambulance_ids]}

            ambulances[ambulance_id] = {'starting_hospital': hospital_id, 'route': None}

        IMPORTANT: Although all values are integers (inlcuding ids) JSON converts everything into strings. Hence,
                   if you wish to use the values as integers, please remember to cast them into ints. Likewise, to index
                   into the dictionaries please remember to cast numeric ids into strings i.e. self.patients[str(p_id)]

        RETURN INFO
        -----------
        You must return a tuple of dictionaries (hospital_locations, ambulance_routes). These MUST be structured as:
            hospital_locations[hospital_id] = {'xloc': x, 'yloc': y}
                These values indicate where you want the hospital with hospital_id to start on the grid

            ambulance_routes[ambulance_id] = {[array of stops along route]}
                This array follows the following rules:
                    - The starting location of each ambulance is known so array must start with first patient that
                      it must pick up (or hospital location that it will head to)
                    - There can only ever be up to 4 patients in an ambulance at a time so any more than 4
                      patient stops in a row will result in an invalid input
                    - A stop for a patient is a string starting with 'p' followed by the id of the patient i.e. 'p32'
                        + The 'p' can be uppercase or lowercase
                        + There can be no whitespace, i.e. 'p 32' will not be accepted
                    - A stop for a hospital is the same as the patient except with an 'h', i.e. 'h3'
                        + The 'h' can also be uppercase or lowercase

            Example:
                ambulance_routes[3] = ['p0', 'p43', 'h4', 'p102', 'p145', 'p241', 'p32', 'h1']

                This will be read as ambulance #3 starts at it's designated hospital, goes to patient #0, then to
                patient #43, then drops both off at hospital #4, then picks up patients #102, #145, #241, #32 in that
                order then drops all of them off at hospital #1
        """
        res_hos = {}
        res_amb = {}
        res_hos[0] = {'xloc': 36, 'yloc': 52}
        res_hos[1] = {'xloc': 18, 'yloc': 20}
        res_hos[2] = {'xloc': 70, 'yloc': 85}

        # testing no movement/time increment
        res_amb[0] = ['p0', 'p1', 'p2', 'p3', 'h0', 'p4', 'h0']

        # testing more than 4 pickups
        res_amb[1] = ['p5', 'p6', 'p7', 'p8', 'h1']

        # testing duplicate person id
        res_amb[2] = ['p9', 'p10', 'p11', 'h2']
        res_amb[3] = ['p12', 'p11', 'h2']

        # testing rescue overtime (t = 0 before unloading)
        res_amb[4] = ['p13', 'h0']

        # testing rescue barely making it (t = 0 after unloading counts as rescued)
        res_amb[5] = ['p14', 'h0']

        return (res_hos, res_amb)
Example #12
0
class Player(object):
    def __init__(self, name):
        self.name = name
        self.client = SocketClient(HOST, PORT)
        self.client.send_data(json.dumps({'name': self.name}))

    def play_game(self):
        buffer_size_message = json.loads(self.client.receive_data(size=2048))
        buffer_size = int(buffer_size_message['buffer_size'])
        game_state = json.loads(self.client.receive_data(size=buffer_size))
        self.patients = {
            int(key): value
            for key, value in game_state['patients'].items()
        }
        self.hospitals = {
            int(key): value
            for key, value in game_state['hospitals'].items()
        }
        self.ambulances = {
            int(key): value
            for key, value in game_state['ambulances'].items()
        }

        # Get hospital locations and ambulance routes
        (hos_locations, amb_routes) = self.your_algorithm()
        response = {
            'hospital_loc': hos_locations,
            'ambulance_moves': amb_routes
        }
        print('sending data')
        min_buffer_size = sys.getsizeof(json.dumps(response))
        print(min_buffer_size)
        print(response)

        buff_size_needed = 1 << (min_buffer_size - 1).bit_length()
        buff_size_needed = max(buff_size_needed, 2048)
        buff_size_message = {'buffer_size': buff_size_needed}
        self.client.send_data(json.dumps(buff_size_message))
        time.sleep(2)
        self.client.send_data(json.dumps(response))

        # Get results of game
        game_result = json.loads(self.client.receive_data(size=8192))
        if game_result['game_completed']:
            print(game_result['message'])
            print('Patients that lived:')
            print(game_result['patients_saved'])
            print('---------------')
            print('Number of patients saved = ' +
                  str(game_result['number_saved']))
        else:
            print('Game failed run/validate ; reason:')
            print(game_result['message'])

    def your_algorithm(self):
        """
        PLACE YOUR ALGORITHM HERE

        You have access to the dictionaries 'patients', 'hospitals', and 'ambulances'
        These dictionaries are structured as follows:
            patients[patient_id] = {'xloc': x, 'yloc': y, 'rescuetime': rescuetime}

            hospitals[hospital_id] = {'xloc': None, 'yloc': None, 'ambulances_at_start': [array of ambulance_ids]}

            ambulances[ambulance_id] = {'starting_hospital': hospital_id}

        RETURN INFO
        -----------
        You must return a tuple of dictionaries (hospital_locations, ambulance_routes). These MUST be structured as:
            hospital_locations[hospital_id] = {'xloc': x, 'yloc': y}
                These values indicate where you want the hospital with hospital_id to start on the grid

            ambulance_routes[ambulance_id] = {[array of stops along route]}
                This array follows the following rules:
                    - The starting location of each ambulance is known so array must start with first patient that
                      it must pick up (or hospital location that it will head to)
                    - There can only ever be up to 4 patients in an ambulance at a time so any more than 4
                      patient stops in a row will result in an invalid input
                    - A stop for a patient is a string starting with 'p' followed by the id of the patient i.e. 'p32'
                        + The 'p' can be uppercase or lowercase
                        + There can be no whitespace, i.e. 'p 32' will not be accepted
                    - A stop for a hospital is the same as the patient except with an 'h', i.e. 'h3'
                        + The 'h' can also be uppercase or lowercase

            Example:
                ambulance_routes[3] = ['p0', 'p43', 'h4', 'p102', 'p145', 'p241', 'p32', 'h1']

                This will be read as ambulance #3 starts at it's designated hospital, goes to patient #0, then to
                patient #43, then drops both off at hospital #4, then picks up patients #102, #145, #241, #32 in that
                order then drops all of them off at hospital #1
        """
        res_hos = {}
        res_amb = {}
        counter = 0
        p_count = 0

        total_patients = len(self.patients)

        for hos_id, hos in self.hospitals.items():
            res_hos[hos_id] = {
                'xloc': self.patients[counter]['xloc'],
                'yloc': self.patients[counter]['yloc']
            }
            counter += 4

        for amb_id, amb in self.ambulances.items():
            if p_count < total_patients - 4:
                res_amb[amb_id] = [
                    'p' + str(i) for i in range(p_count, p_count + 4)
                ] + ['h' + str(self.ambulances[amb_id]['starting_hospital'])]
            else:
                res_amb[amb_id] = [
                    'h' + str(self.ambulances[amb_id]['starting_hospital'])
                ]
            p_count += 4

        return (res_hos, res_amb)
Example #13
0
class NoTippingClient(object):
    def __init__(self, name, is_first):
        self.first_resp_recv = False
        self.name = name
        self.client = SocketClient(HOST, PORT)
        self.client.send_data(
            json.dumps({
                'name': self.name,
                'is_first': is_first
            }))
        response = json.loads(self.client.receive_data())
        self.board_length = int(response['board_length'])
        self.num_weights = int(response['num_weights'])
        self.myWeight = dict()
        self.is_first = is_first
        for i in range(1, int(self.num_weights) + 1):
            self.myWeight[i] = 1

        if is_first:
            self.position = -1
        else:
            self.position = -2

        self.nextWeight = 1

    def play_game(self):
        # pass
        response = {}
        while True:
            response = json.loads(self.client.receive_data())
            if 'game_over' in response and response['game_over'] == "1":
                print("Game Over!")
                exit(0)

            # Indices start at zero but are actually
            board_state = [
                int(state) for state in filter(
                    None, list(response['board_state'].split(' ')))
            ]

            if response['move_type'] == 'place':
                position, weight = self.place(board_state)
                self.client.send_data(
                    json.dumps({
                        "position": position,
                        "weight": weight
                    }))
            else:
                position = self.remove(board_state)
                self.client.send_data(json.dumps({"position": position}))

    def place(self, board_state):
        """
        PLACE YOUR PLACING ALGORITHM HERE
        
        Inputs:
        board_state - array of what weight is at a given position on the board

        Output:
        position (Integer), weight (Integer)
        """
        # position = randint(-self.board_length, self.board_length)
        # weight = self.myWeight[randint(1, self.num_weights)]
        # num_tries = 0
        # self.check_balance(self.copy_board_with_updated_move(board_state, position, weight))
        # # import pdb; pdb.set_trace()
        # while board_state[(position + self.board_length) % self.board_length] != 0 and self.myWeight[weight] != 1 and num_tries < 10 and not self.check_balance(self.copy_board_with_updated_move(board_state, position, weight)):
        #     import pdb; pdb.set_trace()
        #     position = randint(-self.board_length, self.board_length)
        #     weight = self.myWeight[randint(1, self.num_weights)]
        #     num_tries += 1

        # self.myWeight[weight] = 0
        sleep(2)

        curr_position, weight = self.position, self.nextWeight
        while board_state[(curr_position + self.board_length) %
                          self.board_length] != 0:
            # import pdb; pdb.set_trace()
            curr_position += 1 if self.is_first else -1

        self.position = curr_position
        self.nextWeight = weight + 1

        return curr_position, weight

    def remove(self, board_state):
        """
        PLACE YOUR REMOVING ALGORITHM HERE
        
        Inputs:
        board_state - array of what weight is at a given position on the board

        Output:
        position (Integer)
        """
        position = randint(-self.board_length, self.board_length)

        while board_state[str(position)] != 0:
            position = randint(-self.board_length, self.board_length)

        return position

    def copy_board_with_updated_move(self, old_board, position, weight):
        new_board = old_board.copy()
        new_board[position] = weight
        return new_board

    def check_balance(self, board):
        left_torque = 0
        right_torque = 0
        for i in range(0, 61):
            left_torque += (i - 30 + 3) * board[i]
            right_torque += (i - 30 + 1) * board[i]
        left_torque += 3 * 3
        right_torque += 1 * 3
        return left_torque >= 0 and right_torque <= 0
Example #14
0
class NoTippingClient(object):
    def __init__(self, name, is_first):
        self.first_resp_recv = False
        self.name = name
        self.client = SocketClient(HOST, PORT)
        self.client.send_data(
            json.dumps({
                'name': self.name,
                'is_first': is_first
            }))
        response = json.loads(self.client.receive_data())
        self.board_length = response['board_length']
        self.num_weights = response['num_weights']
        self.magic_point = min(int(self.num_weights),
                               min(5, math.floor(int(self.num_weights) / 2)))
        self.myWeight = dict()
        self.place_turn = 0  #self turns
        self.remove_turn = 0  #self turns

        for i in range(1, int(self.num_weights) + 1):
            self.myWeight[i] = 1

    def play_game(self):
        # pass
        response = {}
        while True:
            response = json.loads(self.client.receive_data())
            if 'game_over' in response and response['game_over'] == "1":
                print("Game Over!")
                exit(0)

            self.board_state = [
                int(state) for state in filter(
                    None, list(response['board_state'].split(' ')))
            ]

            if response['move_type'] == 'place':
                position, weight = self.place(self.board_state)
                self.client.send_data(
                    json.dumps({
                        "position": position,
                        "weight": weight
                    }))
                self.place_turn = self.place_turn + 1
            else:
                position = self.remove(self.board_state)
                self.client.send_data(json.dumps({"position": position}))
                self.remove_turn = self.remove_turn + 1

    def check_balance(self, board_state):
        left_torque = 0
        right_torque = 0

        for i in range(0, 61):
            left_torque += (i - 30 + 3) * int(self.board_state[i])
            right_torque += (i - 30 + 1) * int(self.board_state[i])
        left_torque += 3 * 3
        right_torque += 1 * 3

        return left_torque >= 0 and right_torque <= 0

    def find_place_position(self, key, board_state):
        for i in range(0, 61):
            if self.board_state[i] == 0:
                self.board_state[i] = key
                if self.check_balance(self.board_state):
                    self.board_state[i] = 0
                    return i
                self.board_state[i] = 0
        return -100

    def possible_remove_moves(self, board):
        possible_positions = []

        for i in range(0, 61):
            if self.board_state[i] != 0:
                tempWeight = self.board_state[i]
                self.board_state[i] = 0

                if self.check_balance(self.board_state):
                    possible_positions.append(i - 30)
                self.board_state[i] = tempWeight

        if len(possible_positions) == 0:
            return 1

        best_position = 100

        for i in possible_positions:
            if abs(i) < abs(best_position):
                best_position = i

        self.board_state[i + 30] = 0

        return best_position

    #returns a list from right to left of the board weights in increasing order
    def possible_moves(self, board):
        moves = []
        potential_last_move = 0
        potential_last_weight = 0

        for i in range(0, 61):
            for j in self.myWeight:
                if self.myWeight[j] == 1:
                    potential_last_weight = j

                    if self.board_state[i] == '0' or self.board_state[i] == 0:
                        potential_last_move = i
                        self.board_state[i] = j

                        if self.check_balance(self.board_state):
                            move = {}
                            move['position'] = i
                            move['weight'] = j
                            moves.append(move)

                        self.board_state[i] = 0

        last_move = {
            "position": potential_last_move,
            "weight": potential_last_weight
        }
        moves.append(last_move)

        return moves

    def place(self, current_board_state):
        """
        PLACE YOUR PLACING ALGORITHM HERE
        
        Inputs:
        current_board_state - array of what weight is at a given position on the board

        Output:
        position (Integer), weight (Integer)
        """
        moves = self.possible_moves(self.board_state)

        #hope this works
        if (self.place_turn == self.magic_point):
            smallest_position = 100
            largest_weight = 0

            for i in moves:
                if abs(i['position'] - 30) < smallest_position:
                    smallest_position = i['position'] - 30

            for i in moves:
                if i['position'] - 30 == smallest_position:
                    if i['weight'] > largest_weight:
                        largest_weight = i['weight']

            self.myWeight[largest_weight] = 0
            return smallest_position, largest_weight

        target_move = moves[
            0]  #should not be empty, and already furthest right with heaviest weight

        self.myWeight[target_move['weight']] = 0

        return target_move['position'] - 30, target_move['weight']

    def remove(self, current_board_state):
        """
        PLACE YOUR REMOVING ALGORITHM HERE
        
        Inputs:
        current_board_state - array of what weight is at a given position on the board

        Output:
        position (Integer)
        """

        moves = self.possible_remove_moves(self.board_state)

        return moves
Example #15
0
class Player(object):
    def __init__(self, name):
        self.name = name
        self.client = SocketClient(HOST, PORT)
        self.client.send_data(json.dumps({'name': self.name}))

    def play_game(self):
        buffer_size_message = json.loads(self.client.receive_data(size=2048))
        buffer_size = int(buffer_size_message['buffer_size'])
        game_state = json.loads(self.client.receive_data(size=buffer_size))
        self.patients = {
            int(key): value
            for key, value in game_state['patients'].items()
        }
        self.hospitals = {
            int(key): value
            for key, value in game_state['hospitals'].items()
        }
        self.ambulances = {
            int(key): value
            for key, value in game_state['ambulances'].items()
        }

        # Get hospital locations and ambulance routes
        (hos_locations, amb_routes) = self.your_algorithm()
        response = {
            'hospital_loc': hos_locations,
            'ambulance_moves': amb_routes
        }
        print('sending data')
        min_buffer_size = sys.getsizeof(json.dumps(response))
        print(min_buffer_size)
        print(response)

        buff_size_needed = 1 << (min_buffer_size - 1).bit_length()
        buff_size_needed = max(buff_size_needed, 2048)
        buff_size_message = {'buffer_size': buff_size_needed}
        self.client.send_data(json.dumps(buff_size_message))
        time.sleep(2)
        self.client.send_data(json.dumps(response))

        # Get results of game
        game_result = json.loads(self.client.receive_data(size=8192))
        if game_result['game_completed']:
            print(game_result['message'])
            print('Patients that lived:')
            print(game_result['patients_saved'])
            print('---------------')
            print('Number of patients saved = ' +
                  str(game_result['number_saved']))
        else:
            print('Game failed run/validate ; reason:')
            print(game_result['message'])

    def your_algorithm(self):
        """
        PLACE YOUR ALGORITHM HERE

        You have access to the dictionaries 'patients', 'hospitals', and 'ambulances'
        These dictionaries are structured as follows:
            patients[patient_id] = {'xloc': x, 'yloc': y, 'rescuetime': rescuetime}

            hospitals[hospital_id] = {'xloc': None, 'yloc': None, 'ambulances_at_start': [array of ambulance_ids]}

            ambulances[ambulance_id] = {'starting_hospital': hospital_id}

        RETURN INFO
        -----------
        You must return a tuple of dictionaries (hospital_locations, ambulance_routes). These MUST be structured as:
            hospital_locations[hospital_id] = {'xloc': x, 'yloc': y}
                These values indicate where you want the hospital with hospital_id to start on the grid

            ambulance_routes[ambulance_id] = {[array of stops along route]}
                This array follows the following rules:
                    - The starting location of each ambulance is known so array must start with first patient that
                      it must pick up (or hospital location that it will head to)
                    - There can only ever be up to 4 patients in an ambulance at a time so any more than 4
                      patient stops in a row will result in an invalid input
                    - A stop for a patient is a string starting with 'p' followed by the id of the patient i.e. 'p32'
                        + The 'p' can be uppercase or lowercase
                        + There can be no whitespace, i.e. 'p 32' will not be accepted
                    - A stop for a hospital is the same as the patient except with an 'h', i.e. 'h3'
                        + The 'h' can also be uppercase or lowercase

            Example:
                ambulance_routes[3] = ['p0', 'p43', 'h4', 'p102', 'p145', 'p241', 'p32', 'h1']

                This will be read as ambulance #3 starts at it's designated hospital, goes to patient #0, then to
                patient #43, then drops both off at hospital #4, then picks up patients #102, #145, #241, #32 in that
                order then drops all of them off at hospital #1
        """
        res_hos = {}
        res_amb = {}
        counter = 0
        p_count = 0

        total_patients = len(self.patients)

        ## create data for clustering
        locData = []
        for patient_id in self.patients:
            patient = self.patients[patient_id]
            locData.append((patient['xloc'], patient['yloc']))
        locData = np.array(locData)

        ## cluster
        kmeans = KMeans(n_clusters=5, random_state=0).fit(locData)

        ## assign hospitals
        labels = kmeans.labels_
        centers = kmeans.cluster_centers_
        clustering = {i: np.where(labels == i)[0] for i in range(5)}
        sorted_by_number_elements_cluster = sorted(clustering.items(),
                                                   key=lambda kv: len(kv[1]))

        ## creating res_hos [i.e. which hospital to place where, based on num of avail ambulances]
        hospitalsByNumber = {}
        for hospital_id in self.hospitals:
            hospitalsByNumber[hospital_id] = self.hospitals[hospital_id][
                'ambulances_at_start']
        sorted_by_number_ambulances = sorted(hospitalsByNumber.items(),
                                             key=lambda kv: len(kv[1]))
        ## cluster with min number of patients matched with hospital with min number of avail ambulances
        mappingCenterToAmbulances = {}
        for i in range(len(sorted_by_number_ambulances)):
            x, y = centers[sorted_by_number_elements_cluster[i][0]]
            res_hos[sorted_by_number_ambulances[i][0]] = {
                'xloc': int(x),
                'yloc': int(y)
            }
            mappingCenterToAmbulances[(
                int(x), int(y))] = sorted_by_number_ambulances[i][1]

        # can do this because labels are 0,1,2,3,4
        for i in range(len(clustering)):
            #print("clustering")
            cluster = clustering[i]
            #print(len(cluster))
            center = tuple(centers[i])
            center = (int(center[0]), int(center[1]))
            ambulancesOperatingInThisCluster = mappingCenterToAmbulances[
                center]
            ambulanceBucketPatient = self.radDivide(
                cluster, ambulancesOperatingInThisCluster, center)
            # decide on order for ambulance using search
            for ambulance_id in ambulanceBucketPatient:
                patientsToVisit = ambulanceBucketPatient[ambulance_id]
                sorted(patientsToVisit,
                       key=lambda patient_id: self.patients[patient_id][
                           'rescuetime'])
                #aa
                #print(ambulance_id)
                #print(center)
                #print(patientsToVisit)

                numBuckets = math.ceil(len(patientsToVisit) / 6)
                nn = len(patientsToVisit) / numBuckets
                globalOrder = []
                ii = 0
                tt = 0
                while ii < numBuckets:
                    #print(ii)
                    #print(nn)
                    ll = patientsToVisit[int(ii * nn):int((ii + 1) * nn)]
                    #print(ll)
                    order, tt = self.orderOfPatients(ll, center, tt)
                    #order.append(-1)
                    #order = [ll[x] if x is not -1 else -1 for x in order]
                    globalOrder += order
                    ii += 1

                #print("bestPath")
                #print(order)

                res_amb[ambulance_id] = self.parse(
                    globalOrder,
                    self.ambulances[ambulance_id]['starting_hospital'])
        return (res_hos, res_amb)

    def orderOfPatients(self, patientsToVisit, center, time):
        self.onPath = [0] * len(patientsToVisit)
        self.path = []
        self.bestPath = []
        self.pathLen = 0
        self.bestPathValue = 0
        self.timeT = 0
        visited = [0] * len(patientsToVisit)
        for i in range(len(patientsToVisit)):
            self.dfs(i, patientsToVisit, center, time)
        print("saved " + str(self.bestPathValue) + "/" +
              str(len(patientsToVisit)))
        #print(self.bestPath)
        return self.bestPath, time + self.timeT

    # nextPatientToSaveIndex might also cater hospital
    def dfs(self, nextPatientToSaveIndex, patientsToVisitIndices, center, ttt):
        self.path.append(nextPatientToSaveIndex)
        if nextPatientToSaveIndex != -1:
            self.onPath[nextPatientToSaveIndex] = 1
            self.pathLen += 1
        if self.pathLen == len(patientsToVisitIndices):
            translatedPath = [
                patientsToVisitIndices[x] if x is not -1 else -1
                for x in self.path
            ]
            translatedPath.append(-1)
            value, timetaken = self.peopleSaved(translatedPath, center, ttt)
            if value > self.bestPathValue:
                self.bestPath = copy.deepcopy(translatedPath)
                self.bestPathValue = value
                self.timeT = timetaken
        else:
            for i in range(len(patientsToVisitIndices)):
                if self.onPath[i] == 0:
                    self.dfs(i, patientsToVisitIndices, center, ttt)
            # hospital to hospital case
            if nextPatientToSaveIndex != -1:
                self.dfs(-1, patientsToVisitIndices, center, ttt)
        self.path.pop()
        if nextPatientToSaveIndex != -1:
            self.onPath[nextPatientToSaveIndex] = 0
            self.pathLen -= 1

    def dist(self, a, b):
        return int(abs(a[0] - b[0]) + abs(a[1] - b[1]))

    def canBeSaved(self, hosp, patient, time):
        return True

    def parse(self, order, hospital_id):
        return [('p' + str(x)) if x is not -1 else ('h' + str(hospital_id))
                for x in order]

    def radDivide(self, patientsIndexList, ambulances, hospital):
        num_ambulances = len(ambulances)
        num_patients = len(patientsIndexList)
        ret = {}
        angle = []
        for pID in range(0, num_patients):
            pat = self.patients[patientsIndexList[pID]]
            theta = math.atan2(pat['yloc'] - hospital[1],
                               pat['xloc'] - hospital[0])
            if theta < 0.0:
                theta += 2 * math.pi
            angle.append([patientsIndexList[pID], theta])
        angle = sorted(angle, key=lambda x: x[1])
        n = num_patients / num_ambulances
        for i in range(0, num_ambulances):
            ambID = ambulances[i]
            ambPat = []
            for j in range(int(i * n), int((i + 1) * n)):
                ambPat.append(angle[j][0])
            ret[ambID] = ambPat
        return ret

    def peopleSaved(self, path, hospital, tt):
        ret = 0
        time = 0
        locX = hospital[0]
        locY = hospital[1]
        p1, p2, p3, p4 = [-1] * 4
        for p in path:
            if p == -1:
                num_p = (p1 > -1) + (p2 > -1) + (p3 > -1) + (p4 > -1)
                time += self.dist([hospital[0], hospital[1]],
                                  [locX, locY]) + num_p
                locX = hospital[0]
                locY = hospital[1]
                if p4 != -1:
                    ret += self.saved(self.patients[p4], time + tt)
                if p3 != -1:
                    ret += self.saved(self.patients[p3], time + tt)
                if p2 != -1:
                    ret += self.saved(self.patients[p2], time + tt)
                if p1 != -1:
                    ret += self.saved(self.patients[p1], time + tt)
                p1 = -1
                p2 = -1
                p3 = -1
                p4 = -1
            else:
                if p4 != -1:
                    return -1, 0
                p4 = p3
                p3 = p2
                p2 = p1
                p1 = p
                time += self.dist(
                    [self.patients[p]['xloc'], self.patients[p]['yloc']],
                    [locX, locY]) + 1
                locX = self.patients[p]['xloc']
                locY = self.patients[p]['yloc']
        return ret, time

    def saved(self, pID, time):
        if time > pID['rescuetime']:
            return 0
        else:
            return 1
Example #16
0
class NoTippingClient(object):
    def __init__(self, name, is_first):
        self.first_resp_recv = False
        self.name = name
        self.client = SocketClient(HOST, PORT)
        self.client.send_data(
            json.dumps({
                'name': self.name,
                'is_first': is_first
            }))
        response = json.loads(self.client.receive_data())
        self.board_length = response['board_length']
        self.num_weights = response['num_weights']
        self.myWeight = dict()
        for i in range(1, int(self.num_weights)):
            self.myWeight[i] = 1

    def play_game(self):
        # pass
        response = {}
        while True:
            response = json.loads(self.client.receive_data())
            if 'game_over' in response and response['game_over'] == "1":
                print("Game Over!")
                exit(0)

            self.board_state = [
                0
            ] * 30 if not response else response['board_state'].split(' ')

            if response['move_type'] == 'place':
                position, weight = self.place(self.board_state)
                self.client.send_data(
                    json.dumps({
                        "position": position,
                        "weight": weight
                    }))
            else:
                position = self.remove(self.board_state)
                self.client.send_data(json.dumps({"position": position}))

    def place(self, board_state):
        """
        PLACE YOUR PLACING ALGORITHM HERE
        
        Inputs:
        current_board_state - array of what weight is at a given position on the board

        Output:
        position (Integer), weight (Integer)
        """

        allPosition = []
        for key, value in self.myWeight.items():
            if value == 1:
                position = self.find_place_position(key, self.board_state)
                if position != -100:
                    allPosition.append((key, position - 30))
                if position != -100:
                    allPosition.append((key, position - 30))
                    break
        if len(allPosition) == 0:
            choice = (1, 0)
        else:
            choice = random.choice(allPosition)
        self.myWeight[choice[0]] = 0
        print("Added: " + str(choice))
        return choice[0], choice[1]

    def remove(self, board_state):
        """
        PLACE YOUR REMOVING ALGORITHM HERE
        
        Inputs:
        current_board_state - array of what weight is at a given position on the board

        Output:
        position (Integer)
        """
        allPossiblePosition = []
        for i in range(0, 61):
            if self.board_state[i] != 0:
                tempWeight = self.board_state[i]
                self.board_state[i] = 0
                if self.check_balance(self.board_state):
                    allPossiblePosition.append(i - 30)
                self.board_state[i] = tempWeight
        if len(allPossiblePosition) == 0:
            choice = 1
        else:
            choice = random.choice(allPossiblePosition)
            random.jumpahead(1)
        print("Removed:" + str(choice))
        return choice

    def check_balance(self, board_state):
        left_torque = 0
        right_torque = 0
        for i in range(0, 61):
            left_torque += (i - 30 + 3) * self.board_state[i]
            right_torque += (i - 30 + 1) * self.board_state[i]
        left_torque += 3 * 3
        right_torque += 1 * 3
        return left_torque >= 0 and right_torque <= 0

    def find_place_position(self, key, board_state):
        for i in range(0, 61):
            if self.board_state[i] == 0:
                self.board_state[i] = key
                if self.check_balance(self.board_state):
                    self.board_state[i] = 0
                    return i
                self.board_state[i] = 0
        return -100