整数の黄金度


21

正の整数nは、n = a * bとなるように、整数辺 abを持つ長方形として表すことができます。つまり、面積は数値を表します。一般に、abは与えられたnに対して一意ではありません。

よく知られているように、長方形の辺が黄金比である場合、長方形は目にとって特別に心地よい(または脳ですか?)、φ =(sqrt(5)+1)/ 2≈1.6180339887 ...

これらの2つの事実を組み合わせて、この課題の目的は、整数nを2つの整数abの積に分解することです。その比率は、φに可能な限り近い(usualの通常のメトリックで)。φが無理であるという事実は、一意の解のペア(ab)があることを意味します。

チャレンジ

正の整数で指定されたN、出力正の整数、Bよう * B = Nとの差の絶対値/ Bφが最小化されます。

一例として、考えるN対(= 12 、B満たす)* B = N(1、12)、(2,6)、(3,4)、(4,3)、(:あり6,2)、(12,1)。比率がφに最も近いペアは(4,3)で、4/3 = 1.333になります。

ルール

機能またはプログラムは受け入れ可能です。

分子()が表示されなければならない最初の出力で、かつ分母B第二。それ以外は、入力および出力形式は通常どおり柔軟です。たとえば、2つの数値は、適切な区切り文字を含む文字列として、または配列として出力できます。

このコードは、任意の大きな数値に対して理論的に機能するはずです。実際には、メモリまたはデータ型の制限によって制限される場合があります。

3番目の小数以下の精度である限り、φの近似バージョンを考慮するだけで十分です。つまり、真のφと近似値の絶対差は0.0005を超えてはなりません。たとえば、1.618は許容範囲です。

近似の合理的なバージョンのφを使用する場合、解が一意ではない可能性がわずかにあります。その場合、最小化条件を満たす任意のペアabを出力できます。

最短のコードが優先されます。

テストケース

1        ->  1    1
2        ->  2    1 
4        ->  2    2
12       ->  4    3
42       ->  7    6
576      ->  32   18
1234     ->  2    617
10000    ->  125  80
199999   ->  1    199999
9699690  ->  3990 2431

たとえば、a / bb / aの結果を含む回答が可能な限り1に近い場合を除き、ほとんどの回答では、φに対する何らかの合理的な近似を使用します。
ニール

@Neil私はあなたのコメントを理解しているかどうかわかりません。最小化のあなたのアイデアは、|a/b-b/a-1|証拠が順番になるでしょうが、約束している
ルイスMendo

証拠全体をコメントに詰め込めるかどうかはわかりませんが、概要は次のとおりです。長方形全体がを表しa/bます。単位の正方形を削除すると、右側にを表す小さな長方形が残りb/aます。したがって、黄金の長方形は1の差を実現します
ニール

aとbがフィボナッチ数列の隣接する数値でない場合、テストでそれらを含む点はありますか?
イチゴ

そうは言っても、1618 x 1000は良い候補のように思えます(または、参照により、809 x 500)
ストロベリー

回答:


6

ゼリー、16 15 14バイト

@milesのおかげで1バイト節約されました。

÷/ạØp
ÆDżṚ$ÇÞḢ

オンラインでお試しください!

説明

÷/ạØp         Helper link, calculates abs(a/b - phi). Argument: [a, b]
÷/            Reduce by division to calculate a/b.
  ạØp         Calculate abs(a/b - phi).

ÆDżṚ$ÇÞḢ      Main link. Argument: n
ÆD            Get divisors of n.
  żṚ$         Pair the items of the list with those of its reverse. The reversed
              divisors of a number is the same list as the number divided by each
              of the divisors.
     ÇÞ       Sort by the output of the helper link of each pair.
       Ḣ      Get the first element [a, b] and implicitly print.

除数リストの逆をそれ自体でインターリーブすることにより、バイトを保存できます。÷/ạØp¶ÆDżṚ$ÇÞḢ14バイトを使用して、引数として[a, b]指定さnれたリストを返します。
マイル

@miles Cool!私はどうやら完全に逃したようだ/。(これは私がPythソリューションで行ったことです。)ラップトップに乗ると編集します。
-PurkkaKoodari


6

Matlab、96 81バイト

Golfed(-15bytes)、に小道具ルイスMendo

function w(n);a=find(~(mod(n,1:n)));[~,c]=min(abs(a./(n./a)-1.618));[a(c) n/a(c)]

元の:

function w(n)
a=find(not(mod(n,1:n)));b=abs(a./(n./a)-1.618);c=find(not(b-min(b)));[a(c) n/a(c)]

これは間違いなく素晴らしい解決策ではありませんが、コードゴルフでの私の最初の試みです。なんて楽しい!


2
楽しいことに同意しました!サイトへようこそ!
DJMcMayhem

1
あなたは置き換えることができますnotによって~ 数バイトを保存します。また、第二の出力使用してmin、あなたが取り除くことができますfinda=find(~(mod(n,1:n)));[~,c]=min(abs(a./(n./a)-1.618));[a(c) n/a(c)]
ルイスMendo

よくわかりました-それはかなりのシンボルを削ります!
ptev

1
あなたは使用して、それを短くすることができますn=input('');代わりにfunction w(n);、あなたは余分なペア持って()周りmod
flawr


5

Mathematica、51バイト

#&@@SortBy[{x=Divisors@#,#/x},Abs[#/#2-1.618]&]&

(上付き文字として表示さ転置のためのMathematicaの後置演算子であるTMathematicaで)。

Mathematicaには組み込み機能がGoldenRatioありますが、特に前者にもが必要なため、1.618ははるかに短くなっていますN@


5

Pyth、21 20 18バイト

hoacFN.n3C_Bf!%QTS

オンラインでお試しください。 テストスイート。

説明

  1. インクルージョンを取得S1から入力までの範囲をします。
  2. f入力を除算する数値のフィルター !%QT
  3. 取得する [that list, that list reversed] _Bます。数値の逆数の除数は、各除数で除算された数と同じリストです。
  4. リストを転置して、ペアを取得します [numerator, denominator]ます。
  5. S ortペアaの比率cFNと黄金比の絶対差によるペア.n3
  6. 最初の(最低の)ペアhを取得して印刷します。

5

Javascript(ES6)、73バイト

n=>{for(b=0,k=n/.809;n%++b||k>b*b*2&&(a=b););return[b=k-a*a>b*b?b:a,n/b]}

私たちは探します:

  • a = nの最高除数で、n /φ>a²
  • b = n /φ<b²のnの最小除数

そして、解は[a、n / a]または[b、n / b]のいずれかです。n /φ-a²b²-n /φを比較しますして、ゼロに最も近い式を見つけます。

同じ精度でφよりも短いように書くことができるφ/ 2に基づいてコードで使用される実際の式:.809VS1.618

したがって:

n /φ >a²⇔n /(φ/ 2)>2a²

そして:

n /φ-a²>b²-n /φ⇔2n /φ-a²>b²⇔n /(φ/ 2)-a²>b²

複雑

反復の数は、nの因子の数に大きく依存します。最悪の場合は、nが素数の場合に発生します。1からnまでのすべての反復を実行して、その2つの除数を見つける必要があるためです。これは199999で発生することです。一方、9699690は19スムーズであり、ブレークポイント√(n /φ)≈2448の両側に2つの除数がすぐに見つかります。

テストケース

let f =
n=>{for(b=0,k=n/.809;n%++b||k>b*b*2&&(a=b););return[b=k-a*a>b*b?b:a,n/b]}

console.log(JSON.stringify(f(12)));       // [ 3, 4 ]
console.log(JSON.stringify(f(42)));       // [ 6, 7 ]
console.log(JSON.stringify(f(576)));      // [ 18, 32 ]
console.log(JSON.stringify(f(1234)));     // [ 2, 617 ]
console.log(JSON.stringify(f(10000)));    // [ 80, 125 ]
console.log(JSON.stringify(f(199999)));   // [ 1, 199999 ]
console.log(JSON.stringify(f(9699690)));  // [ 2431, 3990 ]


4

JavaScript(ES6)、83バイト

f=
n=>{p=r=>Math.abs(r/n-n/r-1);for(r=i=n;--i;)r=n%i||p(i*i)>p(r*r)?r:i;return[r,n/r]}
;
<input type=number min=1 oninput=[a.value,b.value]=f(+this.value)><input readonly id=a><input readonly id=b>

実際にa / b - b / a -1 の絶対値を最小化する(ab)ペアを返しますが、これは少なくともすべてのテストケースで機能しますが、代わりに1.618テストを使用することで4バイト節約できます。


3

Brachylog、41バイト

:1fL:2a:Lzoht
,A:B#>.*?!,.=
:3a/:$A-$|
//

オンラインでお試しください!

説明

  • 主な述語:

    :1fL           L is the list of all couples [A:B] such that A*B = Input (see Pred. 1)
        :2a        Compute the distance between all As/Bs and φ (see Pred. 2)
           :Lz     Zip those distances to L
              o    Sort the zip on the distances
               ht  Take the couple [A:B] of the first element of the sorted list
    
  • 述語1:出力は次の[A:B]ようなカップルですA*B = Input

    ,A:B           The list [A:B]
        #>         Both A and B are strictly positive
          .        Output = [A:B]
           *?      A*B = Input
             !,    Discard other choice points
               .=  Assign a value to A and B that satisfy the constraints
    
  • 述語2:A/Bとの間の距離を計算します。

    :3a            Convert A and B to floats
       /           Divide A by B
        :$A-       Subtract φ
            $|     Absolute value
    
  • 述語3:intを逆に反転してfloatに変換する

    /              1/Input
     /             Output = 1/(1/Input)
    

好奇心から:φBrachylogの定義済みリテラルはありますか?または、コードのどこで定義されていますか?
ルイスメンドー

1
ああ、私はちょうど見た:$A
ルイスメンドー

2
@LuisMendo Afor Au;)
16

ああ、とてもいい!
ルイスメンドー

2

Haskell(ラムダボット)、86バイト

f(x,y)=abs$(x/y)-1.618
q n=minimumBy((.f).compare.f)[(x,y)|x<-[1..n],y<-[1..n],x*y==n]

2

php、103バイト

<?php for($s=$a=$argv[1];++$i<$a;)if($a%$i==0&&$s>$t=abs($i*$i/$a-1.618)){$n=$i;$s=$t;}echo"$n ".$a/$n;

未割り当ての$ iに関する通知を生成します(実行は中断されません)。したがって、通知を黙らせる環境で実行する必要があります。


PHPのオープンタグをカウントする必要はありませんphp -r '…'(コードは(-r無料で)実行できます)。そしてshort_open_tag、デフォルトでオンになっているように、長い形式は間違いなく必要です。
マナトワーク

私の知る限り、$ argvは-rで動作しないため、とにかくこれを実行することはできません。とにかく、Windowsを使用していてタグなしで実行している場合は、readline()またはfgets(STDIN)に変更することは、おそらくとにかく短くなります。
-user59178

-rそして、$argv一緒にうまく働いている:pastebin.com/vcgb5pT2
manatwork

ほら まあそれは私にとってはうまくいきません、私は未定義の変数通知を受け取ります、それが設定であるのか、それともいつものように単なるウィンドウであるのか疑問に思います。
user59178

あなたはまだ置き換えることができ<?php<?3つのバイトを保存します。
ポールシュミッツ

1

Python 3、96バイト

非常にシンプルなソリューション。このSO回答を利用します

lambda n:min([((i,n//i),abs(1.618-i/(n//i)))for i in range(1,n+1)if n%i<1],key=lambda x:x[1])[0]

オンラインで試す

Python 2の同じソリューションは1バイト長くなります。

lambda n:min([((i,n/i),abs(1.618-1.*i/(n/i)))for i in range(1,n+1)if n%i<1],key=lambda x:x[1])[0]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.