A rail yard’s freight trains
A rail yard keeps each freight train as a doubly linked list of cars, and its yard tool holds handles to the cars it works on: the lesson’s worklist, with cars for jobs. The cars come from the checker’s plumbing, which counts every link read (each step along the train) and every link write, so the checker can tell a correct operation that walks from one that relinks, however the code is written. Each level starts from the previous level’s finished code, so you can begin at any of them.
Yard crews move whole blocks of coupled cars, all bound for one destination, from one place in a train to another. The yard tool holds handles to the block’s first and last car and the car to put it behind. A teammate added a block move that moves the block one car at a time.
Moving a block one car at a time rewrites six links per car, so a 400-car block costs 2,400 writes where six would do, and every intermediate state is a train nobody asked for.
Reproduce A train loco → boxcar → tanker → hopper: train.moveRunAfter(tanker, hopper, loco) gives loco → tanker → hopper → boxcar, correctly, but writes 11 links; six are enough.
Acceptance criteria The block move puts the cars from first to last, in their order, just after the anchor, or at the front when there is none. The cars around the block’s old place are joined, and the train walks the same both ways. Moving a block to where it already is changes nothing. It writes at most six links and reads only a handful, however many cars the block holds: the cars inside the block keep their links, and nothing walks the block. Notes Cases print the train walked from the locomotive (or, for a long train, its length and first cars), whether walking back agrees, and whether the move stayed within six link writes (and, for the long train, eight link reads). The plumbing counts the links as before: every read of a car’s previous or next link is a link read (one step along the train), and every assignment to one is a link write, whether or not it changes the value. The train’s head and tail are not counted. The block is given by its first and last car; the anchor is never inside the block. Keep the train’s fields and its methods’ names and signatures; the checker calls them.