Prolific Perfect Pangram Programs Pertaining to Printable ASCII

23

3

Updates: Time limit removed. You must be able to describe output - see new rule.

A pangram is a sentence that uses every letter in the alphabet at least once, such as:

The quick brown fox jumps over the lazy dog.

A perfect pangram uses every letter exactly once.

Consider writing a program that is a perfect pangram, using the 95 printable ASCII characters (hex codes 20 to 7E) as the alphabet:

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

Such a program must contain exactly 95 characters, with each printable ASCII character occurring exactly once, but in any order. (Thus there are 95! = 1.03×10148 possibilities.)

Your task is to write this program such that the number of printable ASCII characters printed to stdout is as high as possible (i.e. prolific).

Your score is the number of printable ASCII characters your program outputs (the total amount, not the distinct amount: AABC scores 4 whereas ABC scores 3). The highest score wins.

Details

  • The output may contain any characters (including duplicates) but only instances of the 95 printable ASCII characters count towards your score.
    • You can use this JSFiddle to count the number of printable ASCII characters in any string.
  • If your language does not have stdout use the most appropriate alternative.
  • Your program...
    • must have finite runtime (the time limit has been removed)
    • must have finite output
    • may contain comments
    • must compile and run without (uncaught) errors
    • must not prompt for or require input
    • must be time invariant and deterministic
    • must not use external libraries
    • must not require a network connection
    • must not make use of external files
      • (you may use the program file itself as long as changing the file name does not alter the program's behavior)
  • If this task is impossible is some language that's just too bad.
  • You must give your exact output or precisely describe it if it is too large to fit in a post. You do not actually have to run your program. As long as it would run in a finite amount of time on a computer with an unbounded amount of memory it is valid.

Example

This simplistic Python 2 program is a possible solution:

print 9876543210#!"$%&'()*+,-./:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghjklmoqsuvwxyz{|}~

It outputs 9876543210 which contains 10 printable ASCII characters, thus scoring 10.

Calvin's Hobbies

Posted 2014-10-10T00:17:02.590

Reputation: 84 000

14As amazingly admirable as alliteration appears, pangrams just pack a powerful punch, as they're quite vexing. – Geobits – 2014-10-10T01:36:05.323

2I just reread the total-not-distinct rule too. I'd skimmed over it earlier, concluding it was obviously a distinct-not-total rule since the alternative would lead to absurd constructions such as printing the letter a six quadrillion times, where it isn't even possible to obtain an accurate upper limit on character count. Anyway, I'm still proud of my 95, even if it is kind of small. Size isn't everything, you know. – COTO – 2014-10-10T05:50:26.313

Why do you think this task is impossible in HQ9+? – Peter Taylor – 2014-10-10T08:24:16.807

I'm going to try and do this in FORTRAN (so I can make use of the case insensitivity). --- AND scratch that. I need the letter O 4 times: 2 times for the program declaration and 2 times for my loop declaration. – Nzall – 2014-10-10T09:55:40.203

@COTO The problem with that is that is was too easy to get a perfect score, therefore not much of a contest. – Calvin's Hobbies – 2014-10-10T11:14:42.623

@PeterTaylor In the implementations I've seen any character besides HQ9+ throws an error. – Calvin's Hobbies – 2014-10-10T11:15:46.420

@Calvin'sHobbies: Indeed. I read the comments after submitting and discovered the shocking truth. ;) – COTO – 2014-10-10T12:41:07.813

I wish tab weren't forbidden to write the program itself... it would make other program than the cryptic ones possible :/ (see my answer)... (I wrote my first golfscript answer, but it fails on that rule) – Olivier Dulac – 2014-10-10T16:48:19.940

@OlivierDulac Then what would stop you from making a string of arbitrarily many tabs and printing it? 95 characters only. – Calvin's Hobbies – 2014-10-10T16:51:46.477

I wonder why you allowed comments in the program? – GreenAsJade – 2014-10-10T23:22:22.157

@GreenAsJade Why not? It would be a lot harder if not impossible in many languages without allowing them. And the better answers will presumably use as much real code as possible, not waste characters in comments. – Calvin's Hobbies – 2014-10-11T00:06:19.007

At first I thought this was impossible. Now I see the proliferation of answers, it strikes me that being allowed comments is cheating :) – GreenAsJade – 2014-10-11T01:58:51.127

Are there any limits on the CPU register size? – Dennis – 2014-10-11T13:39:28.107

1@Dennis No. 5more – Calvin's Hobbies – 2014-10-11T16:03:09.430

Answers

12

GolfScript, over 2↑↑↑(9871↑↑2) chars

2 9871.?,{;0$[45)63]n+*~}/
#!"%&'(-:<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ\^_`abcdefghijklmopqrstuvwxyz|

Prints an integer. Take advantage of unlimited CPU register size (which determines the maximum string length in Ruby), memory and run time. The linefeed is solely for readability.

The code

2             # Push 2.
9871.?        # Push b := 9871↑↑2 = 9871↑9871 = 9871**9871.
,{            # For each i from 0 to b - 1:
  ;0$         #   Discard i and duplicate the integer on the stack.
  [45)63]n+*  #   Replicate ".?\n" that many times.
  ~           #   Evaluate.
 }/           #

The score

Define b = 9871↑↑2 (see Knuth's up-arrow notation).

  • .? executes f : x ↦ x↑x.

  • The inner block executes g : x ↦ fx(x).

    Since f(x) = x↑x = x↑↑2, f2(x) = (x↑x)↑(x↑x) > x↑x↑x = x↑↑3,
    f3(x) = ((x↑x)↑(x↑x))↑((x↑x)↑(x↑x)) > (x↑x↑x)↑(x↑x↑x) > x↑x↑x↑x = x↑↑4 and so forth, we have
    g(x) > x↑↑(x+1) > x↑↑x.

  • The outer block executes h : x ↦ gb(x).

    Since g(x) = x↑↑x = x↑↑↑2, g2(x) = (x↑↑x)↑↑(x↑↑x) > x↑↑x↑↑x = x↑↑↑3,
    g3(x) = ((x↑↑x)↑↑(x↑↑x))↑↑((x↑↑x)↑↑(x↑↑x)) > (x↑↑x↑↑x)↑(x↑↑x↑↑x) > x↑↑x↑↑x↑↑x = x↑↑↑4 and so forth, we have h(x) > x↑↑↑(b+1).

  • We start with the integer 2 on the stack, so the code calculates h(2) > 2↑↑↑(b+1).

  • The score is the number of decimal digits of h(2), which is log(h(2)) + 1 > log(2↑↑↑(b+1)) > 2↑↑↑b.

Thus, the score is larger than 2↑↑↑(9871↑↑2).

2↑↑↑n grows at a ridiculous pace as n gets larger. 2↑↑↑4 := 2↑↑2↑↑2↑↑2 = 2↑↑2↑↑4 = 2↑↑65536, which is a right-associative power tower of 65536 copies of 2:

                                                                2↑↑↑4                                                                 

Similarly, 2↑↑↑5 := 2↑↑(2↑↑↑4), which is a power tower of 2↑↑↑4 copies of 2.

Now, the score isn't 2↑↑↑4 or 2↑↑↑5, it's larger than 2↑↑↑b, where b > 2 × 1039 428. That's a big number...

Dennis

Posted 2014-10-10T00:17:02.590

Reputation: 196 637

@DigitalTrauma - You should check mine ;) – Optimizer – 2014-10-10T21:46:34.227

@Dennis - How much is it roughly ? – Optimizer – 2014-10-10T21:54:48.007

@Optimizer You got me ;-) – Digital Trauma – 2014-10-10T22:01:11.367

Awesome! It reminds me of Graham's number... That is big! – rewritten – 2014-10-11T07:24:47.783

3Note that, while this theoretically should print a very large number of zeros, in practice it just crashes the interpreter with in `*': bignum too big to convert into `long' (RangeError). – Ilmari Karonen – 2014-10-11T11:56:22.957

22

Perl, 70*18446744073709551615*10^987654320

say q{!"#%&'+,-./:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\]^_`bcdfghijklmnoprtuvwz|}x(1e987654320*~$[)

Output:

!"#%&'+,-./:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\]^_`bcdfghijklmnoprtuvwz|

repeated 18446744073709551615*10^987654320 times.

$[ is by default 0, so ~$[ is equivalent to 18446744073709551615.

As a side note, I ran out of memory trying to create the number 10^987654320.


Old Answer (7703703696):

say qw(!"#$%&'*+,-./:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`bcdefghijklmnoprtuvz{|}~10)x98765432

Output is:

!"#$%&'*+,-./:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`bcdefghijklmnoprtuvz{|}~10

repeated 98765432 times.

Note: Run all samples with perl -Mbignum -E

es1024

Posted 2014-10-10T00:17:02.590

Reputation: 8 953

nice! but I wonder if one could use recursivity... (not possible to call oneself if you have to use your own name, as it would repeath the characters in the name... but couldn't your function name end up in $_ or another of Perl's variables?).. or use $0 calls cleverly (without filling the heap) – Olivier Dulac – 2014-10-10T15:48:03.897

If you had enough memory, you could do perl -E'say qw{m}x(9876543210*ord$")' – hmatt1 – 2014-10-10T16:34:53.167

2If it helps there is no longer a time or memory limit. – Calvin's Hobbies – 2014-10-10T20:34:36.990

2It's unfortunate that Perl uses ** rather than ^ for exponentiation. – Mark – 2014-10-12T09:38:27.053

11

Bash+coreutils, 151,888,888,888,888,905 (1.5*10^17)

seq 9E15;#\!%*+,-./2346780:=@ABCDFGHIJKLMNOPQRSTUVWXYZ]^_abcdfghijklmnoprtuvwxyz~"'$&()?<>`{}|[

Outputs integers 1 to 9x1015, one per line. Takes a long time.

Why 9E15? It turns out that GNU seq appears to use 64-bit floats (double) internally. The largest whole number we can represent with this type, before increment by one stops working due to lack of precision, is 253 or 9007199254740992. The closest we can get to this with exponential notation is 9E15 or 9000000000000000.

To calculate the score, I am using adding up all the numbers with a given number of digits and adding 9E15, because there is a newline between each number:

8000000000000001*16 + 900000000000000*15 + 90000000000000*14 + 9000000000000*13 + 900000000000*12 + 90000000000*11 + 9000000000*10 + 900000000*9 + 90000000*8 + 9000000*7 + 900000*6 + 90000*5 + 9000*4 + 900*3 + 90*2 + 9 + 9000000000000000

I could pipe this output through od for an extra order of magnitude or so, but that makes the score calculation much harder.


Pre-rule change answer:

Bash+coreutils, 18,926,221,380

seq 1592346780;#\!%*+,-./:=@ABCDEFGHIJKLMNOPQRSTUVWXYZ]^_abcdfghijklmnoprtuvwxyz~"'$&()?<>`{}|[

Outputs 1 to 1592346780. On my mid 2012 macbook (which is not that far off the linked benchmark), this takes about 9m45s.

I couldn't resist optimizing it a bit more, even though its probably meaningless.

Output:

$ time ./pangram.sh | wc
 1592346780 1592346780 18926221380

real    9m46.564s
user    11m7.419s
sys 0m10.974s
$ 

Digital Trauma

Posted 2014-10-10T00:17:02.590

Reputation: 64 644

why aren't you doing seq 9876543210;? – durron597 – 2014-10-10T17:14:00.620

@durron597 Because that takes too long - probably about an hour. It needs to complete in under 10 minutes. – Digital Trauma – 2014-10-10T17:14:51.873

but surely the only limiting factor of this program is i/o... any other program in any other language could not really beat this. – durron597 – 2014-10-10T17:17:01.507

@durron597 Yes, I think that is right. Though I wouldn't be surprised if someone in this community finds a clever way... – Digital Trauma – 2014-10-10T17:21:35.433

@durron597 I thinks that's true as well. Fitting exactly 10 minutes would just require some fiddling with the numbers. Oh well :/ (I'd remove the time limit but I imagine it's too late for that.) – Calvin's Hobbies – 2014-10-10T17:26:04.340

@Calvin'sHobbies I'll leave it to your judgement, but I won't get all upset if you remove the time limit :) – Digital Trauma – 2014-10-10T17:39:43.420

1@DigitalTrauma I'm actually removing the time limit to ensure this is not the penultimate answer (no offense I just don't want the contest to be over so soon :P), so feel free to use 9876543210. You may want to read the new last rule. – Calvin's Hobbies – 2014-10-10T17:39:50.467

6

GolfScript, ≈ 3*10^(2*10^7) i.e. ≈ 3x1020000000

 87 9654321?,`0${;.p}/#!"%&'()*+-9:<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_abcdefghijklmnoqrstuvwxyz|~

How it works

87 9654321?                "Pushes 87^9654321 to stack";
           ,               "Pushes an array [0, 1, 2 ... (87^9654321) - 1] to stack";
            `              "Creates a string representation of the array like "[0 1 2...]";
             0$            "Copies the string";
               {;.p}/      "Print the string wrapped in quotes X times";
                     #...  "This is all comment";

Here X is the character count (length) of the string representation of the array [0, 1, 2..,(87^9654321) - 1] which will be like [0 1 2 3 4 ... (87^9654321) - 1]

I am trying to calculate X here so as to find my score. (87^9654321) - 1 is roughly 10^(10^7.272415829713899) with 18724742 decimal digits.

X is roughly 3*10^(2*10^7) so X*X is also same only. Note that these values are on a very lower side as due to computation limitations of (even) wolframa, I was not able to compute sum (floor(log10(x)) + 1) for x = 1 to (87^9654321 - 1) which is the true value of X

Optimizer

Posted 2014-10-10T00:17:02.590

Reputation: 25 836

In theory, there would be a few ways of making this even hewuger, but sadly Ruby's BigNum does have limits and 87 9654321? is just Infinity. – Dennis – 2014-10-10T20:55:31.293

Oh! ? Do you know the maximum ? ;) – Optimizer – 2014-10-10T21:00:15.550

Not exactly. Seems to depend on the machine, since the integer has to fit into RAM. With unbounded memory, I don't know where the limit would be. Probably 2**(2**64)-1 for 64-bit Ruby. – Dennis – 2014-10-10T21:13:17.353

We have unbounded amount of RAM – Optimizer – 2014-10-10T21:16:50.240

Yes, that's why I clarified. For CJam, there's a fixed limit and the interpreter just crashes when you exhaust the memory. Ruby seems to be different. – Dennis – 2014-10-10T21:19:48.653

Didn't see your edit. 2(264)-1 is way less than 87 9654321?, so I guess I am good for now ;) – Optimizer – 2014-10-10T21:30:42.427

Since we're on a theoretical machine now, I guess even that limit is irrelevant. – Dennis – 2014-10-10T21:31:25.793

Yeah, and with 0-9, 87 9654321? seemed to be the maximum valued number I could form using power .. – Optimizer – 2014-10-10T21:32:19.537

It's actually not a limitation of BigNum, but of Ruby's ** operator, which the GolfScript interpreter uses to implement ?. I'd be inclined to consider this an interpreter bug. – Ilmari Karonen – 2014-10-11T12:00:00.740

4

MATLAB, 95

Code

char(37-5:126)% !"#$&'*+,./0489;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`bdefgijklmnopqstuvwxyz{|}~

Output

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

Output contains all specified ASCII characters, each exactly once, and in order.

COTO

Posted 2014-10-10T00:17:02.590

Reputation: 3 701

1Note to viewers: This answer was submitted when the spec asked to maximize unique characters. This is no longer the goal, but it's ok if this answer stays since it is valid. – Calvin's Hobbies – 2014-10-10T16:55:47.403

2

Ruby, 89

p %q{!"#$&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnorstuvwxyz|~}

Output:

"!\"\#$&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnorstuvwxyz|~"

Contains all ASCII characters except, p, , %, q, {, and }.

Doorknob

Posted 2014-10-10T00:17:02.590

Reputation: 68 138

1Note to viewers: This answer was submitted when the spec asked to maximize unique characters. This is no longer the goal, but it's ok if this answer stays since it is valid. – Calvin's Hobbies – 2014-10-10T16:56:30.520

2

GolfScript, 93

{ !#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz|~}

Output:

{ !#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz|~}
}

Contains all ASCII characters except " and '.

Doorknob

Posted 2014-10-10T00:17:02.590

Reputation: 68 138

6You're program isn't a perfect pangram though, is it? It doesn't seem to contain " or ' either. – Martin Ender – 2014-10-10T09:01:35.383

Note to viewers: This answer was submitted when the spec asked to maximize unique characters. This is no longer the goal, but it's ok if this answer stays if it made valid. – Calvin's Hobbies – 2014-10-10T16:57:26.753

1It's easy enough to make this valid under the new rules: just remove # from its current position and append #"' to the end. The score will drop by one, though. – Ilmari Karonen – 2014-10-11T11:50:46.730

2

Golfscript - 27*265439870

This my first Golfscript submission! :)

12,`{.+}6543 9870?*#!"$%&'()-/:;<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_abcdefghijklmnopqrstuvwxyz|~

Explanation:

12,                     - Creates an array of ascending numbers from 0 to 11
   `                    - Converts the array to a string
    {.+}                - Duplicates the string on the stack and concatenates the two
        6543 9870?      - Calculates 6543^9870 and pushes it to the stack
                  *     - Repeat the block 6543^9870 times
                   #... - The rest is a comment

The output is a load of lists of numbers. Consider the following code:

12,`{.+}1*

With 12, it produces the following array:

[0 1 2 3 4 5 6 7 8 9 10 11]

The backtick turns that into a string, passing it to the block {.+}. This duplicates the string and then concatenates the two, producing:

[0 1 2 3 4 5 6 7 8 9 10 11][0 1 2 3 4 5 6 7 8 9 10 11]

The 1* tells the interpreter to execute the previous block one time (21 = 2).

So, based upon that:

 12,`{.+}n*

Outputs the output of 12,` 2n times.

Beta Decay

Posted 2014-10-10T00:17:02.590

Reputation: 21 478