You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
102 lines
2.2 KiB
102 lines
2.2 KiB
#!/usr/bin/env julia
|
|
|
|
using Test
|
|
|
|
struct Move
|
|
direction :: Char
|
|
count :: Int
|
|
end
|
|
|
|
mutable struct State
|
|
head_x :: Int
|
|
head_y :: Int
|
|
tail_x :: Int
|
|
tail_y :: Int
|
|
end
|
|
|
|
function parse_move(line)
|
|
parts = split(line, limit=2)
|
|
return Move(parts[1][1], parse(Int, parts[2]))
|
|
end
|
|
|
|
function read_moves(io)
|
|
return [parse_move(line) for line in readlines(io)]
|
|
end
|
|
|
|
function apply_move(state, direction)
|
|
if direction == 'U'
|
|
state.head_y += 1
|
|
elseif direction == 'D'
|
|
state.head_y -= 1
|
|
elseif direction == 'L'
|
|
state.head_x -= 1
|
|
elseif direction == 'R'
|
|
state.head_x += 1
|
|
end
|
|
x_diff = state.head_x - state.tail_x
|
|
y_diff = state.head_y - state.tail_y
|
|
if abs(x_diff) <= 1 && abs(y_diff) <= 1
|
|
return state
|
|
end
|
|
if abs(x_diff) <= 1
|
|
state.tail_x += x_diff
|
|
state.tail_y += sign(y_diff) * (abs(y_diff) - 1)
|
|
elseif abs(y_diff) <= 1
|
|
state.tail_y += y_diff
|
|
state.tail_x += sign(x_diff) * (abs(x_diff) - 1)
|
|
else
|
|
throw(DomainError("invalid state"))
|
|
end
|
|
return state
|
|
end
|
|
|
|
function get_visited(moves)
|
|
visited = Set{NTuple{2, Int}}()
|
|
state = State(0, 0, 0, 0)
|
|
push!(visited, (state.tail_x, state.tail_y))
|
|
for move in moves
|
|
for _ in 1:move.count
|
|
state = apply_move(state, move.direction)
|
|
push!(visited, (state.tail_x, state.tail_y))
|
|
end
|
|
end
|
|
return visited
|
|
end
|
|
|
|
function visited_map(visited)
|
|
(min_x, max_x) = extrema([t[1] for t in visited])
|
|
(min_y, max_y) = extrema([t[2] for t in visited])
|
|
nrows = max_y - min_y + 1
|
|
ncols = max_x - min_x + 1
|
|
vmap = zeros(Int, nrows, ncols)
|
|
for (x, y) in visited
|
|
vmap[nrows - (y - min_y), (x - min_x + 1)] = 1
|
|
end
|
|
return vmap
|
|
end
|
|
|
|
function test()
|
|
@testset "visited count" verbose=true begin
|
|
@test length(get_visited(read_moves("example.txt"))) == 13
|
|
@test length(get_visited(read_moves("input.txt"))) == 6037
|
|
end
|
|
end
|
|
|
|
function main()
|
|
if size(ARGS, 1) == 0
|
|
test()
|
|
else
|
|
infile = ARGS[1]
|
|
println("infile = ", infile)
|
|
moves = read_moves(infile)
|
|
println("moves: ", moves)
|
|
visited = get_visited(moves)
|
|
println("visited: ", visited)
|
|
println("count : ", length(visited))
|
|
display(visited_map(visited))
|
|
println()
|
|
end
|
|
end
|
|
|
|
main()
|