Created
March 13, 2024 14:12
-
-
Save pmusa/818b05fa1755278385cb96a6a5584b65 to your computer and use it in GitHub Desktop.
valencia_dev_dive_robot.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
import math | |
class Robot: | |
MAX_FUEL = 200 | |
BASE_X = 0 | |
BASE_Y = 0 | |
BASE = (BASE_X, BASE_Y) | |
CAR_WEIGHT = 5 | |
SAMPLE_WEIGHT = 10 | |
MAX_X = 40 | |
MIN_X = -40 | |
MAX_Y = 40 | |
MIN_Y = -40 | |
def __init__(self): | |
self.x = Robot.BASE_X | |
self.y = Robot.BASE_Y | |
self.fuel = Robot.MAX_FUEL | |
self.weight = Robot.CAR_WEIGHT | |
self.samples = 0 | |
self.total_samples = 0 | |
def move(self, destination): | |
dest_x, dest_y = destination | |
dx = dest_x - self.x | |
dy = dest_y - self.y | |
if not Robot.is_valid_destination(dest_x, dest_y): | |
print("Invalid destination. Skipping...") | |
return | |
dist_to_dest = abs(dx) + abs(dy) | |
fuel_to_dest = dist_to_dest * self.get_fuel_per_move() | |
# distance to base from the next destination | |
dist_to_base = abs(dest_x) + abs(dest_y) | |
fuel_to_base = dist_to_base * self.get_fuel_per_move(1) | |
self.print_status(fuel_to_dest + fuel_to_base) | |
if fuel_to_dest + fuel_to_base > self.fuel: | |
if self.x == Robot.BASE_X and self.y == Robot.BASE_Y: | |
print("Error: will run out of Fuel.") | |
return | |
print("Fuel is not sufficient. Returning to base to refuel...") | |
self.move(Robot.BASE) | |
self.refill() | |
print(f"Refueled. Resuming mission to coordinates x={dest_x};y={dest_y}") | |
self.move(destination) | |
else: | |
while dx != 0 or dy != 0: | |
if dx != 0: | |
self.x += int(math.copysign(1, dx)) | |
dx -= math.copysign(1, dx) | |
elif dy != 0: | |
self.y += int(math.copysign(1, dy)) | |
dy -= math.copysign(1, dy) | |
self.consume_fuel() | |
print(f'>{self.x};{self.y}') | |
def is_valid_destination(x, y): | |
return x >= Robot.MIN_X and x <= Robot.MAX_X and y >= Robot.MIN_Y and y <= Robot.MAX_Y | |
def get_fuel_per_move(self, extra_samples=0): | |
if not extra_samples: | |
extra_samples = 0 | |
return math.log10(self.weight + (extra_samples * Robot.SAMPLE_WEIGHT)) | |
def consume_fuel(self): | |
self.fuel -= self.get_fuel_per_move() | |
def print_status(self, fuel_needed): | |
print(f'Current location is x={self.x} y={self.y}') | |
print(f'Samples [total:{self.total_samples} current:{self.samples}] Weight:{self.weight}') | |
print(f'Fuel: {self.fuel} - Total fuel needed: {fuel_needed}') | |
def refill(self): | |
self.drop_samples() | |
self.fuel = Robot.MAX_FUEL | |
def collect_sample(self): | |
self.samples += 1 | |
self.total_samples += 1 | |
self.weight += Robot.SAMPLE_WEIGHT | |
def drop_samples(self): | |
print(f'Dropping {self.samples} sample(s).') | |
self.samples = 0 | |
self.weight = Robot.CAR_WEIGHT | |
def run_sequence(self, sequence): | |
destinations = sequence.split(">") | |
destinations.pop(0) # skip the first empty match. | |
print(f"Starting Delivery to {destinations}") | |
for dest_str in destinations: | |
x, y = map(int, dest_str.split(";")) | |
print("---------") | |
print(f"Going to coordinates x={x};y={y}") | |
self.move((x, y)) | |
if self.x == x and self.y == y: | |
self.collect_sample() | |
print(f"Sample collected! New weight: {self.weight}") | |
print("All destinations reached!") | |
print("Returning to base...") | |
self.move(Robot.BASE) | |
print("Returned to base. Dropping samples...") | |
self.drop_samples() | |
print("Samples dropped. Mission complete!") | |
if __name__ == "__main__": | |
if len(sys.argv) < 2: | |
print("Usage: python3 robot.py <sequence>") | |
sys.exit(1) | |
sequence = sys.argv[1] | |
robot = Robot() | |
robot.run_sequence(sequence) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment