This week I wanted to start with a "normal" approach that felt pythonic with a particle class and a bunch of for loops / if statements, but still using numpy arrays. Then rewrite it with everything possible vectorized in numpy and see the difference in solve times for each.
Below is a 5000 particle simulation with 2000 time steps that took 0.66 s to solve for (and incidentally much longer to write to a .mp4 file).

Below is a 5000 particle simulation with 1000 time steps that took 0.18 s to solve for (and incidentally much longer to write to a .mp4 or .gif file).