Not sure if I've ever mentioned it on this site before, but I love macros! So, here's a solution that uses a recursive macro recording.
Starting from the top of the file, type:
Press "Return" here
How it Works
qqqqq # This is recursive macro boilerplate. It clears
# out the "q register by recording an empty
# macro, and then starts recording a macro into
# the same register
V # Start a linewise visual selection and
/ <CR> # Search for
\v # Using very magic, (so we don't need as many
# backslashes), match
( ) # a group, containing either
\nxxx$ # a newline, followed by "xxx", followed by the
# end of the line
| # or
%$ # the end of the file
d # Delete the visual selection
4+ # Move to the start of the fourth line down
@qq@q # More recursive macro boilerplate. This plays
# back the macro in the "q register, which
# currently does nothing, because it is empty,
# and then ends the recording. When you play
# back the macro later, the "q register now
# contains the macro, and so it will repeat
# until it hits an error.
When you are at the bottom of the file, attempting to move down four lines with
4+ will fail, causing the macro to stop.
Why You Might Prefer This Solution
The slight advantage this has over the OP's solution is that playing back a macro only adds a single entry to the undolist, so you can undo/redo all the changes with a single u/Ctrl-R. In order to fully take advantage of this, you will want to ensure all the edits are made by the macro playback, so after recording the macro, insert a single u undo.
i.e. At the end, instead of typing: