day 20 solution
parent
774759cbbd
commit
519bbbe38f
|
@ -0,0 +1,8 @@
|
|||
all: day20.beam
|
||||
erl -noshell -s day20 start -s init stop
|
||||
|
||||
day20.beam:
|
||||
erlc day20.erl
|
||||
|
||||
clean:
|
||||
rm -f day20.beam
|
|
@ -0,0 +1,124 @@
|
|||
-module(day20).
|
||||
-export([start/0, simulate_particle/6]).
|
||||
|
||||
process_input_string(Input)
|
||||
-> Lines = re:split(Input, "\n"),
|
||||
process_input_lines(Lines, 0, []).
|
||||
|
||||
process_input_lines([], _Index, Particles)
|
||||
-> Particles;
|
||||
process_input_lines([Line|Tail], Index, Particles)
|
||||
-> [Position,Velocity,Acceleration|_] = re:split(Line, ", "),
|
||||
PositionTuple = process_input_coordinate(Position),
|
||||
VelocityTuple = process_input_coordinate(Velocity),
|
||||
AccTuple = process_input_coordinate(Acceleration),
|
||||
process_input_lines(Tail, Index + 1, lists:append(Particles, [{ Index, PositionTuple, VelocityTuple, AccTuple }])).
|
||||
|
||||
process_input_coordinate(RawCoord)
|
||||
-> Coord = string:slice(RawCoord, 3, string:length(RawCoord) - 4),
|
||||
[X,Y,Z|_] = re:split(Coord, ","),
|
||||
{ XInt, _ } = string:to_integer(X),
|
||||
{ YInt, _ } = string:to_integer(Y),
|
||||
{ ZInt, _ } = string:to_integer(Z),
|
||||
{ XInt, YInt, ZInt }.
|
||||
|
||||
find_closest_particle(Particles)
|
||||
-> spawn_processors(Particles),
|
||||
get_processor_output(length(Particles)).
|
||||
|
||||
get_processor_output(Iterations)
|
||||
-> get_processor_output(Iterations, { -1, -1 }).
|
||||
|
||||
get_processor_output(Iterations, Result)
|
||||
when Iterations == 0 -> Result;
|
||||
get_processor_output(Iterations, Result)
|
||||
-> { _MinIndex, MinDistance } = Result,
|
||||
receive
|
||||
{ Index, Distance } when MinDistance == -1; Distance < MinDistance -> NewResult = { Index, Distance }, get_processor_output(Iterations - 1, NewResult);
|
||||
{ _Index, _Distance } -> get_processor_output(Iterations - 1, Result)
|
||||
end.
|
||||
|
||||
spawn_processors(Particles)
|
||||
-> Iterations = 1000,
|
||||
spawn_processors(Particles, Iterations).
|
||||
|
||||
spawn_processors([], _Iterations)
|
||||
-> true;
|
||||
spawn_processors([Head|Tail], Iterations)
|
||||
-> { Index, Position, Velocity, Acceleration } = Head,
|
||||
spawn(?MODULE, simulate_particle, [self(), Index, Position, Velocity, Acceleration, Iterations]),
|
||||
spawn_processors(Tail, Iterations).
|
||||
|
||||
simulate_particle(Parent, Index, Position, _Velocity, _Acceleration, Iterations)
|
||||
when Iterations == 0 -> { X, Y, Z } = Position,
|
||||
Distance = abs(X) + abs(Y) + abs(Z),
|
||||
Parent ! { Index, Distance };
|
||||
simulate_particle(Parent, Index, Position, Velocity, Acceleration, Iterations)
|
||||
-> { PX, PY, PZ } = Position,
|
||||
{ VX, VY, VZ } = Velocity,
|
||||
{ AX, AY, AZ } = Acceleration,
|
||||
NewVX = AX + VX,
|
||||
NewVY = AY + VY,
|
||||
NewVZ = AZ + VZ,
|
||||
NewV = { NewVX, NewVY, NewVZ },
|
||||
NewPX = NewVX + PX,
|
||||
NewPY = NewVY + PY,
|
||||
NewPZ = NewVZ + PZ,
|
||||
NewP = { NewPX, NewPY, NewPZ },
|
||||
simulate_particle(Parent, Index, NewP, NewV, Acceleration, Iterations - 1).
|
||||
|
||||
calc_collisions(Iterations, _Positions, BadParticles, TotalParticleCount)
|
||||
when Iterations == 0 -> io:fwrite("found ~p collided particles of ~p total particles, ~p remain~n", [length(BadParticles), TotalParticleCount, TotalParticleCount - length(BadParticles)]), BadParticles;
|
||||
calc_collisions(Iterations, Positions, BadParticles, TotalParticleCount)
|
||||
-> %io:fwrite("calculating collisions on ~p~n", [Iterations]),
|
||||
{ CheckPositions, NextPositions } = lists:partition(fun(X) -> { _Index, Iteration, _Position } = X, Iteration == Iterations end, Positions),
|
||||
%io:fwrite("check positions ~p~n", [CheckPositions]),
|
||||
{ _, FilteredPositions } = lists:partition(fun(X) -> { Index, _Iteration, _Position } = X, lists:any(fun(Y) -> Y == Index end, BadParticles) end, CheckPositions),
|
||||
CollidedPositions = lists:filter(fun(CheckPosition) ->
|
||||
{ Index, _Iteration, Position } = CheckPosition,
|
||||
{ X, Y, Z } = Position,
|
||||
lists:any(fun(NextPosition) ->
|
||||
{ OtherIndex, _OtherIteration, OtherPosition } = NextPosition,
|
||||
{ OtherX, OtherY, OtherZ } = OtherPosition,
|
||||
(Index /= OtherIndex) and (OtherX == X) and (OtherY == Y) and (OtherZ == Z)
|
||||
end, CheckPositions)
|
||||
end, FilteredPositions),
|
||||
%io:fwrite("collidedpositions ~p~n", [CollidedPositions]),
|
||||
Found = lists:map(fun(X) -> { Index, _Iteration, _Position } = X, Index end, CollidedPositions),
|
||||
calc_collisions(Iterations - 1, NextPositions, lists:append(BadParticles, Found), TotalParticleCount).
|
||||
|
||||
get_all_positions(_Particle, Steps, Positions)
|
||||
when Steps == 0 -> Positions;
|
||||
get_all_positions(Particle, Steps, Positions)
|
||||
-> { Index, Position, Velocity, Acceleration } = Particle,
|
||||
{ PX, PY, PZ } = Position,
|
||||
{ VX, VY, VZ } = Velocity,
|
||||
{ AX, AY, AZ } = Acceleration,
|
||||
NewVX = AX + VX,
|
||||
NewVY = AY + VY,
|
||||
NewVZ = AZ + VZ,
|
||||
NewV = { NewVX, NewVY, NewVZ },
|
||||
NewPX = NewVX + PX,
|
||||
NewPY = NewVY + PY,
|
||||
NewPZ = NewVZ + PZ,
|
||||
NewP = { NewPX, NewPY, NewPZ },
|
||||
get_all_positions({ Index, NewP, NewV, Acceleration }, Steps - 1, lists:append(Positions, [{ Index, Steps, NewP }])).
|
||||
|
||||
find_collided_particles(Particles)
|
||||
-> Iterations = 1000,
|
||||
Positions = lists:flatten(lists:map(fun(X) -> get_all_positions(X, Iterations, []) end, Particles)),
|
||||
calc_collisions(Iterations, Positions, [], length(Particles)).
|
||||
|
||||
start()
|
||||
-> Sample = "p=<3,0,0>, v=<2,0,0>, a=<-1,0,0>
|
||||
p=<4,0,0>, v=<0,0,0>, a=<-2,0,0>",
|
||||
io:fwrite("closest particle sample ~p~n", [find_closest_particle(process_input_string(Sample))]),
|
||||
{ ok, File } = file:read_file("input"),
|
||||
ProblemInput = process_input_string(unicode:characters_to_list(string:chomp(File))),
|
||||
io:fwrite("closest particle problem input ~p~n", [find_closest_particle(ProblemInput)]),
|
||||
Sample2 = "p=<-6,0,0>, v=<3,0,0>, a=<0,0,0>
|
||||
p=<-4,0,0>, v=<2,0,0>, a=<0,0,0>
|
||||
p=<-2,0,0>, v=<1,0,0>, a=<0,0,0>
|
||||
p=<3,0,0>, v=<-1,0,0>, a=<0,0,0>",
|
||||
io:fwrite("collided particle sample ~p~n", [find_collided_particles(process_input_string(Sample2))]),
|
||||
io:fwrite("collided particle problem input ~p~n", [find_collided_particles(ProblemInput)]).
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue