Skip to content

Instantly share code, notes, and snippets.

@ducc
Last active July 31, 2022 01:03
Show Gist options
  • Save ducc/68c2d80d9fa6ccfdf20ab77b26a4d3ce to your computer and use it in GitHub Desktop.
Save ducc/68c2d80d9fa6ccfdf20ab77b26a4d3ce to your computer and use it in GitHub Desktop.
mars rover written in jq
def parse_direction_name: {
name: .,
ordinal: (
if . == "N" then 0
elif . == "E" then 1
elif . == "S" then 2
elif . == "W" then 3
else error("invalid rover direction: " + .)
end
),
};
def parse_direction_ordinal: {
ordinal: .,
name: (
if . == 0 then "N"
elif . == 1 then "E"
elif . == 2 then "S"
elif . == 3 then "W"
else error("invalid direction ordinal: " + .)
end
),
};
def parse_position: split(" ") | {
x: .[0] | tonumber,
y: .[1] | tonumber,
direction: .[2] | parse_direction_name,
};
def parse_instruction: split("");
def parse_rover($x): {
position: $x | .a | .[($x | .b)+1] | parse_position,
instructions: $x | .a | .[($x | .b) +2] | parse_instruction,
};
def parse_inputs($a): {
plateau_size: $a | .[0],
rovers: $a | length | (. / 2) | (. - 1) | [range(.) | (. * 2)] | [parse_rover({ a: $a, b: .[]})],
};
def wrap_direction_ordinal: if . == -1 then 3 elif . == 4 then 0 else . end;
def turn_left: (.ordinal - 1) | wrap_direction_ordinal | parse_direction_ordinal;
def turn_right: (.ordinal + 1) | wrap_direction_ordinal | parse_direction_ordinal;
def update_direction: {
position: {
x: .position.x,
y: .position.y,
direction: (
if .instruction == "L" then (.direction | turn_left)
elif .instruction == "R" then (.direction | turn_right)
else .position.direction
end
),
},
instruction: .instruction,
};
def move_forward: (
if .direction.name == "N" then {x: .x, y: (.y + 1)}
elif .direction.name == "E" then {x: (.x + 1), y: .y}
elif .direction.name == "S" then {x: .x, y: (.y - 1)}
elif .direction.name == "W" then {x: (.x - 1), y: .y}
else error("invalid direction name: " + .direction.name)
end
);
def update_position: {
direction: .position.direction,
result: (
if .instruction != "M" then {x: .position.x, y: .position.y}
else .position | move_forward
end
)
} | {
position: {
direction: .direction,
x: .result.x,
y: .result.y,
},
};
def handle_instruction($instructions): {
direction: .position.direction,
instruction: $instructions | .[0],
position: .position,
} | update_direction | update_position;
def move_rover($instructions):
if ($instructions | length) == 0 then .
else handle_instruction($instructions) | move_rover($instructions | del(.[0]))
end;
def move_rovers: .rovers | .[] | move_rover(.instructions);
parse_inputs(.) | move_rovers
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment