Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Write the shortest program possible such that when you combine the first character and every Nth character after it into a new program, the output is N. This must work for N = 1, 2, ..., 16.

Another way to say it is, if you remove all the characters from your program except for the first one and every Nth one after that, the output of the remaining code should be N.

Example

If your code was

ABCDEFGHIJKLMNOP

N = 1 results in ABCDEFGHIJKLMNOP. Running this should output 1.
N = 2 results in ACEGIKMO. Running this should output 2.
N = 3 results in ADGJMP. Running this should output 3.
N = 4 results in AEIM. Running this should output 4.
N = 5 results in AFKP. Running this should output 5.
N = 6 results in AGM. Running this should output 6.
N = 7 results in AHO. Running this should output 7.
N = 8 results in AI. Running this should output 8.
N = 9 results in AJ. Running this should output 9.
N = 10 results in AK. Running this should output 10.
N = 11 results in AL. Running this should output 11.
N = 12 results in AM. Running this should output 12.
N = 13 results in AN. Running this should output 13.
N = 14 results in AO. Running this should output 14.
N = 15 results in AP. Running this should output 15.
N = 16 results in A. Running this should output 16.

Details

  • All characters are allowed, ASCII and non-ASCII. (Newlines and unprintable ASCII are allowed as well. Note that carriage return and line feed count as distinct characters.)
  • Your score is the length in characters of your unaltered program (15 in example). The lowest score wins.
  • A score below 16 is clearly impossible because then at least two of the altered programs would be identical.
  • Output may be to a file or stdout or anything else reasonable. However, the output of the 16 different programs must all go to the same place (e.g. it's not ok if AO goes to stdout but A goes to a file). There is no input.
  • The output must be in decimal, not hex. The actual output should only contain the 1 or 2 characters that make up the number from 1 to 16, nothing else. (Things like Matlab's ans = are ok.)
  • Your program does not have to work for N = 17 or above.
share|improve this question
    
Your stance on comments in the program? Yay or nay? –  AndoDaan Aug 19 at 3:41
    
@AndoDaan Yay . –  Calvin's Hobbies Aug 19 at 3:47
    
Welcome back! =) I had to stare a while before realizing that this was indeed asked, not edited by Calvin Hobbies. –  bitpwner Aug 19 at 3:48
2  
Yay, so you didn't leave us after all! :D –  Doorknob Aug 19 at 4:02
3  
It looks like when code is ABCDEFGHIJKLMNO and N = 15, result code is just A. –  Snack Aug 19 at 4:54

6 Answers 6

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`) < 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:

  1. Start with a hash.
  2. Append a new line i with the print i command and i - 1 hashes in between each two neighboring characters.
  3. 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)<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.

share|improve this answer
3  
The character is usually called "hash" (or "octothorpe" if you feel fancy, or "number sign") –  FireFly Aug 19 at 11:43
    
Nice work! Using Ruby you could shorten it a lot by using p 1 instead of print 1. –  Calvin's Hobbies Aug 19 at 17:07
1  
Yes, absolutely! In terms of code golf this might be Python's major weakness. - But thanks to AndoDaan's 5765776-character solution my code length is still far beyond average! :) –  Falko Aug 19 at 17:09

Befunge 93 - Five million seven-hundred sixty-five thousand and seven-hundred and seventy six characters

I demand to be taken seriously...

v                                                                               &(720 720 - 80) X SPACE
""""""""""""""""                                                                &(720 720 - 80) X SPACE
1234567890123456                                                                &(720 720 - 80) X SPACE
"""""""""1111111                                                                &(720 720 - 80) X SPACE
,,,,,,,,,"""""""                                                                &(720 720 - 80) X SPACE
@@@@@@@@@,,,,,,,                                                                &(720 720 - 80) X SPACE
         ,,,,,,,                                                                &(720 720 - 80) X SPACE
         @@@@@@@                                                                &(720 720 - 80) X SPACE

3 reasons why. 1st reason: a befunge script is always 80x25, so no matter what, there had to be something that got reduced on the lines with code. 2nd reason: why that something is about 5.5 million spaces is because 720 720 is the smallest common multiple of 1 to 16... Means there will be no wrap around mess when we're skipping characters. 3rd reason: wow, this is pretty absurd.

share|improve this answer

209 characters (Various languages)

I just tried to keep things simple and avoid putting anything in positions with a lot of prime factors. The advantage is an ability to run in many scripting languages. It should work in any language that is not deliberately perverse and has the following features:

  • Integer literals
  • Basic arithmetic operators +, - (subtraction and negation), *, /
  • Prints the evaluation of a bare expression
  • Has a single character that begins a line comment

For example,

Python 2 command-line interpreter (though not from a file):

+                1 #            4 /   23      #    #   5            #            9   #            7   6 *         #    # -        5     2   *  -        ##  2        6   #2                     *   2       6   4

MATLAB (simply replace '#' with '%'):

                 1 %            4 /   23      %    %   5            %            9   %            7   6 *         %    % -        5     2   *  -        %%  2        6   %2                     *   2       6   4

N.B. There should be 17 spaces preceding the first '1'. You guys know a lot of languages, so please help me list more that it could run in ( :

EDIT: Added unary + at position 0 for Python to avoid the line being indented.

share|improve this answer
    
Spyder throws an IndentationError run in the command line. But maybe you didn't use the correct markdown syntax when posting the code here. –  Falko Aug 19 at 13:45
    
As I feared the number of spaces turned out wrong, but now it is fixed. @Falko Each program should be all on one line so I don't think the missing spaces should cause an indentation error. Maybe your interpreter demands that everything be left aligned, or maybe the program for each number needs to be run separately instead of all together. –  feersum Aug 19 at 15:21
    
My interpreter expects the first line to start at the very beginning. So your code can't be executed. –  Falko Aug 19 at 15:50
    
I'm getting unexpected indent in the Python 2.7 console as well. But it works in Matlab so no worries. I believe it also works in Ruby. –  Calvin's Hobbies Aug 19 at 15:51
    
Oops sorry Falko and Calvin's Hobbies, you are right it didn't work. But I've managed to circumvent the error by changing the first character to '+'. –  feersum Aug 19 at 22:28

CJam, 89 bytes

GiiAHH(5A5(7ii)ii;(;(-i((i(-i)i)ii)i()i((i(i(iiii(iii(iiiii(iiiii(i-i(iiiiiii(ii(ii(-ii-

This approach doesn't use any kind of comments.

i casts to integer, so it is a noop here. It could be replaced by whitespace, but the letters seem more readable to me...

Try it online by executing the following Code:

G,{)
"GiiAHH(5A5(7ii)ii;(;(-i((i(-i)i)ii)i()i((i(i(iiiii(iii(iiiii(iiiii(i-i(iiiiiii(ii(ii(-ii-"
%_~}%N*

Example run

$ cat nth-char.cjam 
G,{)"GiiAHH(5A5(7ii)ii;(;(-i((i(-i)i)ii)i()i((i(i(i
iii(iii(iiiii(iiiii(i-i(iiiiiii(ii(ii(-ii-"%_~}%N*N
$ cjam nth-char.cjam 
GiiAHH(5A5(7ii)ii;(;(-i((i(-i)i)ii)i()i((i(i(i
iii(iii(iiiii(iiiii(i-i(iiiiiii(ii(ii(-ii-
1
GiH(A(i)i((i((iii)(i(((
i(i(ii(ii(-(iii(ii(i-
2
GA(5ii(-(-ii(((iii(i(i(iii(((i
3
GHAii((ii(((iii(i-iii(-
4
GH(i(iii(i(i(i(ii-
5
G(i((i((i(((i((
6
G5)-ii(iii(i(
7
GAi(i(iiiii-
8
G5(-(i(ii(
9
G((i((((i
10
G7ii(i(i-
11
Gi((i(i(
12
Gi((ii(
13
G)i(i((
14
Giii(i
15
Giiiii
16
share|improve this answer

GolfScript, 61 bytes

1})_#;#;;00123358_(_};}_}_}} _}_(__6
_})4_)_+)__(__}__;_}___6

This takes advantage of comments (#) and the undocumented "super-comments" (everything following an unmatched } it is silently ignored).

_ is a noop. It could be replaced by whitespace, but the underscores seem more readable to me...

Try it online.

Example run

$ cat nth-char.gs
16,{)"1})_#;#;;00123358_(_};}_}_}} _}_(__6
_})4_)_+)__(__}__;_}___6"\%.~}%n*
$ golfscript nth-char.gs
1})_#;#;;00123358_(_};}_}_}} _}_(__6
_})4_)_+)__(__}__;_}___6
1
1)##;0238(}}}} }(_
}4)+_(__;}_6
2
1_#025(;}}}_
)))(};_6
3
1#;28}} (
4+(_}6
4
1;05}_}64)__6
5
1#2(}}
)(;6
6
1;3; 6)_}
7
1;8}(4(}
8
10(}
);
9
10}}4_6
10
11}_+_
11
12}
(6
12
13})_
13
13 )}
14
15})6
15
18((
16
share|improve this answer

APL, 49

⌊⊃⍟○7⍟⍟1|/2111118 9⍝×-1 ×○3×4_5_×   1_   _⍝_⍝ __2

Altered programs

1  ⌊⊃⍟○7⍟⍟1|/2111118 9⍝×-1 ×○3×4_5_×   1_   _⍝_⍝ __2
2  ⌊⍟7⍟|21189×1×345× 1  ⍝⍝_2
3  ⌊○⍟/119-××5 1 ⍝ 2
4  ⌊7|18××4×1 ⍝2
5  ⌊⍟21×○5   
6  ⌊⍟19×51⍝2
7  ⌊11-4 ⍝
8  ⌊|8×× 2
9  ⌊/9×1 
10 ⌊2×5 
11 ⌊11 ⍝
12 ⌊1×12
13 ⌊13 
14 ⌊14⍝
15 ⌊15 
16 ⌊8×2

Explaination

I'll start from the bottom as it would make explaining easier

There are two language feature of APL to keep in mind. One, APL has no operator precedence, statements are always evaluated right to left. Two, many APL functions behave quite differently depending if it is given one argument on its right (monadic) or two arguments on its left and right (dyadic).

Monadic is round down (floor function), Dyadic × is obviously multiplication, comments out rest of the line
This should make these obvious:

16 ⌊8×2
15 ⌊15 
14 ⌊14⍝
13 ⌊13 
12 ⌊1×12
11 ⌊11 ⍝
10 ⌊2×5 

9: ⌊/9×1
/ is Reduce. Basically it takes the function of the left and the array on the right, insert the function between every pair of elements of the array and evaluate. (This is called "fold" in some languages)
Here, the right argument is a scalar so / does nothing.

8: ⌊|8×× 2
Monadic × is the signum function and monadic | is the absolute value function So, × 2 evaluates to 1 and |8×1 is of course 8

7: ⌊11-4 ⍝ should be obvious

6: ⌊⍟19×51⍝2
Monadic is natural log
So, ⍟19×51 evaluates to ln(19×51) = 6.87626..., and rounds it down to 6

5: ⌊⍟21×○5
Monadic multiplies its argument by π
⍟21×○5 is ln(21×5π) = 5.79869...

4: ⌊7|18××4×1 ⍝2
Dyadic | is the mod function
×4×1 evaluates to 1, and 7|18×1 is 18 mod 7 = 4

3: ⌊○⍟/119-××5 1 ⍝ 2
Space-separated values is an array. Note that in APL, when most scalar functions are give array arguments, it is an implicit map.
Dyadic is log
So ××5 1, is signum of signum on 5 and 1, which gives 1 1, 119-1 1 is ¯118 ¯118 (¯ is just the minus sign. APL has to distinguish between negative numbers and subtraction), and ⍟/¯118 ¯118 is log-118(-118) = 1

2: ⌊⍟7⍟|21189×1×345× 1 ⍝⍝_2
You can work it out yourself

1: ⌊⊃⍟○7⍟⍟1|/2111118 9⍝×-1 ×○3×4_5_× 1_ _⍝_⍝ __2
This one consist of a more complicated use of /. If n is a number, F is a function, and A is an array, then nF/A takes each group of n consecutive entries of A and apply F/. For example, 2×/1 2 3 takes each pair of consecutive entries (which are 1 2 and 2 3) and apply ×/ to each group to give 2 6
So, 1|/2111118 9 just returns 2111118 9 (as it applies |/ to scalars). Then, ⍟○7⍟⍟ applies ln, then log7 to those numbers, then multiplies them by π and ln again. The numbers that come out the other side are 1.46424... 0.23972...
Here, is just used to select the first element of an array.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.