Quit Whining; Start Quining
GolfScript, 16 bytes
{%}+")1$~":x`+0x
Try it online in Web GolfScript.
Example run
$ echo -n 3 | golfscript quining.gs
{3 % ")1$~"}0)1$~
$ echo -n 3 | golfscript quining.gs | golfscript
{3 % ")1$~"}1)1$~
$ echo -n 3 | golfscript quining.gs | golfscript | golfscript
{3 % ")1$~"}2)1$~
$ echo -n 3 | golfscript quining.gs | golfscript | golfscript | golfscript
{3 % ")1$~"}0)1$~
Generator
# (implicit) Read from STDIN.
{%}+ # Concatenate the read input with the block.
# For example, "3"{%}+ -> {3 %}.
")1$~":x # Push that string and save it in the the variable `x'.
`+ # Inspect the string and concatenate it with the block.
# For example, {3 %}'")1$~"'+ -> {3 % ")1$~"}
0x # Push a 0 and the string stored in `x'.
Modular quine
For example, the modular quine {3 % ")1$~"}0)1$~
works as follows.
{ } # Define a block.
3 % # Take the integer on the stack modulo 3.
")1$~" # Push that string.
0) # Push 0 and increment. Pushes 1.
1$~ # Copy the block from the bottom of the stack and execute it.
The original copy of the block, the modified integer and the string the block pushed are printed, resulting in {3 % ")1$~"}1)1$~
.
All printed programs have a trailing linefeed, which GolfScript prints automatically.
Ruby, 100 bytes + brownie points
Generating program/zero-state:
;puts <<2.sub(/2*/){$&[/./]?$':?2*gets.to_i}*2,2
;puts <<2.sub(/2*/){$&[/./]?$':?2*gets.to_i}*2,2
2
Output for input of 3:
222;puts <<2.sub(/2*/){$&[/./]?$':?2*gets.to_i}*2,2
222;puts <<2.sub(/2*/){$&[/./]?$':?2*gets.to_i}*2,2
2
This program, when run, will not ask for input but output itself with the initial 222 on the first 2 rows replaced with 22. That will output a version where each row begins with 2, which will output the original program.
"2" lives a varied life here as (in order of appearance) a repeated digit in a no-op numeric literal, a HEREDOC reference, a regex literal, a character literal, a numeric argument to String#*, a numeric argument to puts
, a character in a HEREDOC string, and finally a HEREDOC delimiter.
Python 3.8 (pre-release), 59 bytes
b=0;exec(s:=f"print('b=%d;exec(s:=%r)'%(-~b%{input()},s))")
Try it online!