Run the Nth characters to get N
Python - 1201 1137 (generator: 241 218) - Long live the hashes!

Strategy:

I tried to start every line with as many hashes as the desired output n. Then all other versions will skip this line completely.

The main difficulty, however, was to append the correct number of hashes so that the next run will hit the beginning of the next line exactly. Furthermore, interferences with other versions might occur, e.g. version 16 jumping right into the print command of line 5 and so on. So this was a lot of trial and error combined with a helper script for rapid testing.

Statistics:


Characters: 1201 1137
Hashes: 1066 1002 (88.1 %)
Non-hashes: 135 (11.9 %)


Code:

#
print 1#####
#p#r#i#n#t# #2######################
##p##r##i##n##t## ##3###
###p###r###i###n###t### ###4
####p####r####i####n####t#### ####5#########
#####p#####r#####i#####n#####t##### #####6##########
######p######r######i######n######t###### ######7###########
#######p#######r#######i#######n#######t####### #######8###
########p########r########i########n########t######## ########9##
#########p#########r#########i#########n#########t######### #########1#########0##
##########p##########r##########i##########n##########t########## ##########1##########1##
###########p###########r###########i###########n###########t########### ###########1###########2##
############p############r############i############n############t############ ############1############3##
#############p#############r#############i#############n#############t############# #############1#############4##
##############p##############r##############i##############n##############t############## ##############1##############5##
###############p###############r###############i###############n###############t############### ###############1###############6


Test script:

with open('printn.py', 'r') as f:
    c = f.read()

for n in range(1, 17):
    print "n =", n, "yields",
    exec c[::n]


Output:

n = 1 yields 1
n = 2 yields 2
n = 3 yields 3
n = 4 yields 4
n = 5 yields 5
n = 6 yields 6
n = 7 yields 7
n = 8 yields 8
n = 9 yields 9
n = 10 yields 10
n = 11 yields 11
n = 12 yields 12
n = 13 yields 13
n = 14 yields 14
n = 15 yields 15
n = 16 yields 16




Update: A generating script!

I thought about my solution and that there must be a pattern to generate it algorithmically. So here we go:

lines = ['#']
for i in range(1, 17):
    lines.append(('#' * (i - 1)).join('\nprint ' + `i`))
    fail = True
    while fail:
        while ''.join(lines)[::i].find('print ' + `i`) &lt; 0:
            lines[i] = '#' + lines[i]
        fail = False
        for n in range(1, 17):
            try:
                exec ''.join(lines)[::n]
            except:
                lines[i] = '#' + lines[i]
                fail = True
                break
print ''.join(lines)


It builds the program line by line:


Start with a hash.
Append a new line i with the print i command and i - 1 hashes in between each two neighboring characters.
While the "i-version" (every i-th character) of the current program does not contain the command print i (due to misalignment) or any n-version with n in range(1, 17) throws an exception, add another hash to the previous line.


It actually returned a shorter program than I found manually this morning. (So I updated my solution above.) Furthermore, I'm pretty sure there is no shorter implementation following this pattern. But you never know!

Golfed version - 241 218:

h='#';L=[h];I=range(1,17);J=''.join
for i in I:
 p='print '+`i`;L+=[(h*(i-1)).join('\n'+p)]
 while 1:
  while J(L)[::i].find(p)&lt;0:L[i]=h+L[i]
  try:
   for n in I:exec J(L)[::n]
   break
  except:L[i]=h+L[i]
print J(L)


Note that there might be a shorter generator, e.g. by hard-coding the required number of succeeding hashes for each line. But this one computes them itself and could be used for any N > 16.