Найдите количество единиц, чтобы получить число, используя + и *

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

Так как это проблема , выигрывает наименьшее количество байтов.

Спирали Чюу
источник
4
OEIS A005245
бетсег
9
Добро пожаловать в программирование головоломок и Code Golf! В качестве первого задания это нормально, но в следующий раз, пожалуйста, используйте Песочницу, прежде чем публиковать задания, чтобы получить обратную связь!
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.
user202729
источник
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(и , следовательно , truthy, а также , безусловно , не является минимальным) , если iне является фактором, но NaN(и , следовательно , falsy) , если iэто фактор. Изменить: 12 байтов сохранены с вдохновением от @ edc65.

Нил
источник
Я попытался запустить его в фоновом режиме, чтобы увидеть, действительно ли он способен вычислять, f(50)но, к сожалению, Windows Update перезагрузил мой компьютер, прежде чем он мог завершить работу.
Нил
Вы пробовали пройтись по массиву?
edc65
@ edc65 Извините, но мне неясно, что вы предлагаете и почему.
Нил
Я вижу 2 карты, каждая сканирует aмассив. Разве вы не можете объединить оценки в 2 лямбды и взять мин?
edc65
@ edc65 Ах да, по какой-то причине я подумал, что вложение min будет дешевле, но я заменяю его (i+=2)другим, ++iпоэтому я экономлю всего 12 байт, спасибо!
Нил
5

Пари / ГП , 66 байт

Порт Дениса Python ответ :

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

Попробуйте онлайн!


Пари / ГП , 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]))

Попробуйте онлайн!

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

Python 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

Wolfram Language (Mathematica) , 59 байт

Сохранено 3 байта благодаря Мартину Эндеру. Использование кодировки CP-1252, где ±один байт.

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

Попробуйте онлайн!

alephalpha
источник
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а числовая сортировка слишком длинная (как видно из сортировки, все еще находящейся в коде). Вместо этого я просто предполагаю, что если число является целевым фактором, я буду использовать умножение. Это безопасно, так как если, например, 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@

Попробуйте онлайн!

Тон Хоспел
источник