Знайдіть кількість одиниць, щоб отримати число за допомогою + і *


28

Вступ

Ваша мета - знайти найменшу кількість одиниць, які потрібно додати або помножити разом, щоб отримати вхідне значення, це A005245 .

Вхідні дані

Один натуральне число N .

Вихідні дані

Найменше число тих , які повинні бути додані / множаться , щоб отримати N .

Зразок введення

7

Вибірка зразка

6

Пояснення

( 1+ 1+ 1) * ( 1+ 1) + 1= 7

Оскільки для цього потрібні 6такі, вихід є6

Тестові справи

 1  1
 2  2
 3  3
 5  5
10  7
20  9
50 12

Оскільки це проблема з , виграє найменша кількість байтів.



9
Ласкаво просимо до головоломки програмування та коду для гольфу! Як перший виклик, це нормально, але наступного разу, будь ласка, використовуйте « Пісочницю» перед публікацією викликів, щоб отримати зворотній зв'язок!
betseg

4
Я б запропонував змінити це, щоб явно вказати, що ви шукаєте необхідну мінімальну кількість. Інакше просто вивести оригінальне число і стверджувати, що це кількість тих, які потрібно скласти разом, було б дійсним рішенням.
Кудлатий

2
Чи є приклади, коли f(x) != x.primeFactorisation().sum()крім 1?
jrtapsell

1
@jrtapsell: так. Наведений приклад $ f (7) = 6 $ - це один. Для будь-якого (достатньо великого) простого $ p $ ви можете розподілити $ p-1 $ і додати його. Можливо, ви зможете зробити ще краще.
Росс Міллікан

Відповіді:


17

Python 2 , 74 70 байт

f=lambda n:min([n]+[f(j)+min(n%j*n+f(n/j),f(n-j))for j in range(2,n)])

Спробуйте в Інтернеті!

Альтернативна версія, 59 байт (неперевірена)

f=lambda n:min([n]+[f(j)+f(n/j)+f(n%j)for j in range(2,n)])

Це працює принаймні до n = 1 000 000 , але я ще повинен довести, що це працює для всіх позитивних n .

Спробуйте в Інтернеті!


Вибачте, якщо я пропускаю щось просте, але очевидно, що це намагається виконувати кожне життєздатне дерево виразів. Зокрема, ми маємо зовнішній шар n=a*j+bз b<j, але , можливо , нам потрібно b>=j?
xnor

Гм, це буде невдалим, лише якщо і те b>=jі інше b>=a. Але ти маєш рацію, не очевидно, що цього не станеться.
Денніс

Цікаво, що не існує контрприкладів до 1 000 000, мені цікаво, чи це насправді просто завжди працює. Моя найкраща думка для контрприкладу була б якоюсь формою a*b+c*dз a,b,c,dусіма виразами підсумовування і є дуже ефективною.
xnor

10

Желе , 16 14 байт

Дякуємо Деннісу, що врятував 2 байти!

ÆḌḊ,Ṗ߀€+U$FṂo

Спробуйте в Інтернеті!


Логічне пояснення

Дано число n :

  • Якщо це так 1, відповідь така 1. Інакше:

Представлення - це a + bабо a × b, де aі bє виразами.

Розглянемо всі можливі значення aта b:

  • Якщо представлення є a + b, то aі bзнаходяться в діапазоні [1 .. n-1].
  • Якщо уявлення a × b, aі bє власні подільники nбільше 1.

В обох випадках список [[<proper divisors of n larger than 1>], [1, 2, ..., n-1]]обчислюється ( ÆḌḊ,Ṗ), відображається поточне посилання над кожним числом ߀€, додаються правильні пари разом ( +U$) та отримують мінімальне значення ( FṂo).

Пояснення коду

ÆḌḊ,Ṗ߀€+U$FṂo   Main link. Assume n = 10.
ÆḌ       Proper divisors. [1,2,5]equeue, remove the first element. [2,5]
   ,Ṗ    Pair with op. Auto convert n = 10 to range 
         [1,2,3,4,5,6,7,8,9,10] and remove the last element
         10, get [1,2,3,4,5,6,7,8,9].

߀€      Apply this link over each element.
   +U$   Add with the Upend of itself.

FṂ       Flatten and get the inimum element.
  o      Logical or with n.
         If the list is empty, minimum returns 0 (falsy), so logical or
         convert it to n.

5

JavaScript (ES6), 108 96 байт

f=n=>n<6?n:Math.min(...[...Array(n-2)].map((_,i)=>Math.min(f(++i)+f(n-i),n%++i/0||f(i)+f(n/i))))

Дуже неефективно; Array(n>>1)прискорює його трохи за рахунок байта. Пояснення: n%++iне є нульовим, якщо iне є фактором, так n%++i/0є Infinity(і, отже, неправдоподібний, і, безумовно, не мінімальний), якщо iне є фактором, але NaN(і, отже, хибним), якщо iє фактором. Редагувати: збережено 12 байт з натхненням від @ edc65.


Я спробував запустити це у фоновому режимі, щоб побачити, чи він насправді здатний обчислювати, f(50)але, на жаль, оновлення Windows перезавантажило мій ПК, перш ніж воно могло закінчитися.
Ніл

Ви пробували одиночну прогулянку по масиву?
edc65

@ edc65 Вибачте, але мені незрозуміло, що ви пропонуєте і чому.
Ніл

Я бачу 2 карти, кожна з яких сканує aмасив. Не можете ви злити оцінки в 2 лямбдах і взяти хв?
edc65

@ edc65 О так, чомусь я думав, що введення мінімуму не буде дешевше, але я можу замінити (i+=2)іншим, ++iтому я заощаджую 12 байт загалом, дякую!
Ніл

5

Парі / GP , 66 байт

Порт Dennis's Python відповідь :

f(n)=vecmin(concat(n,[f(j)+min(n%j*j+f(n\j),f(n-j))|j<-[2..n-1]]))

Спробуйте в Інтернеті!


Парі / GP , 72 байти

Більш довгі, але ефективніші:

f(n)=if(n<6,n,vecmin([if(d>1,f(d)+f(n/d),1+f(n-1))|d<-divisors(n),d<n]))

Спробуйте в Інтернеті!


1
Денніс поліпшив свій метод і використання , яке може заощадити вам 11 байт: f(n)=vecmin(concat(n,[f(j)+f(n\j)+f(n%j)|j<-[2..n-1]])).
Джонатан Аллан


3

Пітон 2 , 181 байт

def F(N,n,s="",r=""):
 try:
	if n<1:return(eval(s)==N)*0**(`11`in s or"**"in s)*s
	for c in"()+*1":r=F(N,~-n,s+c)or r
 except:r
 return r
f=lambda N,n=1:F(N,n).count(`1`)or f(N,-~n)

Спробуйте в Інтернеті!


@ pizzapants184 Основна функція fне повинна бути анонімною, оскільки вона називає себе рекурсивно.
Джонатан Фрех

Ах, вибачте, я цього не бачив.
pizzapants184

2

Мова Вольфрама (Mathematica) , 59 байт

Збережено 3 байти завдяки Мартіну Ендеру. Використання кодування CP-1252, де ±є один байт.

±1=1;±n_:=Min[1+±(n-1),±#+±(n/#)&/@Divisors[n][[2;;-2]]]

Спробуйте в Інтернеті!


2
Використання ±замість fзбереження 3 байти, припускаючи, що джерело закодовано в CP 1252: tio.run/##y00syUjNTSzJTE78///QRkNbQ@tDG/PirWx9M/…
Мартін Ендер

1
Не працює належним чином для введення даних 353942783.
Міша Лавров

1

Perl 5 , -p 78 байт

Підрахунок 79 байт у старому стилі ( +1для -p)

Той факт, що Perl повинен використовувати додатковий $для всього скалярного доступу, дійсно шкодить довжині гольфів, які роблять багато арифметичних ...

Цей метод здебільшого подібний до інших, які вже розміщені (спробуйте множення та додавання, щоб скласти цільове число, візьміть найдешевший). Однак він не повторюється повторно, тому його можна використовувати для порівняно великих входів.

Він також не намагається мінімізувати витрати на створення числа шляхом додавання чи множини [зобов’язання, оскільки в perl 5 немає вбудованого, minа числовий сорт є looooooong (як видно з сортування, що все ще знаходиться в коді). Натомість я просто припускаю, чи число є фактором цілі, що я буду використовувати множення. Це безпечно, оскільки якщо, наприклад, 3є коефіцієнтом 12(значить, це підсумовує вартість 3і 12/3) пізніше в циклі він врахує, 9=12-3що не буде фактором, тому 9+3з тією ж вартістю, яку будь-коли 3+9спробують. Однак це може не вдатися до цілей <= 4(це стосується лише 1і 2). Додавання $_до списку для мінімізації виправлень. Що прикро, оскільки мені це фактично не потрібно для базових справ, тому що я вже ініціалізую@; з правильними початковими значеннями, так що це коштує 3 байти.

#!/usr/bin/perl -p
($_)=sort{$a-$b}$_,map{$;[$_]+$;[$'%$_?$'-$_:$'/$_]}//..$_ for@;=0..$_;$_=pop@

Спробуйте в Інтернеті!

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