git @ Cat's Eye Technologies NaNoGenLab / c4a9a2f
Nuts to this! I want bigger _r_'s! Chris Pressey 10 years ago
2 changed file(s) with 76 addition(s) and 11 deletion(s). Raw diff Collapse all Expand all
77 and we want to produce it using only permutations or combinations,
88 with duplicates allowed or not, of _r_ words out of _n_ input words. What
99 method and what values of _n_ and _r_ should we get as close to 50,000 words
10 (without going under) as possible? (This should exclude trivial solutions
11 like P(50000, 1).)
10 (without going under) as possible?
11
12 This should exclude trivial solutions like P(50000, 1). And, assuming this
13 novel will be in "sentences" of _r_ words, what results do we get if we
14 insist on a high _r_?
1215
1316 OK so my actualy hypothesis is that I can get a computer to brute-force its
1417 way through these numbers so I don't have to do anything hard like write
6063 uninteresting text too (kind of like counting in base 15, unless it was
6164 scrambled up somehow.)
6265
63 Raising _n_ higher results in OverflowErrors (srsly, Python? thought you had
64 bignums, dude) but probably wouldn't get us anywhere.
66 After writing some code to catch OverflowErrors (srsly, Python? thought you had
67 bignums, dude) I ran it for _n_ up to 800 and found that P_duplicates(224,2) =
68 50176. OK, also not a surprise given the square root is around 223. Again,
69 not sure how interesting such a text would be, although that may not matter.
6570
6671 ### C (combinations without repetitions) ###
6772
7378 When looking at _n_ up to 500, the best result was C_duplicates(316, 2) = 50086.
7479 Again, not bad.
7580
81 ### Nuts to this! I want bigger _r_'s! ###
82
83 You will note that the value of _r_ in the above results is often 2, which
84 suggests our novel would be a series of pairs of things, which sounds pretty
85 boring no matter which way you slice it. What if we insist _r_ is larger?
86
87 Here are some results for _r_ = 3 and maximum _n_ in all cases is 500:
88
89 $ ./perm-comb-finder.py --minimum-r=3 --top=500
90 best: P(38,3) = 50616
91 best: P(9,9) = 362880
92 best: P_duplicates(15,4) = 50625.0
93 best: C(317,315) = 50086
94 best: C_duplicates(66,3) = 50116
95
96 Interesting to note that the best _r_ for C becomes a whopping 315, but that
97 is just due to the symmetrical nature of C (I blame Pascal's Triangle.)
98 50,086 is still our overall winner, but C_duplicates(66, 3) might arguably be
99 more interesting. Let's try _r_ = 4, 5, and 6:
100
101 $ ./perm-comb-finder.py --minimum-r=4 --top=500
102 best: P(11,5) = 55440
103 best: P(9,9) = 362880
104 best: P_duplicates(15,4) = 50625.0
105 best: C(317,315) = 50086
106 best: C_duplicates(13,7) = 50388
107
108 $ ./perm-comb-finder.py --minimum-r=5 --top=500
109 best: P(11,5) = 55440
110 best: P(9,9) = 362880
111 best: P_duplicates(9,5) = 59049.0
112 best: C(317,315) = 50086
113 best: C_duplicates(13,7) = 50388
114
115 $ ./perm-comb-finder.py --minimum-r=6 --top=500
116 best: P(9,6) = 60480
117 best: P(9,9) = 362880
118 best: P_duplicates(7,6) = 117649.0
119 best: C(317,315) = 50086
120 best: C_duplicates(13,7) = 50388
121
122 Of these, C_duplicates(13,7) might be the most interesting, but technically
123 C(317,315) is still the winner.
124
76125 Future Work
77126 -----------
78127
00 #!/usr/bin/env python
11
22 from math import factorial, pow
3 from optparse import OptionParser
34 import sys
45
56
1718
1819 # order matters. repetition allowed.
1920 def P_duplicates(n, r):
20 return pow(n, r)
21 try:
22 return pow(n, r)
23 except OverflowError:
24 return float('inf') # everything in Python is Pythonic, esp. this
2125
2226
2327 # order doesn't matter. repetition not allowed.
3135
3236
3337 TARGET = 50000
38 MIN_R = 1
3439
3540 def find(fun, top):
3641 best = 10000000000
3944 if best == TARGET:
4045 print "BINGO!"
4146 break
42 for r in tqdm(xrange(1, n+1)):
47 for r in tqdm(xrange(MIN_R, n+1)):
4348 attempt = fun(n, r)
4449 if attempt >= TARGET and attempt < best:
4550 best = attempt
5156
5257
5358 def main(argv):
54 (best, n, r) = find(P, 300)
59 global MIN_R
60
61 optparser = OptionParser(__doc__)
62 optparser.add_option("--minimum-r", default=1,
63 help="lowest value of _r_ to consider")
64 optparser.add_option("--top", default=400,
65 help="highest value of _n_ to consider")
66 (options, args) = optparser.parse_args(argv[1:])
67 MIN_R = int(options.minimum_r)
68 options.top = int(options.top)
69
70 (best, n, r) = find(P, options.top)
5571 print "best: P(%s,%s) = %s" % (n, r, best)
5672
57 (best, n, r) = find(lambda n, r: P(n, n), 100)
73 (best, n, r) = find(lambda n, r: P(n, n), options.top)
5874 print "best: P(%s,%s) = %s" % (n, n, best)
5975
60 (best, n, r) = find(P_duplicates, 100)
76 (best, n, r) = find(P_duplicates, options.top)
6177 print "best: P_duplicates(%s,%s) = %s" % (n, r, best)
6278
63 (best, n, r) = find(C, 500)
79 (best, n, r) = find(C, options.top)
6480 print "best: C(%s,%s) = %s" % (n, r, best)
6581
66 (best, n, r) = find(C_duplicates, 500)
82 (best, n, r) = find(C_duplicates, options.top)
6783 print "best: C_duplicates(%s,%s) = %s" % (n, r, best)
6884
6985