Золотість цілого числа


21

Позитивне ціле число n може бути представлено у вигляді прямокутника з цілими сторонами a , b таким, що n = a * b . Тобто площа представляє число. Загалом, a і b не є унікальними для даної n .

Як відомо, прямокутник особливо приємний для ока (чи це мозок?), Коли його сторони знаходяться в золотому співвідношенні , φ = (sqrt (5) +1) / 2 ≈ 1.6180339887 ...

Поєднуючи ці два факти, мета цього виклику полягає в тому, щоб розкласти ціле число n на добуток двох цілих чисел a , b , відношення яких максимально наближене до φ (при звичайній метриці на ℝ). Той факт, що φ ірраціональний, означає, що існує унікальна пара рішення ( a , b ).

Змагання

Враховуючи додатне ціле число n , виведіть додатні цілі числа a , b такі, що a * b = n і абсолютна різниця між a / b і φ зведена до мінімуму.

Як приклад, розглянемо n = 12. Пари ( a , b ), які задовольняють a * b = n, є: (1, 12), (2,6), (3,4), (4,3), ( 6,2), (12,1). Пара, відношення якої найближче до φ, дорівнює (4,3), що дає 4/3 = 1,333.

Правила

Функції або програми прийнятні.

Чисельник ( ) повинен з'явитися першим на виході, а знаменник ( б ) другий . Крім цього, формати введення та виведення є гнучкими, як зазвичай. Наприклад, два числа можуть бути виведені як рядки з будь-яким розумним роздільником, або як масив.

Код повинен теоретично працювати для довільно великих чисел. На практиці це може бути обмежено пам'яттю або обмеженнями типу даних.

Досить розглянути приблизну версію φ , якщо вона точна до третьої чи більшої десяткової . Тобто абсолютна різниця між справжнім φ і приблизним значенням не повинна перевищувати 0,0005. Наприклад, 1.618 прийнятно.

При використанні наближеної, раціональної версії φ є невеликий шанс, що рішення не буде унікальним. У цьому випадку ви можете вивести будь-яку пару a , b, яка відповідає критерію мінімізації.

Найкоротший код виграє.

Тестові кейси

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|є багатообіцяючою, хоча доказ був би в порядку
Луїс Мендо

Не впевнений, що я можу зафіксувати цілий доказ у коментарі, але контур такий: весь прямокутник являє собою a/b. Видалення одиничного квадрата залишає невеликий прямокутник праворуч, який представляє b/a. Таким чином, золотий прямокутник досягає різниці 1.
Ніл

Якщо a і b не є суміжними числами в послідовності Фібоначчі, чи є якийсь момент, що включає їх у тесті?
Полуниця

Це означає, що 1618 x 1000 здається хорошим кандидатом (або, посиланням, 809 x 500)
Полуниця

Відповіді:


6

Желе, 16 15 14 байт

Збережено 1 байт завдяки @miles.

÷/ạØ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 Класно! Я, мабуть, зовсім пропустив /. (Це я зробив у своєму рішенні Pyth.) Буде редагуватися, коли я переходжу на свій ноутбук.
PurkkaKoodari


6

Матлаб, 96 81 байт

Гольф (-15 байт), реквізит до Луїса Мендо

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ви зможете позбутися find:a=find(~(mod(n,1:n)));[~,c]=min(abs(a./(n./a)-1.618));[a(c) n/a(c)]
Луїс Мендо

Добре помічений - це оббриває цілком деякі символи!
птев

1
Ви можете скоротити його, використовуючи n=input('');замість цього, у function w(n);вас є додаткова пара ()навколо mod.
недолік


5

Математика, 51 байт

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

Є Постфіксний Mathematica в транспозиції (відображається у вигляді верхнього індексу Tв Mathematica).

У Mathematica є вбудований GoldenRatio, але 1.618 набагато коротший, тим більше, що вимагає і перший N@.


5

Pyth, 21 20 18 байт

hoacFN.n3C_Bf!%QTS

Спробуйте в Інтернеті. Тестовий набір.

Пояснення

  1. Отримайте Sдіапазон включення ive від 1 до входу.
  2. filter для чисел, які поділяють вхідні дані !%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, для якого n / φ <b²

Тоді рішення є або [a, n / a] або [b, n / b] . Ми порівнюємо n / φ - a² з b² - n / φ, щоб з’ясувати, який вираз найближчий до нуля.

Поточна формула , яка використовується в коді заснована на ф / 2 , який може бути записаний в більш короткому шляху , ніж ф з тією ж точністю: .809проти 1.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.

Тестові кейси

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 ) пару, яка мінімізує абсолютне значення a / b - b / a -1, але це працює принаймні для всіх тестових випадків, хоча, мабуть, я міг би зберегти 4 байти, використовуючи замість тесту 1.618 .


3

Брахілог , 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: Перетворіть інт на поплавок, перевернувши його обернену

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

З цікавості: чи φє заздалегідь заданий літерал у Брахілозі? Або де це визначено в коді?
Луїс Мендо

1
О, я щойно бачив:$A
Луїс Мендо

2
@LuisMendo Afor Au;)
Фаталізувати

Ааа, дуже приємно!
Луїс Мендо

2

Haskell (Lambdabot), 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, тому це не можна запускати так. Це означає, що змінити його на readline () або fgets (STDIN), якщо ви знаходитесь у Windows та працює без тегу, швидше за все, коротше.
користувач59178

-rі $argvдобре працюємо разом: pastebin.com/vcgb5pT2
манатура

Ага. Ну, це не працює для мене, я просто отримую не визначені змінні повідомлення, мені цікаво, чи це налаштування чи це просто вікна, як зазвичай.
user59178

Ви все ще можете замінити <?phpз , <?щоб зберегти три байта.
Пол Шмітц

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 на один байт довше.

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]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.