Thank your for the explanation! The modulo was a big piece that I was missing.
I still need to spend some time understanding how the math guarantees unique combinations of values, but I did figure out how to generate the series now (in Ruby).
(0..4).map do |b|
(0..4).map do |a|
(0..4).map do |x|
(a * x + b) % 5
end.join(" ")
end.join("\n")
end.join("\n\n").then { puts _1 }
EDIT: To make this line up with the document, I actually had to offset a by the value of b. I'm still not totally sure why this is necessary. (0..4).map do |b|
(0..4).map do |a|
(0..4).map do |x|
((a - b) * x + b) % 5
end.join(" ")
end.join("\n")
end.join("\n\n").then { puts _1 }