ゴルフできますか?


53

ランダムな18ホールのゴルフコースを生成する必要があります。

出力例:

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

ルール:

  • プログラムは、正確に18ホールのホール長のリストを出力する必要があります
  • 各穴の長さは3、4、または5でなければなりません
  • コース全体で穴の長さは最大72になる必要があります
  • プログラムは、ゼロ以外の確率ですべての可能なホール構成を生成できる必要があります(各構成の確率は同じである必要はありませんが、その場合は追加の称賛を要求してください)

3
確認してください、44152809ソリューション?
赤ちゃんウサギ

1
私も解の正確な数に興味がありますが、4,400万を超えるはずだと思います...(ただし、数学者ではありません:| 1(5)/ 1(3)= 306の可能性(17 * 18) | 2(5)/ 2(3)= 69360 poss(17 * 17 * 16 * 15)| 3(5)/ 3(3)= 11182080 poss(16 * 16 * 16 * 15 * 14 * 13)|は右に見える?
-NRGdallas

11
@ baby-rabbit:ブルートフォース列挙により44,152,809個のソリューションを確認できます。また、それは直接このようにして計算することができる:平均が正確であるため4、唯一可能性があり34または5、クラスがある可能な解決策{ no 3's or 5'sone 3 and one 5two 3's and two 5's、...、nine 3's and nine 5's}。これはで計算できます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。これは、ほぼ11.4%すべての可能な組み合わせが有効なソリューションであることを意味します(44,152,809 / 3^18)
mellamokb

2
sum(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)与える44152809L
サンジーブマーティ14年

回答:


29

k(18 17 16文字)

元のアプローチに戻り、CSの改善に貢献しました。

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

他のアプローチ(17文字)、Jソリューションと同じ方法、CSへのH / T

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

旧版:

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

スタックオーバーフローの影響を受けず、一定量のスペースで実行されます。


CSへのH / Tとは何ですか?
ガレス


このプログラムは、Kインタープリターのバグを発見するのに役立ちました。ありがとう!私は以前、niladsが単一の引数に適用できることを認識していませんでした(無視されます)。
ヨーネ


15

J、20 18 17文字

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

これは、9個のランダムな数字が0または1であり、追加される前に否定されることを除いて、前の回答と同じように機能します。これは、と同じ数-1のがあることを意味し1ます。4を追加すると34s、5s 、sのリストが表示され、毎回最大72が追加されます。

前の答え:

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

最初の9個の穴をランダムに生成し、?9#3それらをコピーして反転(,2-])(3を5に、5を3に変換)して最終9を生成します。これにより、合計が72になることが保証されます(3穴ごとの平均合計は4および4x18 = 72です)。次に、結果({~?~@#)をランダムにシャッフルして、すべての組み合わせが可能になるようにします。


実際には{3,5,4,4,4 ...}を生成しません。結果全体をシャッフルする方が良いでしょう
ラチェットフリーク

@rachetfreak良い点。今すぐ編集します。
ガレス

13

MS-DOSでの16ビットx86マシンコード-45バイト

Hexdump:

0E5F576A12595188ECE44088C3E44130D8240374F400C4AAE2EF595E80FC2475DFAC0432CD29B020CD29E2F5C3

Base64コード化バイナリ:

Dl9XahJZUYjs5ECIw+RBMNgkA3T0AMSq4u9ZXoD8JHXfrAQyzSmwIM0p4vXD

コメント付きの実際のソースコード:

 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.

nasm 18h.asm -o 18h.comMS-DOS(またはDosbox)、または32ビットWindowsバージョンのNTVDMでコンパイルして実行します。

サンプル出力:

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

3
アセンブラーが大好き...
woliveirajr

13

Mathematica 71 68 66 60

Tallyの提案により6文字が保存されました。

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}

すべての可能な結果が可能ですが、それらは等しくありそうにありません。


分析

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

72の10個の可能なパーティション(組み合わせではなく、組み合わせ)をすべて、3、4、5からなる18個の要素に生成します。

パーティション


RandomChoice それらの1つを選択します。

RandomSample その選択の順列を返します。


Hehe、RandomIntegerの代わりにRandomChoiceを使用して、ほぼ同じ答えを投稿しようとしていました。そうすることで、さらに4つのキャラクターを剃ることができると思います。
タリー14

タリー、ありがとう。あなたの提案は役に立ちました。
DavidC 14

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

アルゴリズムは@sgrieveに似ています。


上記の@sgrieveと同じ問題-それが18のホールを通過することを妨げるものは何もありません。
gt6989b

3
これは問題ではありません。この場合のサンプルコマンドは常に18個の値を生成します。
12

8

GolfScript(26文字)

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

Ilmariのソリューションには明らかな類似点がいくつかありますが、明らかな違いもあります。特に、平均額が4であるという事実を利用しています。


くそー、それは確かにそこにループ条件を持つ巧妙なトリックです。私は{;0{3.rand+.@+}18*])72-}do自分で思いついた が、そこから短くする方法を理解できなかった。+1。
イルマリカロネン

7

Python 77

コード

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

出力

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

インポートは本当にこのソリューションを殺します。numpyを使用して3〜5の18個の数値を生成し、リストの合計が72になるまでリストを生成し続けます。


18個のホールを生成する前に、プログラムが72個に達するのを妨げるものは何ですか?72をスキップできないのはなぜですか?
DavidC

3
コードは常に18ホールを生成し、合計が72に等しいかどうかを確認します。たとえば、16ホール後の合計が72であった場合、さらに2ホールが生成され、合計が72を超えてテストに失敗します。
sgrieve

7

GolfScript、27文字

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

sgrieveのPythonソリューションと同じ拒否サンプリング方法を使用します。したがって、実際にはすべての有効な出力が等しく発生する可能性があります。


7

Q(25文字)

オリジナル(27)

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

サンプル出力

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

少し短い(25)

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

7

JavaScript、66 64 61文字

TwoScoopsofPig(PHP)および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

2
s!=72s-721文字を保存することができます。そして、最後のセミコロン;aは別の文字にも必要ありません。
ジョータスカン

for(i=x;i;i--)から2文字を保存する前に見たことがないfor(i=0;i<x;i++)、ありがとう!
数学チラー

7

Python 2、70バイト

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

sgrieveのソリューションに似たもう1つを次に示します。

Python 2、73バイト+等しい確率

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

5

JavaScript、116 99 65バイト

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

1
これをChrome 21で実行すると、が表示されますi is not defined
mellamokb

5

Python、128 120 116文字

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

import ステートメントはまだ長さキラーです(ネームスペースに2つの関数をインポートする場合のみ23文字)

このコードは、ランダムに選択する前にすべての可能なソリューションを最初に評価するため、近い将来結果を必要としないことを願っています。この問題の最も遅い解決策かもしれません。

私は各構成の等しい確率のために余分な名誉を主張しています...


4
import random,itertools
-grawity

あなたは正しい、それは物事を少し短縮します。
エイドリアンプリソン

その他のヒント:andの代わりにandをimport random as r,itertools as i使用します 使用の代わりに、と代わりに:)rirandomitertools18*[0]range(18)[3,4,5,6]range(3,6)
アレックス・L

私はPython 3を使用しています:リスト内包表記はジェネレータであり、長さを持たないため、choice()関数での使用は禁止されています。...遅いので、このコードを作るものもありますその
エイドリアン・プリッソン

1
申し訳ありませんが、リストの理解とジェネレーター式を台無しにしました(イテレーターのパフォーマンスが向上するため、一般的にジェネレーター式を優先してリストの理解を避けます)。確かに、python3でも、いくつかの文字を削除できます... @Alexはそれを正しく行いました。
エイドリアンプリソン

4

PHP-77文字

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

sgrieveのソリューションと同じように、これは18個のホールのリストを作成し、合計額をチェックし、それを印刷するか拒否して再試行します。奇妙なことに、2つのソリューションは同じ長さです。

面倒なことに、PHPは名前の簡潔さを備えた配列関数を提供していません。Array_sumとprint_rは私を殺している。提案を歓迎します。


1
ここでは中括弧は不要であり、sumが必要になる場合があります+=<?while($s!=72)for($s=$i=0;18>$i;$s+=$a[++$i]=rand(3,5));print_r($a);
-grawity

私はロジックを置くことを考えたことはありません-それは便利だ中でループのためのコール(と私はサムのためのカウンタをインクリメントないためちょっとダム感じます)。
TwoScoopsofPig

ありがとう-しかし、それは実際には「中括弧は不要」という意味ではありません。元のコードでそれらを削除することもできますwhile(array_sum($a)!=72)for($i=0;18>$i;)$a[++$i]=rand(3,5);
。–粗さ

私は仕事中にゴルフをしているので、それよりも厳しいphp.iniに対して実行することを除いて、中かっこがない、または不一致であることに文句を言います。通常私が持っているでしょう。
TwoScoopsofPig

それは変だ; 5.4.7 with E_ALL | E_STRICTは、欠落していることについて文句を言いません{}(PHPの構文では明示的に許可されているため)。
悲しみ

4

Ruby 1.9(62文字)

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

レール(55文字)

$ rails c(任意のRailsのフォルダ内)REPL:

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

注:のshuffle[0]代わりに使用すると、Ruby 1.8で動作しますsample


2
まで空白が必要ですか?
カズ

@Kazあなたは正しい、それは必要ありません。:) 62文字になりました。
jsコーダー

1
を使用(1..18).map{rand(3)+3}してランダム配列を取得できます;)
エピデミアン

4

Lisp(78 69文字)

(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))

sgrieveのPythonソリューションに似ています。

NILとしてcから開始し、72の合計をチェックし、docの「インクリメント関数」は3から5の間の18個の数字のリストを生成し、再度72をチェックし、泡立て、すすぎ、繰り返します。

一緒にゴルフを見doたり、loop素敵にプレーしたりするのは爽快です。


3

C(123文字)-効率への取り組み

wcをパイプ処理すると、10秒以内にすべての44152809ソリューションが生成されます...

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);}

ああ、まあ-質問を正しく読みませんでした-しかし、すべてのソリューションを生成している場合、等しい確率でランダムなソリューションを選択することは、スクリプトの練習です:P


3

クロージュア-55

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

非常に面白いトリック.... 5パーホールと正確に同じ数の3パーホールがなければならないという問題の数学的構造を活用します。


3

Python 83

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

sgrieveのソリューションに似ていますが、numpyはありません

ゴルフAdrien Plissonのソリューション: 120-> 108文字

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

出力

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


良いアプローチですが、randi([3,5],1,18)代わりに次のように入力することで4バイトを節約できます3+floor(rand(1,18)*3)
。brainkz

3

Java(61文字)

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

サンプル出力:

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

私はJavaの専門家ではありませんが、sとiの宣言、およびSystem#println(..)の呼び出しがあるべきではありませんか?
hiergiltdiestfu

これは単なるコードスニペットであり、プログラムではありません。実際、@ JoeIbanezのCバージョンに非常によく似ています。
フランツD.

2

C(94文字)

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]);

s=0初期化されていないintは72に等しくなるチャンスは何であるため、ライン1上の必要でないかもしれませんか?私はまっすぐなCで初期化されていない値を読むのが好きではありません。また、これにはおそらくrand()関数のシードが必要です。

出力

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

だから基本的には、1つが72に等しくなるまで3から5の範囲の18個の数字のランダムな文字列をループするのですか?良いものの効率は必須ではありません。
キース

5
@KeithS公平を期すために、それがこの質問に対する回答の大半が行っていることです。
ガレス

2

Bashシェルスクリプト(65文字)

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

shufは、GNU coreutilsパッケージに含まれています。また、Garethに感謝します。)


2

C#(143空白以外):

()=>{
  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);
}

new Guid()空のGUIDを作成します。一意のGUIDを実際に生成するには、静的メソッドを呼び出す必要がありますGuid.NewGuid
ローター

そして、あなたは2つのoff-by-oneエラー(いわば)を持っています:比較はi <nとi> = 18-nであるべきであり、その逆ではありません。また、x-1の代わりに定数3を使用し、x + 1の代わりに5を使用して、サイズを縮小できます。そして、Enumerable.RepeatをEnumerable.Rangeに置き換えることができます。
モルメギル

編集済み; まだ143文字
キース

ありませんMath.Random、そうSystem.Randomです。
CodesInChaos

別のC#アプローチ(143文字):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 14年

2

Haskell、104 102 98文字。

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

[1..n]>>[r]は、より少し短いですreplicate n$r
反時計回りに

に変更されsequenceましたmapM
ローター

2

Perl、74

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

代替ソリューション:

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

2

TXR(99文字)

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

この式は、3〜5の乱数の無限レイジーリストを生成します。

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

残りのロジックは、このリストの最初の18個の要素が合計72個かどうかをチェックする単純なループです。そうでない場合は、要素をポップし、再試行します。forループと呼ばれる暗黙のブロックを含むnilので、(return ...)ループおよび戻り値を終了するために使用することができます。

99文字の長さには終了改行が含まれていることに注意してください。これは必須です。


(t)を()に置き換えることができるコミットを入れました。:)
カズ

2

APL 12

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

インデックスの原点は0に設定されていることに注意してください。つまり、配列は0から始まります⎕IO←0。これはで設定できます。


質問は、可能なすべての構成を生成できるプログラムを要求します。あなたのものは、シンメトリックなものを作成できます。たとえば555455555333333343を作成することはできません。少なくとも私にはそう思えます。
モリスズッカ14

2

R、42バイト

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

sample、デフォルトでは、可能な値の間で均等に描画します(こちら3 4 5)。r=Tは、replace=TRUEサンプルの交換を可能にします。


2

CJam、17 14バイト

CJamはこの課題よりも新しいものですが、これはとにかく最短の回答ではないため、それは実際には重要ではありません。

Z5]Amr*I4e]mrp

ここでテストしてください。

合計72個を維持するには、それぞれ3をとペアにする必要があります5。そのため、次のように機能します。

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.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.