素因数の二乗和が減算される範囲の最大数


17

たとえば、数300

  • 300の素因数は[2, 3, 5](300の素数で素数である一意の数)
  • これらの各数値を二乗すると、 [4, 9, 25]
  • そのリストを合計すると、 4 + 9 + 25 = 38
  • 最後に元の数からその合計(38)を引きます300-38 = 262(これが結果です)

入力

入力は2より大きい正の整数になります。2から入力値(両端を含む)までのすべての数値をチェックし、上記の式で最大の結果をもたらす数値を見つける必要があります。


出力

出力は、スペース、コンマ、改行、または言語で許可されているもので区切られた2つの数字になります(2つの数字を区別するには、区切りが必要です)。これらは、ファイル、stdout、または言語で使用されるものに出力できます。目標は、上記の式を実行したときに最大出力を生成する範囲内の数値を見つけることです。表示される最初の番号は開始番号(300など)で、2番目の番号は式が生成した出力(262など)である必要があります


テストケース

Input: 3       Output: 2, -2
Input: 10      Output: 8, 4
Input: 50      Output: 48, 35
Input: 1000    Output: 1000, 971
Input: 9999    Output: 9984, 9802


作業例

10の入力を考慮して、2〜10のすべての数値に対して数式を実行する必要があります(包括的)。

Num PrimeFacs PrimeFacs^2 SumPrimeFacs^2 Result
2   [2]       [4]         4              -2
3   [3]       [9]         9              -6
4   [2]       [4]         4               0
5   [5]       [25]        25             -20
6   [2, 3]    [4, 9]      13             -7
7   [7]       [49]        49             -42
8   [2]       [4]         4               4
9   [3]       [9]         9               0
10  [2, 5]    [4, 25]     29             -19

ご覧のとおり、最大の結果は4であり、これは8式に値を入力した結果です。つまり、入力の出力10は次のようになります。8, 4


スコアリングとルール

入力と出力のデフォルトのルールが適用されます:Code Golfのデフォルト:入出力メソッド
標準の抜け穴は禁止されていますデフォルトで禁止されている抜け穴
は、機能または完全なプログラムです

バイト単位の最短コードが勝つ


いくつかのスペルミスと文法エラーを修正し、タイトルをよりわかりやすくしました。また、空白の区切り文字を許可しないことに関するビットを変更しました。これは明らかに意図したとおりではないためです(改行とスペースは空白文字であるため)。これが意図したものではない場合は、編集を元に戻して、意図を明確にしてください。
メゴ

2
最大の結果を得るために複数の数値が結び付けられている場合はどうなりますか?
デニス

1
@Dennisは、最大の結果を生成する任意の数を許可することはできますか?既存のソリューションをすべて破る新しいルールを課したくありません。
キーティンゲ

2
はい、おそらくそれが最良の選択肢です。950は、[ 900、862][ 945、862]の両方が有効な答えになる例です。
デニス

1
缶I出力、入力のための逆の順序での数字、例えば5035, 48
-nimi

回答:



4

Java 8ラムダ、247 239 233 225 224 219 198 161文字

それは300文字以下で可能だと思ったのは...あなたが知っている... Java!

そして、200文字未満でも可能です!

m->{int n=1,u,f,F[],g,G=g=1<<31;for(;++n<=m;){u=n;F=new int[m+1];for(f=1;++f<=u;)u/=u%f<1?(F[f]=f--):1;f=0;for(int p:F)f+=p*p;g=n-f>g?(G=n)-f:g;}return G+","+g;}

このインポートの使用が合法かどうかはわかりませんが、大丈夫だと思います。以下は、クラスに追加されていないラムダです。

public class Q80507 {
    static String greatestAfterReduction(int maxNumber) {
        int number = 1, upper, factor, primeFactors[], greatestResult, greatestNumber = greatestResult = 1 << 31; // <-- Integer.MIN_VALUE;
        for (;++number <= maxNumber;) {
            // get unique primefactors
            upper = number;
            primeFactors = new int[maxNumber + 1];
            for (factor = 1; ++factor <= upper;)
                upper /= upper % factor < 1 ? (primeFactors[factor] = factor--) : 1;

            factor = 0;
            for (int prime : primeFactors)
                factor += prime * prime;

            greatestResult = number - factor > greatestResult ? (greatestNumber = number) - factor : greatestResult;
        }
        return greatestNumber + "," + greatestResult;
    }
}

素因数発見は、この答えに基づいています。コードは各値を1回しか保存しないため、セットの機能を使用します。したがって、後で重複を追加する必要はありません。残りのコードは、質問に続いて非常に単純です。

更新

出力から改行を削除しました。

Integer.MIN_VALUEを1 << 31にゴルフしてくれた@ogregoireに感謝します!

コードをもう一度調べた後、物事をゴルフできる場所をさらに見つけました。

== 0から<1のトリックを@Blueに感謝します!

残りの空白を削除しました。また、分離には1つの文字だけが必要なので、1つの文字を無駄にする必要はありません。

値を出力して宣言をまとめる代わりに値を返すことができることを指摘してくれた@ogregoireに再び感謝します!これは大幅に節約できました!

もう1つの文字を保存する場合、2番目の代わりに3要素を使用できることがわかりました。

@AstronDanに、インポートを保存する配列の素晴らしい使用に感謝します。それはまた、もし三者に最初の場合を短縮する可能性を与えました。


1
Integer.MIN_VALUEとして短縮できます1<<31
オリビエグレゴワール

1
代わりにif(u%f <1)で1バイトを節約します
ブルー

1
int同じ場所ですべてのを宣言して、int何度も繰り返さないようにし、可能であればそこに値を割り当てます。
オリビエグレゴワール

1
また、それを取り除き、System.out.println(...)印刷する代わりに値を返します。OPが述べているように、標準のI / Oメソッドが使用されています。
オリヴィエグレゴワール

1
C#で使用した配列トリックを使用して、ハッシュセットをint配列に変換することもできます。これにより、インポートをドロップして多くのバイトを節約できます。
AstroDan

3

実際には、21バイト

u2x;`;y;*@-`M;M;)@í@E

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

説明:

u2x;`;y;*@-`M;M;)@í@E
u2x;                   push two copies of range(2, n+1) ([2, n])
    `      `M          map:
     ;                   duplicate
      y;                 push two copies of prime divisors
        *                dot product of prime divisors lists (equivalent to sum of squares)
         @-              subtract from n
             ;M;)      duplicate, two copies of max, move one copy to bottom of stack
                 @í    get index of max element
                   @E  get corresponding element from range

この言語にリンクできますか?
チャールズ

1
@NotthatCharlesオンライン通訳で言語の名前をクリックできます。
デニス

[OK]を私はGoogleで検索Actually Programming Languageしても、Googleの結果の第五ページを閲覧した後には何も見つかりませんでした。この言語はなんですか?
Tejas Kale

2
@Tejasあなたはそのソースにあなたを送る言語の名前をクリックすることができます:github.com/Mego/Seriously
Amndeep7

3

MATL、18バイト

:"@tYfu2^s-]v2#X>w

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

最後のケースはオンラインコンパイラには時間がかかりすぎますが、正しい結果が生成されます(Matlabで実行しているコンピューターでは約11秒かかります)。

ここに画像の説明を入力してください

説明

説明された手順の簡単な適用。

:         % Implicit input n. Range [1 2 ... n]
"         % For each
  @       %   Push that number
  tYfu    %   Duplicate. Prime factors. Unique values
  2^s-    %   Square. Sum of array values. Subtract
]         % End for each
v         % Concatenate stack contents into vertical vector
2#X>      % Max and arg max
w         % Swap. Implicit display         

3

C#、194バイト

私の最初のコードゴルフ:)。冗長性にもかかわらず、私は自分の好きな言語を使用しました。これを@FroznのJavaのC#関数ポートとして開始しましたが、最適化によりコードをさらに縮小するいくつかの方法を見つけました。

string R(int a){int u,f,g,N=g=1<<31;for(int n=1;++n<=a;){u=n;int[]P=new int[a+1];for(f=1;++f<=u;){if(u%f<1){u/=f;P[f]=f--;}}f=0;foreach(var p in P){f+=p*p;}if(n-f>g){g=(N=n)-f;}}return N+","+g;}

これは、配列を使用して素因数を格納します。因子によって索引付けされているため、繰り返される因子を因子のコピーで置き換えます。これにより、関数はインポートされなくなります。これにはシステムも必要ありません。


これは本当に素晴らしいトリックです!私のバージョンで使用してみます
-Frozn

3

Bash + GNUユーティリティ、74

seq 2 $1|factor|sed -r 's/:?( \w+)\1*/-\1*\1/g'|bc|nl -v2|sort -nrk2|sed q
  • seq 2からnまでのすべての整数を生成します
  • factor番号の後にコロンが続き、次に重複を含むすべての素因数のスペース区切りリストが得られます。たとえば、12の結果は12: 2 2 3
  • sedコロンと重複因子を削除し、必要な算術式を生成します。例:12:12- 2* 2- 3* 3
  • bc これを評価する
  • nl プレフィックスn(2から始まる)
  • sort 降順の2番目の列の数値
  • seq 最初の行を出力して終了します。

イデオン。


2

Brachylog、48バイト

:2:{eI$pd:{:2^.}a+:I--:I.}fF$\hor:0m:Ir.r~m[F:J]

説明

Main predicate:

:2:{}fF                     Unify F with the list of all binding for which predicate 1 is
                            true, given [Input, 2] as input.
       $\hor:0m             Retrieve the max of F by diagonalizing it, taking the
                            first row, sorting that row and reversing the sorted row.
               :Ir.         Unify the Output with [I, Max],
                   r~m[F:J] [I, Max] is in F at index J (the index is unimportant)


Predicate 1:

eI                          I is an integer in the range given in Input
  $pd                       Get the list of prime factors of I, with no duplicates
     :{:2^.}a               Apply squaring to each element of that list
             +              Sum the list
              :I-           Subtract I from the sum
                 -          Multiply by -1 (let's call it Result)
                  :I.       Unify the Output with [Result, I]

2

ゼリー、13 バイト

ÆfQ²S_@,µ€ḊṀṚ

オンラインでお試しください!または、すべてのテストケースを確認します

使い方

ÆfQ²S_@,µ€ḊṀṚ  Main link. Argument: n

        µ      Combine the chain to the left into a link.
         €     Apply it to each k in [1, ..., n].
Æf               Yield k's prime factors as a list.
  Q              Unique; deduplicate the prime factors.
   ²             Square each unique prime factor.
    S            Compute their sum.
     _@          Subtract the result from k.
       ,         Pair with k, yielding [result(k), k].
          Ḋ    Dequeue; discard the first pair which corresponds to k = 1.
           Ṁ   Get the maximum (lexicographical order).
            Ṛ  Reverse the pair.

2

05AB1E、19 17 16バイト

コード:

L©f€n€O®-®)ø¦{¤R

説明:

L                    # make a list of 1..input [1,2,3,4,5,6]
 ©                   # save the list for reuse
  f                  # get primefactors of numbers in list [[],[2],[3],[2],[5],[2,3]]
   €n                # square each factor [[],[4],[9],[4],[25],[4,9]]
     €O              # sum the factors [0,4,9,4,25,13]
       ®-            # subtract from saved list [1,-2,-6,0,-20,-7]
         ®)ø         # zip with saved list [[1,1],[-2,2],[-6,3],[0,4],[-20,5],[-7,6]]
            ¦        # drop the first item (n=1) [[-2,2],[-6,3],[0,4],[-20,5],[-7,6]]
             {       # sort [[-20,5],[-7,6],[-6,3],[-2,2],[0,4]]
              ¤      # get last item [0,4]
               R     # reverse [4,0]

オンラインで試す


2

ジュリア、56バイト

!n=maximum(k->(k-sumabs2(k|>factor|>keys),k),2:n)[[2,1]]

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

使い方

入力所与nは、それぞれ整数のためのKように2≤K≤N 、我々は、タプル生成(F(K)、K) F(k)が差であるK及びその素因数の二乗の和を。

f(k)自体はで計算されますk-sumabs2(k|>factor|>keys)。これは、kを素数キーと指数値のDictに因数分解し、すべてのキー(素数ファクタ)を抽出し、その平方和を取り、kから結果の整数を減算しますます。

最後に、生成されたタプルの辞書編集上の最大値を取得し、インデックス2および1でアクセスすることで逆にします。


1

Clojure、215バイト

(fn j[x](apply max-key second(map(fn[w][w(- w(let[y(reduce +(map #(* % %)(set(flatten((fn f[q](let[c(filter(fn[r](=(mod q r)0))(range 2 q))](if(empty? c)q(map f c))))w)))))](if(= y 0)(* w w)y)))])(range 2(inc x)))))

規則に従ってください。各数の素因数を計算し、それらを二乗して合計します。その後、2つの要素(初期数とその結果)のベクトルのリストを生成し、2番目の要素の最大値を持つ要素を見つけます。

ここでオンラインで見ることができます:https : //ideone.com/1J9i0y


1

R 109バイト

y=sapply(x<-2:scan(),FUN=function(x)x-sum(unique(as.numeric(gmp::factorize(x))^2)));c(x[which.max(y)],max(y))

パッケージをだまして使用しましたgmp




1

PowerShell v2 +、124 120 117バイト

2..$args[0]|%{$y=$z=$_;2..$_|%{$y-=$_*$_*!($z%$_)*('1'*$_-match'^(?!(..+)\1+$)..')};if($y-gt$o){$o=$y;$p=$_}}
"$p $o"

最初の行は値を計算し、2行目は出力のみです。

まず2、コマンドライン引数までの範囲を作成し、$args[0]そのループを作成し|%{...}ます。各ループでは、現在の値に等しいヘルパー変数をで設定し$y=$z=$_ます。次に2、現在の番号までのすべての番号をループします。各内部ループでは、その数が除数!($z%$_)であるかどうか、また ('1'*$_-match'^(?!(..+)\1+$)..')、および素数である、両方である場合は、平方を減算$yします(チェックはブール乗算を使用して行われます)。

すべての素因数を調べて二乗を減算し、残りの数がこれまで$y-gt$oに見てきた最大のものである場合、出力変数を設定します$o=$y;$p=$_。範囲全体をループした後、単にスペースを空けて出力します。


1

Haskell、91バイト

f m=reverse$maximum[[n-sum[p^2|p<-[2..n],mod n p<1,mod(product[1..p-1]^2)p>0],n]|n<-[2..m]]

使用例:f 50-> [48,35]

素因数関数はimport Data.Numbers.Primes、バイト数が多すぎる場合にのみ使用できるため、@ Lynnの素数チェッカーを使用しています。残りは単純です:入力mループnを介し[2..m]て、内部ループpを介して[2..n]p素数、除算n、二乗、合計のすべてを保持します。


1

パイソン2、108の 105 100バイト

f=lambda n,m=2,p=1:m>n or-~f(n,m+1,p*m*m)-(n%m<p%m)*m*m
r=max(range(2,input()+1),key=f)
print r,f(r)

Ideoneでテストします。


1

JavaScript(ES6)、111 105バイト

f=n=>{r=n<2?[]:f(n-1);for(s=[],j=n,i=2;j>1;k%i?i++:j/s[i]=i);s.map(i=>j-=i*i,j=n);return j<r[1]?r:[n,j]}

なぜ以前にこれを再帰的に行うことを考えなかったのかはわかりません。


1

J、44バイト

[:((],.~2+I.@e.)>./)@:}.1(-[:+/*:@~.@q:)@+i.

簡単なアプローチ。また、nその結果のすべての値を最大値で返します。

使用法

   f =: [:((],.~2+I.@e.)>./)@:}.1(-[:+/*:@~.@q:)@+i.
   f 3
2 _2
   f 10
8 4
   f 50
48 35
   f 1000
1000 971
   f 9999
9984 9802
   f 950
900 862
945 862
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.