Can you Golf Golf?

53

8

You are required to generate a random 18-hole golf course.

Example output:

[3 4 3 5 5 4 4 4 5 3 3 4 4 3 4 5 5 4]

Rules:

  • Your program must output a list of hole lengths for exactly 18 holes
  • Each hole must have a length of 3, 4 or 5
  • The hole lengths must add up to 72 for the entire course
  • Your program must be able to produce every possible hole configuration with some non-zero-probability (the probabilities of each configuration need not be equal, but feel free to claim extra kudos if this is the case)

mikera

Posted 2012-09-25T06:13:20.870

Reputation: 1 233

3Please confirm, 44152809 solutions? – baby-rabbit – 2012-09-26T00:38:22.857

1I too am curious on the exact number of solutions, however I think it should be more than 44 million... (I am no mathmetician, however: | 1(5)/1(3) = 306 possibilities (1718) | 2(5)/2(3) = 69360 poss (17171615) | 3(5)/3(3) = 11182080 poss (1616161514*13) | does that look right? – NRGdallas – 2012-09-26T15:51:31.830

11@baby-rabbit: I can confirm 44,152,809 solutions by brute force enumeration. Also, it can be directly calculated this way: since the average is exactly 4, and the only possibilities are 3, 4, or 5, the possible solution classes are { no 3's or 5's, one 3 and one 5, two 3's and two 5's, ..., nine 3's and nine 5's }. This can be calculated by nCr(18,0)*nCr(18,0) + nCr(18,1)*nCr(17,1) + nCr(18,2)*nCr(16,2) + ... + nCr(18,9)*nCr(9,9) = 44,152,809. This means approximately 11.4% of all possible combinations are valid solutions (44,152,809 / 3^18). – mellamokb – 2012-09-26T22:02:18.137

2sum(factorial(18)/factorial(x)/factorial(y)/factorial(z) for x in range(25) for y in range(25) for z in range(25) if 3*x+4*y+5*z == 72 and x+y+z == 18) gives 44152809L – Sanjeev Murty – 2014-01-05T07:05:43.160

Answers

29

k (18 17 16 chars)

Back to the original approach, credit to CS for the improvement.

(+/4-){3+18?3}/0

Other approach (17 chars), same method as the J solution, H/T to CS

4+a,-a:9?2 -18?18

Old version:

(72-+/){18?3+!3}/0

Not susceptible to stack-overflow and runs in fixed amount of space.

skeevey

Posted 2012-09-25T06:13:20.870

Reputation: 4 139

What's H/T to CS? – Gareth – 2012-09-26T14:11:47.263

Hat-tip, http://en.wikipedia.org/wiki/Hat_tip#Metaphor

– skeevey – 2012-09-26T14:35:25.937

This program helped me discover a bug in my K interpreter- thanks! I didn't previously realize that nilads could be applied to a single argument (which they ignore).

– JohnE – 2016-01-13T16:09:23.840

17

K, 28

{$[72=+/s:18?3 4 5;s;.z.s`]}

tmartin

Posted 2012-09-25T06:13:20.870

Reputation: 3 917

15

J, 20 18 17 characters

(?~18){4+(,-)?9#2

This works in the same way as the previous answer except that the 9 random digits are either 0 or 1 and are negated before being appended. This means there are as many -1s as there are 1s. Adding 4 gives me a list of 3s, 4s and 5s that add up to 72 every time.

Previous answer:

({~?~@#)3+(,2-])?9#3

Generates the first 9 holes randomly ?9#3, then copies and inverts them (,2-]) (turns a 3 into a 5 and a 5 into a 3) to generate the final 9. This guarantees that the total will be 72 (since every 3 will have a matching 5 the average total per hole will be 4 and 4x18=72). It then randomly shuffles the result ({~?~@#) to ensure that every combination is possible.

Gareth

Posted 2012-09-25T06:13:20.870

Reputation: 11 678

actually you won't generate {3,5,4,4,4...} you are better off shuffling the entire result – ratchet freak – 2012-09-25T11:23:56.167

@rachetfreak Good point. I'll edit now. – Gareth – 2012-09-25T11:31:18.297

13

Mathematica 71 68 66 60

With 6 chars saved by Tally's suggestion.

RandomSample@RandomChoice@IntegerPartitions[72, {18}, {3, 4, 5}]

{5, 4, 3, 3, 5, 3, 5, 5, 3, 3, 4, 5, 3, 5, 4, 4, 5, 3}

All possible outcomes are possible, but they are not equally likely.


Analysis

IntegerPartitions[72, {18}, {3, 4, 5}]

produces all 10 possible partitions (combinations, not permutations) of 72 into 18 elements consisting of 3's, 4's and 5's.

partitions


RandomChoice selects one of those.

RandomSample returns a permutation of that choice.

DavidC

Posted 2012-09-25T06:13:20.870

Reputation: 24 524

Hehe, I was just about to post almost the exact same answer, only using RandomChoice instead of RandomInteger. I think you can shave of 4 more characters by doing so. – Tally – 2014-12-28T17:25:37.710

Tally, thanks. Your suggestion was helpful. – DavidC – 2014-12-28T19:56:44.843

13

16-bit x86 machine code under MS-DOS - 45 bytes

Hexdump:

0E5F576A12595188ECE44088C3E44130D8240374F400C4AAE2EF595E80FC2475DFAC0432CD29B020CD29E2F5C3

Base64 coded binary:

Dl9XahJZUYjs5ECIw+RBMNgkA3T0AMSq4u9ZXoD8JHXfrAQyzSmwIM0p4vXD

Actual source code with some comments:

 bits 16
 org 0x100

again:
 push cs               ; Save whatever CS we get.
 pop di                ; Use CS:DI as our course buffer..
 push di               ; Save for later use in the print loop
 push 18               ; We need 18 holes for our golf course.
 pop cx                ; ch = 0, cl = 18.
 push cx               ; Save for later use.
 mov ah, ch            ; Zero out ah.
generate_course:
 in al, 0x40           ; Port 0x40 is the 8253 PIT Counter 0.
 mov bl, al            ; Save the first "random" value in bl.
 in al, 0x41           ; Port 0x41 is the 8253 PIT Counter 1.
 xor al, bl            ; Add some more pseudo randomness.
 and al, 3             ; We only need the two lower bits.
 jz generate_course    ; If zero, re-generate a value, since we need only 3, 4, 5 holes.
 add ah, al            ; Sum in ah register.
 stosb                 ; Store in the course buffer.
 loop generate_course  ; Loop for 18 holes.
 pop cx                ; cx = 18.
 pop si                ; si = course buffer.
 cmp ah, 36            ; 72 holes?
 jne again             ; No, re-generate the whole course.

print:                 ; Yup, we have a nice course.
 lodsb                 ; Load the next hole.
 add al, '2'           ; Add ASCII '2' to get '3', '4' or '5'
 int 0x29              ; Undocumented MS-DOS print function.
 mov al, ' '           ; Print a space too for better readability.
 int 0x29              ; Print the character.
 loop print            ; Print the whole course.
 ret                   ; Return to the beginning of the PSP where a INT 0x20 happen to be.

Compile with nasm 18h.asm -o 18h.com and run under MS-DOS (or Dosbox), or NTVDM from a 32-bit Windows version.

Sample output:

4 5 4 5 4 5 3 4 3 4 3 4 4 5 4 3 5 3

Jonas Gulle

Posted 2012-09-25T06:13:20.870

Reputation: 501

3love assembler... – woliveirajr – 2012-09-27T12:18:31.333

8

R - 41

x=0;while(sum(x)!=72)x=sample(3:5,18,T);x

# [1] 5 3 5 3 3 3 3 3 5 4 5 4 5 4 4 5 5 3

The algorithm is similar to @sgrieve's.

flodel

Posted 2012-09-25T06:13:20.870

Reputation: 2 345

Same problem as @sgrieve above -- nothing prevents it from going over in 18 holes. – gt6989b – 2012-09-25T12:27:56.280

3That's not a problem, the sample command in this case always generates 18 values. – sgrieve – 2012-09-25T12:35:59.447

8

GolfScript (26 chars)

{;0{3rand.3+@@+(}18*])}do`

There are some obvious similarities with Ilmari's solution, but also some obvious differences. In particular, I'm exploiting the fact that the average par is 4.

Peter Taylor

Posted 2012-09-25T06:13:20.870

Reputation: 41 901

Damn, but that sure is a clever trick with the loop condition there. I came up with {;0{3.rand+.@+}18*])72-}do myself, but couldn't figure out how to get it any shorter from there. +1. – Ilmari Karonen – 2012-09-25T23:54:38.093

7

Python 77

Code

from numpy.random import*;l=[]
while sum(l)!=72:l=randint(3,6,18)
print l

Output

[3 4 4 5 3 3 3 5 4 4 5 4 5 3 4 4 5 4]

The import really kills this solution. It uses numpy to generate a 18 numbers between 3 and 5 and keeps generating lists until the sum of the list equals 72.

sgrieve

Posted 2012-09-25T06:13:20.870

Reputation: 171

What prevents the program from reaching 72 well before generating 18 holes? What prevents it from skipping 72? – DavidC – 2012-09-25T09:35:09.407

3The code will always generate 18 holes, then check if the sum equals 72. For example, if the sum after 16 holes was 72, it would still generate another 2 holes, therby pushing the sum above 72 and failing the test. – sgrieve – 2012-09-25T09:40:36.810

7

GolfScript, 27 chars

{;18{3.rand+}*].{+}*72-}do`

Uses the same rejection sampling method as sgrieve's Python solution. Thus, every valid output actually is equally likely.

Ilmari Karonen

Posted 2012-09-25T06:13:20.870

Reputation: 19 513

7

Q (25 characters)

Original (27)

while[72<>sum a:18?3 4 5];a

Sample output

4 4 3 3 4 5 4 3 4 5 5 3 5 5 5 4 3 3

Slightly shorter (25)

{72<>sum x}{x:18?3 4 5}/0

sinedcm

Posted 2012-09-25T06:13:20.870

Reputation: 410

7

JavaScript, 66 64 61 chars

Heavily inspired by TwoScoopsofPig (PHP) and Joe Tuskan (JS).

for(a=[s=0];s!=72;)for(s=i=0;i<18;s+=a[i++]=Math.random()*3+3|0);a

for(a=[s=0];s-72;)for(s=i=0;i<18;s+=a[i++]=Math.random()*3+3|0)a

for(a=s=[];s;)for(i=18,s=72;i;s-=a[--i]=Math.random()*3+3|0)a

user1686

Posted 2012-09-25T06:13:20.870

Reputation: 177

2s!=72 can be s-72 to save one char. And the last semi-colon ;a isn't needed either for another char. – Joe Tuskan – 2012-09-25T20:21:58.153

i never saw for(i=x;i;i--) before it saves 2 chars from for(i=0;i<x;i++), thanks man! – Math chiller – 2013-10-21T17:37:26.597

7

Python 2, 70 bytes

from random import*
print sample(([3,5]*randint(0,9)+[4]*99)[:18],18)
edit:

Here's another one, similar to the solution of sgrieve:

Python 2, 73 bytes + equal probability

from random import*
a=[]
while sum(a)-72:a=sample([3,4,5]*18,18)
print a

daniero

Posted 2012-09-25T06:13:20.870

Reputation: 17 193

5

Python, 128 120 116 characters

import random,itertools
random.choice([g for g in itertools.product(*(range(3,6)for l in range(18))) if sum(g)==72])

import statements are still length killers (23 characters only to import 2 function in the namespace)

i hope you do not need the result in a near future, as this code first evaluates all possible solutions before chosing one at random. maybe the slowest solution to this problem.

i do claim extra kudos for equal probability of each configuration...

Adrien Plisson

Posted 2012-09-25T06:13:20.870

Reputation: 151

4import random,itertools – user1686 – 2012-09-25T20:59:25.860

you are right, that shorten things a bit. – Adrien Plisson – 2012-09-26T09:02:00.043

Other tips: import random as r,itertools as i then use r and i instead of random and itertools. Use 18*[0] instead of range(18), and [3,4,5,6] instead of range(3,6) :) – Alex L – 2012-09-26T09:20:18.670

i am using python 3: a list comprehension is a generator and has no length, which forbids its use with the choice() function. that's also what makes this code so slow... – Adrien Plisson – 2012-09-26T09:23:50.017

Ah, I'm using 2.7. I've added my attempt at golfing your answer in my Q here

– Alex L – 2012-09-26T09:30:25.317

Uh... in Python 3, list comprehensions produce lists and can be passed to random.choice. In fact, [genexpr] is syntactic sugar for list(genexpr). – Winston Ewert – 2012-09-26T15:26:18.513

1ooops, sorry, i messed up list comprehension and generator expression (i generally avoid list comprehension in favor of generator expression because of the better performance of iterator). so indeed, even in python3 i can still remove some characters... @Alex did it right. – Adrien Plisson – 2012-09-26T15:39:19.587

5

JavaScript, 116 99 65 bytes

for(i=0,h=[];i<18;)h[i++]=5;while(h.reduce(function(a,b){return a+b})!=72){i=Math.random()*18|0;h[i]=[3,4,4][i%3]}h;

h=[0];while(h.reduce(function(a,b){return a+b})-72)for(i=0;i<18;h[i++]=[3,4,5][Math.random()*3|0])h

while(i%18||(a=[i=s=0]),s+=a[i++]=Math.random()*3+3|0,s-72|i-18)a

Joe Tuskan

Posted 2012-09-25T06:13:20.870

Reputation: 171

1When I run this in Chrome 21, I get i is not defined. – mellamokb – 2012-09-26T23:24:33.603

4

Ruby 1.9 (62 chars)

a=Array.new(18){[3,4,5].sample}until(a||[]).inject(:+)==72
p a

Rails (55 chars)

In the $ rails c REPL (in any Rails folder):

a=Array.new(18){[3,4,5].sample}until(a||[]).sum==72
p a

Note: It works with Ruby 1.8 if you use shuffle[0] instead of sample.

js-coder

Posted 2012-09-25T06:13:20.870

Reputation: 141

2Do you need whitespace around until? – Kaz – 2012-09-25T19:41:07.910

@Kaz You're right, it's not needed. :) 62 chars now. – js-coder – 2012-09-26T12:18:01.073

1You can use (1..18).map{rand(3)+3} to get the random array ;) – epidemian – 2013-11-02T18:58:02.080

4

PHP - 77 Chars

<?while(array_sum($a)!=72){for($i=0;18>$i;){$a[++$i]=rand(3,5);}}print_r($a);

Much like sgrieve's solution, this builds a list of 18 holes, checks total par, and either prints it or rejects it and tries again. Oddly enough, our two solutions are the same length.

Rather annoyingly, PHP doesn't offer array functions with any brevity of name. Array_sum and print_r are killing me. Suggestions welcome.

TwoScoopsofPig

Posted 2012-09-25T06:13:20.870

Reputation: 131

1Curly braces are not needed here, and sum can be +=. <?while($s!=72)for($s=$i=0;18>$i;$s+=$a[++$i]=rand(3,5));print_r($a); – user1686 – 2012-09-25T19:13:11.057

That's useful - I never thought to put the logic in the for loop call (and I feel kinda dumb for not incrementing a counter for the sum). – TwoScoopsofPig – 2012-09-26T19:45:02.337

Thanks – but that isn't actually what I meant by "curly braces not needed"; you could have removed them in the original code too: while(array_sum($a)!=72)for($i=0;18>$i;)$a[++$i]=rand(3,5); – user1686 – 2012-09-27T16:40:44.557

Well except I run against a stricter php.ini than that because I'm golfing at work; it complains no end about braces being missing/mismatched. Normally I would have. – TwoScoopsofPig – 2012-10-17T17:53:20.180

That's odd; 5.4.7 with E_ALL|E_STRICT never complains about missing {}'s (since PHP's syntax explicitly allows that). – user1686 – 2012-10-17T18:21:20.947

I'm stuck on 5.3.2. So. That. – TwoScoopsofPig – 2012-12-18T15:17:34.030

4

Lisp (78 69 chars)

(do((c()(mapcar(lambda(x)(+ 3(random 3)))(make-list 18))))((=(apply'+ c)72)c))

(do((c()(loop repeat 18 collect(+ 3(random 3)))))((=(apply'+ c)72)c))

It's rather similar to sgrieve's Python solution.

Start with c as NIL, check for a sum of 72, the do "increment function" for c generates a list of 18 numbers between 3 and 5, check for 72 again, lather, rinse, repeat.

It's refreshing to see do and loop nicely play golf together.

wintermute

Posted 2012-09-25T06:13:20.870

Reputation: 41

3

C (123 chars) - effort on efficiency

Pipe through wc and it will generate all 44152809 solutions within 10 seconds...

char s[19];g(d,t){int i;if(d--){for(i=51,t-=3;i<54;i++,t--)if(t>=3*d&&t<=5*d)s[d]=i,g(d,t);}else puts(s);}main(){g(18,72);}

Oh, well - didn't read the question properly - but given we're generating all solutions then picking a random one with equal probability is a scripting exercise :P

baby-rabbit

Posted 2012-09-25T06:13:20.870

Reputation: 1 623

3

Clojure - 55

(shuffle(mapcat #([[4 4][3 5]%](rand-int 2))(range 9)))

Quite a fun trick.... exploits the mathematical structure of the problem that there must be exactly as many 3 par holes as 5 par holes.

mikera

Posted 2012-09-25T06:13:20.870

Reputation: 1 233

3

Python 83

import random as r;x=[]
while sum(x)!=72:x=[r.randint(3,5) for i in 18*[0]]
print x

Like sgrieve's solution, but without numpy

Golfing Adrien Plisson's solution: 120->108 characters

import random as r,itertools as i
r.choice([g for g in i.product(*([3,4,5,6]for l in 18*[0]))if sum(g)==72])

MATLAB 53

x=[];
while sum(x)~=72
x=3+floor(rand(1,18)*3);
end
x

Output:

x = 4 3 4 4 4 4 5 4 4 3 4 4 3 5 3 5 4 5

Alex L

Posted 2012-09-25T06:13:20.870

Reputation: 193

Nice approach, but you can save 4 bytes by typing randi([3,5],1,18) instead of 3+floor(rand(1,18)*3) – brainkz – 2016-01-14T21:19:44.540

3

Java (61 chars)

while(s!=72)for(i=0,s=0;i<18;i++)s+=3+(int)(Math.random()*3);

Sample output:

5 4 3 4 5 3 4 4 3 5 4 4 4 4 3 4 4 5

Quasar

Posted 2012-09-25T06:13:20.870

Reputation: 39

I'm no Java expert, but shouldn't there be a declaration of s and i, and some kind of call to System#println(..)? – hiergiltdiestfu – 2015-08-26T08:17:41.450

This is just a code snippet, not a program. And it actually looks very much like @JoeIbanez' C version. – Franz D. – 2015-11-04T22:22:47.073

2

APL 12

4+{⍵,-⍵}?9⍴2

Note that I have the index origin set to 0, meaning arrays start at 0. You can set this with ⎕IO←0.

Zaq

Posted 2012-09-25T06:13:20.870

Reputation: 1 525

The question asks a program that can produce every possible configuration. Yours can produce simmetric ones. You can't produce for example 555455555333333343, at least it seems so to me. – Moris Zucca – 2014-12-27T19:11:44.737

2

CJam, 17 14 bytes

CJam is newer than this challenge, but this is not the shortest answer anyway, so that doesn't really matter.

Z5]Amr*I4e]mrp

Test it here.

To maintain the total of 72, each 3 must be paired with 5. So here is how it works:

Z5]            e# Push [3 5].
   Amr         e# Get a random number between 0 and 9.
      *        e# Repeat the [3 5] array that many times.
       I4e]    e# Pad the array to size 18 with 4s.
           mr  e# Shuffle the array.
             p e# Print it.

Martin Ender

Posted 2012-09-25T06:13:20.870

Reputation: 184 808

2

R, 42 bytes

a=0;while(sum(a)-72)a=sample(3:5,18,r=T);a

sample, by default, draws evenly among the possible values (here 3 4 5). r=T stands for replace=TRUE and allows sample with replacement.

plannapus

Posted 2012-09-25T06:13:20.870

Reputation: 8 610

2

C (94 chars)

int h[18],s=0,i;
while(s!=72)for(i=s=0;i<18;s+=h[i++]=rand()%3+3);
while(i)printf("%d ",h[--i]);

The s=0 on line 1 may not be required, because what are the chances an uninitialized int will equal 72? I just don't like reading uninitialized values in straight C. Also, this probably requires seeding the rand() function.

output

3 3 3 4 5 5 3 3 4 5 5 4 3 4 5 5 5 3 

Joe Ibanez

Posted 2012-09-25T06:13:20.870

Reputation: 121

So basically you're gonna loop through random strings of 18 numbers ranged 3 to 5 until one happens to equal 72? Good thing efficiency isn't a requisite. – KeithS – 2012-09-25T23:10:08.673

5@KeithS To be fair, that's what the majority of the answers to this question are doing. – Gareth – 2012-09-25T23:19:27.403

2

TXR (99 chars)

@(bind g@(for((x(gen t(+ 3(rand 3))))y)(t)((pop x))(set y[x 0..18])(if(= [apply + y]72)(return y))))

This expression generates an infinite lazy list of random numbers from 3 to 5:

(gen t (+ 3(rand 3)))  ;; t means true: while t is true, generate.

The rest of the logic is a simple loop which checks whether the first 18 elements of this list add up to 72. If not, it pops an element off and tries again. The for loop contains an implicit block called nil and so (return ...) can be used to terminate the loop and return value.

Note that the 99 character length includes a terminating newline, which is required.

Kaz

Posted 2012-09-25T06:13:20.870

Reputation: 372

I put in a commit that allows the (t) to be replaced by (). :) – Kaz – 2012-09-25T20:03:15.670

2

C# (143 non-whitespace):

()=>{
  var n=new Math.Random().Next(10);
  Enumerable.Range(1,18)
    .Select((x,i)=>i<n?3:i>=18-n?5:4)
    .OrderBy(x=>Guid.NewGuid())
    .ForEach(Console.Write);
}

KeithS

Posted 2012-09-25T06:13:20.870

Reputation: 211

new Guid() creates an empty GUID. To actually generate a unique GUID you need to call a static method Guid.NewGuid. – Rotsor – 2012-09-26T05:18:00.823

And you have two off-by-one errors (so to speak): the comparisons should be i<n and i>=18-n, not the other way around. And you could reduce the size by using a constant 3 instead of x-1 and 5 instead of x+1. And then you could replace Enumerable.Repeat by Enumerable.Range. – Mormegil – 2012-09-26T14:20:43.993

Edited; still 143 chars – KeithS – 2012-09-26T16:16:15.347

There is no Math.Random, it's System.Random. – CodesInChaos – 2013-11-07T09:15:12.817

Another C# approach (143 chars): var r=new Random();for(;;){var e=Enumerable.Range(1,18).Select(i=>r.Next(3,6)).ToList();if(e.Sum()==72){e.ForEach(i=>Console.Write(i));break;}} – thepirat000 – 2014-01-06T03:40:04.793

2

Bash shell script (65 chars)

shuf -e `for x in {0..8}
do echo $((r=RANDOM%3+3)) $((8-r))
done`

(shuf comes from the GNU coreutils package. Also, thanks Gareth.)

PleaseStand

Posted 2012-09-25T06:13:20.870

Reputation: 5 369

2

Haskell, 104 102 98 chars.

import System.Random
q l|sum l==72=print l|1>0=main
main=mapM(\_->randomRIO(3::Int,5))[1..18]>>=q

Rotsor

Posted 2012-09-25T06:13:20.870

Reputation: 355

[1..n]>>[r] is slightly shorter than replicate n$r. – ceased to turn counterclockwis – 2012-09-27T19:17:28.680

Also changed sequence to mapM. – Rotsor – 2012-09-27T23:14:54.160

2

Perl, 74

{@c=map{3+int rand 3}(0)x18;$s=0;$s+=$_ for@c;redo unless$s==72}print"@c"

Alternative solution:

@q=((3,5)x($a=int rand 9),(4,4)x(9-$a));%t=map{(rand,$_)}(0..17);print"@q[@t{sort keys%t}]"

o_o

Posted 2012-09-25T06:13:20.870

Reputation: 251

1

VBA - 117

VBA never wins at golf. :-)

Sub a()
Do Until d=72
d=0
c=""
For b=1 To 18
e=Int(3*Rnd()+3)
c=c &" " &e
d=d+e
Next
Loop
MsgBox c
End Sub

Gaffi

Posted 2012-09-25T06:13:20.870

Reputation: 3 411

1

PowerShell - 59

while(($x|measure -s).sum-ne72){$x=1..18|%{3..5|random}};$x

Rynant

Posted 2012-09-25T06:13:20.870

Reputation: 2 353

1

Perl, 59

@a=map{3+rand 3|0}1..18 while 72!=eval join'+',@a;print"@a"

Not a winner by any means and could probably be improved still...

Array sum method stolen from perlmonks.

Dom Hastings

Posted 2012-09-25T06:13:20.870

Reputation: 16 415

1

Mathematica, 45 chars

NestWhile[{3, 5}~RandomInteger~18 &, {}, Tr@# != 72 &]

alephalpha

Posted 2012-09-25T06:13:20.870

Reputation: 23 988

1

Perl 6 (42 bytes)

my@a=roll 18,3..5 while 72!= [+] @a;say @a

Probably too long to be acceptable, but at least the solution does exist. roll rolls the dice containing 3, 4, and 5. This generates numbers until the sum is equal to 72. I believe it can generate any course with equal probability (in theory), but considering pseudo-random number generators, it probably doesn't.

Sample output:

~ $ perl6 -e 'my@a=roll 18,3..5 while 72!= [+] @a;say @a'
3 4 3 3 4 5 4 3 4 4 3 4 5 4 5 5 4 5

Konrad Borowski

Posted 2012-09-25T06:13:20.870

Reputation: 11 185

1

TI-BASIC, 13 bytes

3+3fPart(randIntNoRep(0,17)/3

Outputs list of 18 integers. Meets all specs and has equal probability for each case.

Timtech

Posted 2012-09-25T06:13:20.870

Reputation: 12 038

And yes, total is always 72 thanks to our handy 2-byte randIntNoRep( – Timtech – 2014-12-26T01:19:16.540

This only produces lists with exactly 6 3's, 6 4's, and 6 5's. – lirtosiast – 2015-05-16T20:00:40.297

"Each hole must have a length of 3, 4 or 5" – Timtech – 2015-05-19T12:20:46.763

1"Your program must be able to produce every possible hole configuration"-- so for example, 9 3s and 9 5s would be valid. – lirtosiast – 2015-05-19T14:03:45.243

1

Pyth, 18 bytes

#Jm+3O3U18IqsJ72JB

How it works:

#                    infinite loop
       U18           generate the list [0, 1, ..., 17]
  m    U18           map every value of this list to
   +3O3              a random number between 3 and 5
 Jm+3O3U18           and assign the resulting list to J
          I          if
           qsJ72     the sum of J == 72
                J    print J
                 B   and exit the loop

Jakube

Posted 2012-09-25T06:13:20.870

Reputation: 21 462

1

CJam, 31

[Language was created after the question was posted]

Shamelessly long for CJam. It's basically a brute-force solution that keeps trying random configurations until it finds one that adds to 72.

L{;L{3mr3+_U+:U;a+}I*U72=:U!}g`

user16402

Posted 2012-09-25T06:13:20.870

Reputation:

1

Java: 389 bytes

Run by calling the b() function.

import java.util.*;public class a{Random b=new Random();int[]b(){int[]c=new int[18];int d=0;for(int i=0;i<c.length;i++){int e=g(c.length-i,d);int f=h(c.length-i,d);c[i]=i(e,f);d=d+c[i];}
return c;}
int i(int j,int k){return b.nextInt((k-j)+1)+j;}
int g(int l,int m){int n=(l-1)*5;int o=72-m;int p=o-n;return p<3?3:p;}
int h(int q,int r){int s=(q-1)*3;int t=72-r;int u=t-s;return u>5?5:u;}}

PoweredByRice

Posted 2012-09-25T06:13:20.870

Reputation: 171

whoever downvoted can explain? – PoweredByRice – 2014-12-28T15:59:45.893

1

Javascript, 148 143 bytes

t=[];d=0;while(d<18){q=t.reduce(function(a,b){return a+b},z=0);while(!z||q+z+13-d*5<0||q+z-d*3>21)z=3+3*Math.random()|0;t.push(z);d++}alert(t)

SuperJedi224

Posted 2012-09-25T06:13:20.870

Reputation: 11 342

1

PARI/GP, 85 bytes

vecextract(Vec(partitions(72,[3,5],[18,18])[random(10)+1]),numtoperm(18,random(18!)))

This generates a random partition of 72 with 18 components ranging from 3 to 5. The probabilities are not uniform, from 1/10 for the all-4 vector to 1/171531360 for [3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5] and its permutations.

Charles

Posted 2012-09-25T06:13:20.870

Reputation: 2 435

1

Python, 97

Using a different method than the rejection sampling, this picks a random list of indices of random even length and alternates adding and subtracting to the elements at these indices.

from random import*;a=[4]*18;d=1
for i in sample(range(18),2*randint(0,9)):a[i]+=d;d=-d
print a

scleaver

Posted 2012-09-25T06:13:20.870

Reputation: 507

1

Clojure - 72 chars

(some #(if(=(apply +%)72)%)(partition 18(repeatedly #(+(rand-int 3)3))))

Would be much shorter if Clojure didn't have such flowery descriptive function names :-)

mikera

Posted 2012-09-25T06:13:20.870

Reputation: 1 233

1

Groovy

126 chars

def a=[];while(1){(new Random().nextInt(3)!=1&&a.size()<17?a<<3<<5:a<<4);if(a.size()==18)break};Collections.shuffle(a);print a

... ooooh, what a waste of chars :)

110 chars

def a=[];while(a.size()<18){(new Random().next(2)>1&&a.size()<17?a<<3<<5:a<<4)};Collections.shuffle(a);print a

codeporn

Posted 2012-09-25T06:13:20.870

Reputation: 261

0

AHK, 76 bytes

Loop{
s=
t=0
Loop,18{
Random,r,3,5
s:=r " "s
t+=r
}
If t=72
Break
}
Send,%s%

It's of the style to just loop forever until it happens to generate a list that totals 72 strokes.

Engineer Toast

Posted 2012-09-25T06:13:20.870

Reputation: 5 769

0

Octave, 37 bytes

while sum(x=2+randi(3,1,18))-72;end;x

It seems straight forward, (and I guess it is), but there are a few nifty tricks in here. It's 16 bytes shorter than the MATLAB answer, and I think it's hard to golf any further.

In Octave, you can initialize a variable inside a function call, or inside the while statement as done here. So, by doing sum(x=2+randi(3,1,18)) I manage to continuously shuffle a vector of 18 elements with values [3,4,5] until the sum is 72. Instead of checking if this equals 72, we can subtract 72, and check if that's a truthy or a falsey value. Any non-zero values are considered truthy, so it will only stop when the sum is 72. In the end, the loop stops and the vector is printed.

Stewie Griffin

Posted 2012-09-25T06:13:20.870

Reputation: 43 471

0

Seriously, 32 bytes (noncompeting)

35k9Ju;)@nktd9-τ4nktW;lJ`\`np@WX

This language post-dates this challenge. Posted to prove the need for a shuffle command and perhaps a cons command. This uses the same solution as CJam roughly:

35k                                 Push [5,3]
   9Ju                              Push a random number n from 1 to 9
      ;)                            Save a copy of it for later use.
        @n                          Make n copies of [5,3]
          (9-τ                      Transform n -> 2*(9-n)
              4n                    Push that many 4's
                kt                  Compile all numbers into a list.
                  W         W       Until the list is empty:
                   ;lJ`\`np@        Pop a random element from it.
                             X      Discard empty list.

quintopia

Posted 2012-09-25T06:13:20.870

Reputation: 3 899