14
\$\begingroup\$

Your task is to write a computer program such that when it is cut up into lines (split on the newline character) every arrangement of the lines will output a different number between 1 and n! (where n is the total number of lines). No number should be output by two different arrangements and every arrangement should output a number on this range. Since there are n! ways to arrange the lines of a program this means each number should be output by one rearrangement.

For example the python program

print 1;"""
print 2;"""

Has two arrangements

print 1;"""
print 2;"""

and

print 2;"""
print 1;"""

The first outputs 1 and the second outputs 2.

You may use whatever output formats are standard in the language you are using. You may not assume any sort of boilerplate. I think this challenge is more interesting if you have to work around whatever formats the language insists on.

Scoring

Your score will be the number of lines in your program with a higher score being better. You may choose to output numbers from 0 to n!-1 if you would like.

\$\endgroup\$
18
  • 3
    \$\begingroup\$ What about answers that present constructions which work for any n? Are they all tied at a score of ∞? \$\endgroup\$ Commented Feb 8, 2018 at 21:00
  • \$\begingroup\$ @MartinEnder Yes. ∞ is a fine score. If you find a construction like that then you win. \$\endgroup\$
    – Wheat Wizard
    Commented Feb 8, 2018 at 21:01
  • \$\begingroup\$ @AdmBorkBork Yes each arrangement should output one number. Could that be clearer? \$\endgroup\$
    – Wheat Wizard
    Commented Feb 8, 2018 at 21:02
  • 1
    \$\begingroup\$ @totallyhuman Standard output rules for whatever language you are using. I'll update the question to be completely clear on this. \$\endgroup\$
    – Wheat Wizard
    Commented Feb 8, 2018 at 21:07
  • 1
    \$\begingroup\$ @EriktheOutgolfer No tie breaker. Martin may have found a way to score infinity in CJam but there are plenty of other languages to try on. \$\endgroup\$
    – Wheat Wizard
    Commented Feb 8, 2018 at 21:11

8 Answers 8

7
\$\begingroup\$

CJam, score: ∞

Each line is of the form

];Lx+:L{__(f<0+:+\,,(;1+:**\(;}h]:+

where x is a number from 0 to n-1. The result is in the range 0 to n!-1.

Try it online! (For n=3.)

Credits to jimmy23013 for the code that computes the actual permutation index. I've only replaced the bit that reads the input with ];Lx+:L which discards the result from the previous line and then adds the index of the current line to the variable L (which is initially an empty array).

\$\endgroup\$
1
  • \$\begingroup\$ Oh, I did write that. But it doesn't look golfy... (for example the 0+:+) I think you can get a much shorter version using ,m!#. \$\endgroup\$
    – jimmy23013
    Commented Mar 20, 2018 at 3:34
4
\$\begingroup\$

Perl: ∞

$z.="-1,";$_.=A;END{$m.=!!s/./{${z}B}/g,map(/B/||s/\d+\K/,/g*/(-\d*,).*\1/||($n{$_}||=$m++),sort glob),print$n{$z}if/A/}
$z.="-2,";$_.=A;END{$m.=!!s/./{${z}B}/g,map(/B/||s/\d+\K/,/g*/(-\d*,).*\1/||($n{$_}||=$m++),sort glob),print$n{$z}if/A/}
$z.="-3,";$_.=A;END{$m.=!!s/./{${z}B}/g,map(/B/||s/\d+\K/,/g*/(-\d*,).*\1/||($n{$_}||=$m++),sort glob),print$n{$z}if/A/}

Extend to any length you like

Will quickly run out of memory since memory usage is like O(n^n). It would however be easy to replace the permutation indexer by O(n) code, just longer. I'm just illustrating the way you can use END{} for this task in perl. All END{} blocks run at exit time, but only the first one that get called (the one last in the code) will output anything due to the /A/ test which is only true once

Notice that the $m counter must count as a string because as a number it would overflow (later than the end of the universe but it's the principle that counts). For the same reason I "count" the number of lines by constructing a string of As instead of using a real counter though this overflow would happen even later.

Another way to do this in perl:

@{$b.=A; if($a eq $b) {use bigint; $n=0;$n++for@F;$c=0;$c=$c*$n--+map{$z=$_;$a=grep$_&&$_>$z,@F;$_=0;}@F;print$c}}=()x push@F,"1".!($a.=A),
@{$b.=A; if($a eq $b) {use bigint; $n=0;$n++for@F;$c=0;$c=$c*$n--+map{$z=$_;$a=grep$_&&$_>$z,@F;$_=0;}@F;print$c}}=()x push@F,"2".!($a.=A),
@{$b.=A; if($a eq $b) {use bigint; $n=0;$n++for@F;$c=0;$c=$c*$n--+map{$z=$_;$a=grep$_&&$_>$z,@F;$_=0;}@F;print$c}}=()x push@F,"3".!($a.=A),

This uses that fact that in foo = bar bar is executed after foo. This version by the way doesn't go crazy in time and space but that makes the code longer

Yet another idea is to use DESTROY which has the advantage that only one of them will be executed. I'm not going to repeat the permutation indexing code of which I already gave two examples.

push@F,"1";bless\@F;DESTROY{print"Work out permutation index of @{$_[0]}\n" }
push@F,"2";bless\@F;DESTROY{print"Work out permutation index of @{$_[0]}\n" }
push@F,"3";bless\@F;DESTROY{print"Work out permutation index of @{$_[0]}\n" }

Or using BEGIN:

BEGIN{push@F,"1"} print"Work out permutation index of @F\n"; exit;
BEGIN{push@F,"2"} print"Work out permutation index of @F\n"; exit;
BEGIN{push@F,"3"} print"Work out permutation index of @F\n"; exit;
\$\endgroup\$
0
3
\$\begingroup\$

Jelly, ∞

;3ÇQŒ¿$⁼Q$?
;2ÇQŒ¿$⁼Q$?
;1ÇQŒ¿$⁼Q$?

(Example with n=3.)

Try it online!

23 13 11 bytes per line.

For a program with n lines, the lines will have the format

; <i> ÇQŒ¿$⁼Q$?

where <i> represents the number literal i and each line has a different value for i ranging from 1 to n. (The values for i don't actually have to be these specific numbers, they just have to have unique positive values.) This program no longer uses n in the line structure.

How?

  • Without an argument Jelly starts with 0.
  • ;1 appends 1 to 0 or the active list.
  • ⁼Q$ is the conditional monad for the if statement (?) that checks whether the list's elements are unique. If they are, the link above is called (Ç) and another number is appended to the list. If they are not unique, that means we have wrapped around to the first link. The repeated element is removed from the list (Q) and the index of the permutation is found (Œ¿). Note that there is a 0 at the beginning of the list when Œ¿ is taken but it does not affect the output since the values for i are all positive.

New Jelly feature

With the newly added Ƒ quick, we can reduce ⁼Q$ to , saving a byte.

10 bytes/line (for single digits)

;1ÇQŒ¿$QƑ?

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Brain-Flak, 3

(({}){})
({}())
(()(){([()()]{})()(){[()()](<{}>)}}{})

Try it online!

I posted this in chat earlier but hopefully by posting it here people can build off of it.

Explanation

We start with the basic program

(({}){})
({}())

This scores 2 on its own. In order to step up to the next level I want to add a new line. My begining guess was

(()(){[()()]{}(<()>)}{})

This sets the TOS to 2 if it it is zero and does nothing otherwise. This actually is a good start. With the other two lines we are able to get all the numbers from 1 to 6 except 4, because there are 2 ways to output 2:

({}())
(({}){})
(()(){[()()]{}(<()>)}{})

and

({}())
(()(){[()()]{}(<()>)}{})
(({}){})

In order to remedy this we make our line also set 2 to be 4. This can be done with

(()(){([()()]{})()(){[()()](<{}>)}}{})

For clarity this basically implements the Haskell function

f 0 = 2
f 2 = 4
f x = x

This fixes our problem because one of the programs that was previously outputting 2 now outputs 4 with no other program changing.

\$\endgroup\$
2
\$\begingroup\$

Java 7, score: ∞

public class DerangedRearrangements implements B{public void a(){System.out.println("0");}public static void main(String[]a)throws Exception{java.util.regex.Pattern p=java.util.regex.Pattern.compile("^(?:public )?class ([\\w]+).*");java.io.BufferedReader r=new java.io.BufferedReader(new java.io.FileReader("./DerangedRearrangements.java"));String line; while((line=r.readLine())!=null){java.util.regex.Matcher m=p.matcher(line);if(m.matches()){((B)Class.forName(m.group(1)).getDeclaredConstructor().newInstance()).a();}}}}interface B{void a();}
class b1 implements B{public void a(){System.out.println(getClass().getName().substring(1));}}

Try it online!

This is can print out 0 to n!-1. Additional lines are of the following format (where INDEX is a number from 1 to n!-1):

class b<INDEX> implements B{public void a(){System.out.println(getClass().getName().substring(1));}}

This method works by reading its own source in order to determine the order classes are listed in it. Unfortunately there was no cooler method I could find by parsing the compiled file or creating a custom ClassLoader thanks to how java does JIT compilation. I suppose I could have each additional class just print out a statically defined number but this seemed more fun. That would also make it so I could remove the B interface but the scoring isn't based on bytes so I'll leave that in for fun.

How it works (high level):

Reads its own source code line by line. Since each line declares a new class, we use reflection to create an instance of the new class and invoke it's a method which it needs to have because it implements the B interface.

\$\endgroup\$
1
\$\begingroup\$

Ruby, score: ∞

(a||=[])<<2;a.size<3?0:(p 1+a.sort.permutation.to_a.index(a))
(a||=[])<<1;a.size<3?0:(p 1+a.sort.permutation.to_a.index(a))
(a||=[])<<3;a.size<3?0:(p 1+a.sort.permutation.to_a.index(a))

Try it online!

This program has 61 bytes per line (for n<10). It has the same basic format as dylnan's solution; the first number in each line will be a different value between 1 and n, and the second number in each line will be n.

I was hoping to find a way to avoid including n in the program, but I couldn't find one.

\$\endgroup\$
1
\$\begingroup\$

Brain-Flak, 2 (with -d)

{}(@ltN)

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ For 2 you can use ({}()) and (({}){}). \$\endgroup\$
    – Wheat Wizard
    Commented Feb 9, 2018 at 19:38
  • \$\begingroup\$ @WheatWizard trying to make expandable format \$\endgroup\$
    – user63187
    Commented Feb 9, 2018 at 19:40
0
\$\begingroup\$

05AB1E, score: 1,114,112

0ˆ¯JD{œsk
1ˆ¯JD{œsk
2ˆ¯JD{œsk

Try it online! 0-indexed. The ˆ at the start of each line pushes the distinct characters to the global array. The rest of the code is uselessly executed except on the last line, where it concatenates the values into a string, then finds its permutation index. 1,114,112 is the number of possible Unicode characters at time of writing (code points 48-57 are the easiest to demonstrate with of course).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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