+と*を使用して1の数を見つけて数を取得


28

前書き

あなたの目標は、入力値を取得するために加算または乗算する必要があるものの最小数を見つけることです。これはA005245です。

入力

一つの正の整数N

出力

Nを取得するために追加/乗算する必要がある最小数。

サンプル入力

7

サンプル出力

6

説明

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

これには61つが必要なので、出力は6

テストケース

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

これは挑戦なので、バイト数が最も少なくなります。



9
プログラミングパズルとコードゴルフへようこそ!最初の課題としてはこれで問題ありませんが、次回は課題を投稿する前にSandboxを使用してフィードバックを取得してください!
betseg

4
これを変更して、必要な最小数を探していることを明示的に示すことをお勧めします。それ以外の場合は、元の番号を出力し、それを加算する必要があると主張するだけで有効なソリューションになります。
シャギー

2
f(x) != x.primeFactorisation().sum()1以外の例はありますか?
jrtapsell

1
@jrtapsell:はい。指定された$ f(7)= 6 $の例は1です。任意の(十分に大きい)プライム$ p $に対して、$ p-1 $を因数分解して追加できます。まだもっとうまくできるかもしれません。
ロス・ミリカン

回答:


17

パイソン274の 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+bb<jはがありb>=jますが、必要かもしれません。
xnor

うーん、との両方の場合のみ失敗b>=jb>=aます。しかし、あなたは正しい、これが起こらないことは明らかではない。
デニス

1,000,000までの反例がないことは興味深いですが、実際には常に機能するのでしょうか。反例に対する私の最善の考えは、すべての総和式をa*b+c*d持つ形式の何かでa,b,c,dあり、非常に効率的です。
xnor

10

ゼリー16 14バイト

2バイトを節約してくれたDennisに感謝します!

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

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


論理説明

番号nが与えられた場合

  • の場合1、答えは1です。さもないと:

表現はa + borのいずれかでa × b、ここでaand bは式です。

aおよびのすべての可能な値を考慮してくださいb

  • 表現がある場合はa + b、その後、aおよびb範囲内にあります[1 .. n-1]
  • 表現がa × baありbnより大きい適切な除数である場合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)1バイトのコストでわずかに高速化します。説明:n%++i場合は、非ゼロであるi要因ではない、そうn%++i/0Infinityなければ(したがってtruthy、また確かに最小ではない)i要因ではなく、NaN(したがってfalsy)場合はi係数です。編集:@ edc65からのインスピレーションで12バイトを保存しました。


これをバックグラウンドで実行して、実際に計算できるかどうかを確認しましたが、f(50)残念ながらWindows Updateが終了する前にPCを再起動しました。
ニール

アレイ上を1回歩いてみましたか?
edc65

@ edc65申し訳ありませんが、あなたが提案していることとその理由についてはわかりません。
ニール

2つのマップがあり、それぞれマップをスキャンしていaます。2つのラムダの評価をマージして最小値を取ることはできませんか?
edc65

@ edc65ああ、何らかの理由で、最小値をネストするのは安くないと思っていましたが(i+=2)、別のものに置き換えることが++iできるので、合計で12バイトを節約しています、ありがとう!
ニール

5

パリ/ GP、66バイト

デニスの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

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言語(Mathematica)、59バイト

Martin Enderのおかげで3バイト節約されました。CP-1252エンコードを使用して、±1バイトです。

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

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


2
ソースがCP 1252でエンコードされていると仮定して、3バイトを保存する±代わりに使用ftio.run
Martin Ender

1
入力353942783.のために正しく動作しない
ミーシャラブロフ

1

Perl 5、-p 78バイト

古いスタイルのカウントで79バイト(+1for -p

perl $がすべてのスカラーアクセスにエクストラを使用しなければならないという事実は、実際に多くの算術を行うゴルフの長さを傷つけます...

このメソッドは、すでに投稿されている他のメソッドとほぼ同じです(乗算と加算を試して、ターゲット番号を作成し、最も安価に取得します)。ただし、繰り返し再帰することはないため、比較的大きな入力に使用できます。

また、perl 5には組み込みminコードがなく、数値の並べ替えが(コード内の並べ替えからわかるように)長いため、加算または乗算によって数値を構築するコストを最小限にしようとしません。代わりに、数値が乗算を使用するターゲットの要素であるかどうかだけを想定しています。例えば場合ので、それは安全である3の要因である12(それはコストを合計して312/3)以降のループでは、それは考慮します9=12-3ので、要因ではないであろう9+3と同じコストで3+9、とにかく試してみましたを取得します。しかし、ターゲットで失敗するかもしれない<= 4(それだけのためにする12)。$_修正を最小限に抑えるためにリストに追加します。既に初期化されているため、基本ケースでは実際に必要ないため、これは残念です@; 適切な開始値を使用して、3バイトのコストがかかります。

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

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

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