プライムパワー分解からの除数の合計


11

タスクは、その素因数分解を与えられた数の除数の合計を計算することです。

入力

長さnの 2つの配列(または同等のもの)。1つは素因数を含み、もう1つは対応する指数を含みます。

出力

すべての除数の合計(数値自体を含む)。

数値240には、それぞれの指数が4、1、および1である素因数として2、3、および5があります。予想される出力は744になります。

Input: [2,3,5] [4,1,1]
Output: 744

得点

バイト単位の最短コードが勝ちです!

ソリューションの実行時の複雑さがO(指数の積)ではなくO(指数の合計)である場合、スコアに0.8を掛けることができます。


あった同様の質問ここに掲載が、それは挑戦ではなかったです。この問題はゴルフをするのに十分面白いと思います。

今週の勝者は選ばれます


素因数配列は常に最初になければならず、指数配列は2番目になければなりませんか、または配列が逆に入力されると仮定できますか?
Sp3000

提案されたものと同様の入力形式を想定できます
-Moartem

今それを見つけるが、私はこのまたは類似した何かがprojecteuler.net上だと思うことはできません
flawr

回答:


3

Pyth、13バイト* 0.8 = 10.4

*Fms^LhdhedCQ

デモンストレーション。

この回答は、上記の回答とは多少異なります。算術式を使用する代わりに、数の素数の因子の合計を計算するために、因子は明示的に構築され、合計されます。

たとえば、[prime、exponent]ペア[2, 4]では、をマッピング2 ^ x0, 1, 2, 3, 4、を与えて[1, 2, 4, 8, 16]から、31に合計します。

その後、結果が乗算されて印刷されます。

べき乗が適切に実装されている場合、または中間結果キャッシュがある場合、これはになりますO(sum of exponents)


実装とは無関係に、乗算がO(1)であると仮定しない限り、O(n)時間でaの最初のn乗を計算することは不可能だと思います。
デニス

@Dennisまあ、高次の項が支配的なので、おそらく最高次の乗算のrutimeがあります。これはO(n)、基数が定数であると仮定できる場合です。
isaacg

9

CJam、15バイト* 0.8 = 12

q~.{_@)#(\(/}:*

オンラインでお試しください。入力順序は、最初に指数リスト、次に素数のリスト(@Dennisのおかげで3バイト)です。

各プライム指数ペアのための(p, e)検索

(p^(e+1) - 1)/(p - 1)

次に、これらすべての製品を見つけます。例えば240の場合、これは

(1 + 2 + 4 + 8 + 16)(1 + 3)(1 + 5) = 31 * 4 * 6 = 744

べき乗の実装方法によっては、これはの場合よりも優れている場合がありO(sum of exponents)ます。


6

APL、18 13バイト* 0.8 = 10.4

×/(1-⊣×*)÷1-⊣

これにより、左側に因子の配列を取り、右側に指数をとる二項関数列が作成されます。

×/             ⍝ Vector product of
  (1-⊣×*)      ⍝ each factor^(exponent+1)-1
         ÷1-⊣  ⍝ divided by factor-1

オンラインでお試しください。これは、Sp3000の非常に賢いCJam answerと同じアプローチであることに注意してください。

デニスのおかげで5バイト節約できました!


2

TI-BASIC、17バイト* 0.8 = 13.6

Sp3000の方法も使用しますが、私は独自に見つけました。入力から1つのリストとホーム画面から1つのリストを取得します。

Input E
prod(AnsAns^∟E-1)/prod(Ans-1

prod(を2回使用すると、開き括弧を無料で使用できるため、小さくなります。TI-BASICには空の配列がないため、この答えは空の配列をサポートしません。


2

Haskell、38 * 0.8 = 30.4

product$zipWith(\p e->(p*p^e-1)/(p-1))

使用法:

product$zipWith(\p e->(p*p^e-1)/(p-1)) [2,3,5] [4,1,1]
744.0

無名関数は(p,e)p^e幾何級数和を介して除数和を取ります。製品を結合して取得すると結果が得られるため、これを使用して2つのリストを一緒に圧縮します。

算術式より短いものを見つけることができませんでした

(p*p^e-1)/(p-1)
sum$map(p^)[0..e]

たぶん、を取り除く方法があり(\p e->_)ます。

中置関数の定義は同じ長さ(38)を与えます:

p%e=(p*p^e-1)/(p-1)
product$zipWith(%)

2

C ++、111 80 77バイト* 0.8 = 61.6

int g(int*p,int*e,int n){return n?g(p+1,e+1,n-1)*(pow(*p,*e-1)-1)/(*p-1):1;}

これは(p ^(e + 1)-1)/(p-1)を計算し、すべての因子を再帰的に乗算します。それは1年前に私自身が見つけたものです。

助けてくれてありがとう、c ++スタイルのブール値の使用を完全に忘れてしまいました。


1
n==0簡素化へ!n-またはあなたが成果とだけ使用を逆転できるn
トビースパイツ

2

Matlab、53

function t=f(x,y)
s=1:prod(x.^y);t=s*~mod(s(end),s)';

例:

>> f([2 3 5], [4 1 1])
ans =
   744

0.8のボーナスを追加できるようです
-Moartem

@Moartemありがとう!しかし、私はそれについて確信がありません。数を計算し、sから1までの可能な除数をすべてテストしsます。O(指数の合計)とO(指数の積)との間で、おそらくあるので、それの(少なくとも)O(S)、
ルイス・Mendo

はい、そうです、それはO(指数の積)よりもさらに大きい
Moartem

1

Python 2,156

from itertools import*
from operator import*
i=input()
print sum(reduce(mul,[a**b for a,b in zip(i[0],p)])for p in product(*map(range,[x+1 for x in i[1]])))

入力

[[2,3,5],[4,1,1]]

出力

744

説明

このプログラムは、因子と指数の2つのリストのリストを受け取ります。

i=input() # Receive list of 2 lists: i[0] for factors i[1] for exponents

次に、指数リストの可能なすべての組み合わせのリストを作成します。

[x+1 for x in i[1]] # [4,1,1]->[5,2,2] (to include last element)
map(range,[x+1 for x in i[1]]) # [[0, 1, 2, 3, 4], [0, 1], [0, 1]]
product(*map(range,[x+1 for x in i[1]])) # [(0, 0, 0), (0, 0, 1), ..., (4, 1, 1)]

そして、次の要素で圧縮します:

zip(i[0],p) for p in product(*map(range,[x+1 for x in i[1]])) # [[(2, 0), (3, 0), (5, 0)], ..., [(2, 4), (3, 1), (5, 1)]]

指数のべき乗の係数を計算します。

 [a**b for a,b in zip(i[0],p)]for p in product(*map(range,[x+1 for x in i[1]])) # [[1, 1, 1], ..., [16, 3, 5]]

各リストを乗算します(これによりすべての除数が得られます)。

reduce(mul,[a**b for a,b in zip(i[0],p)])for p in product(*map(range,[x+1 for x in i[1]])) # [1, 5, 3, 15, ..., 240]

最後に、すべてのリストを合計して印刷します。

print sum(reduce(mul,[a**b for a,b in zip(i[0],p)])for p in product(*map(range,[x+1 for x in i[1]]))) # 744

あなたのコードが何をするのか簡単に説明してもらえますか(私はpythonに詳しくないので)、あなたのコードの複雑さを判断できますか?
Moartem

それは賢いアプローチですが、複雑さは指数の積です。
Moartem

@Moartemええ、複雑さの軽減にあまり時間をかけませんでした
-TheCrypt

1

Python 3、134 120 117

入力:コンマで区切られた2つのコンマ区切り配列。

例:

(2,3,7,11),(4,2,3,2)
21439600
from functools import*
a=eval(input())
print(reduce(int.__mul__,(sum(x**j for j in range(y+1))for x,y in zip(*a)),1))

NumPyを使用すると、100バイトに減らすことができます。

import numpy
a=eval(input())
print(numpy.product([sum(x**j for j in range(y+1))for x,y in zip(*a)]))

1
最初の例では、一度使用するためにインポートoperatorする代わりに、mul使用float.__mul__して大量のバイトを保存できます。
ケード

1

ゼリー、非競合

チャレンジはゼリーの作成より前に行われているため、この答えは競合しません。

5バイト(ボーナスなし)

*PÆDS

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

使い方

*PÆDS    Main link. Left input: p (prime factors). Right input: e (exponents).

*        Elevate the prime factors to the corresponding exponents.
 P       Take the product of all powers.
  ÆD     Find all divisors of the product.
    S    Compute the sum of the divisors.

7バイト(ボーナス後5.6バイト)

*‘}’:’{P

使い方

×*’:’{P  Main link. Left input: p (prime factors). Right input: e (exponents).

 *       Elevate the prime factors to the corresponding exponents.
         This yields p ** e.
×        Multiply the prime factors with the corresponding powers.
         This yields p ** (e + 1).
  ’      Decrement the resulting products.
         This yields p ** (e + 1) - 1.
    ’{   Decrement the prime factors.
         This yields p - 1.
   :     Divide the left result by the right one.
         This yields (p ** (e + 1) - 1) / (p - 1).
      P  Take the product of all quotients.

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


1

APL、12バイト* 0.8 = 9.6

×/1++/¨⎕*⍳¨⎕

これにより、キーボードから2つのリストが読み取られます。

      ×/1++/¨⎕*⍳¨⎕
⎕:
      4 1 1
⎕:
      2 3 5
744

説明:

  • :キーボードからリストを読み取る(指数)
  • ⍳¨:リスト内の各番号について、リストを生成します[1..n]
  • ⎕*:キーボードから別のリスト(素数)を読み取り、各素数を対応するリストの各指数に上げます
  • +/¨:各リストの合計
  • 1+x^0各リストに欠落しているものを補うために、各結果に1つずつ追加します
  • ×/:結果の積を取る

1

ラケット(スキーム)、65 * 0.8 = 52バイト

みんなと同じ算術

(λ(x y)(foldl(λ(m n o)(*(/(-(expt m(+ n 1))1)(- m 1))o))1 x y))

説明:

(λ (x y)    ;defines anonymous function with two inputs
    (foldl    ;recursively applies the following function to all elements of the lists given to an argument given (foldl function argument lists lists lists...)
        (λ (m n o) (* (/ (- (expt m (+ n 1)) 1) (- m 1)) o))    ;an anonymous function representing the same arithmetic used in the CJam answer, then multiplying it with our incrementor
        1 x y))    ;the incrementor argument is 1, and the input lists are the ones provided into the original function

0

Python 2、80バイト* 0.8 = 64

これは、入力が次々と入力されることを前提としています。Sp3000のCJamの回答で概説されているのと同じ式に従います。

print(reduce(float.__mul__,[~-(x**-~y)/~-x for x,y in zip(input(),input())],1)) 

これが許可されていない場合は、これをソリューションとして使用し、84バイト* 0.8 = 67.2のスコアを取得します。入力はカンマで区切る必要があります[2,3,5],[4,1,1]

k=input()
print(reduce(float.__mul__,[~-(x**-~y)/~-x for x,y in zip(k[0],k[1])],1))

ちょっと おい!これは、私が取り組んでいるシンボリックの可能な解決策です:Ƥ(П([~-(x**-~y)/~-xϝx,yϊʐ(Ί,Ί)],1))


0

Mathematica、40バイト

Total[Outer@@{*}~Join~(#^0~Range~#2),3]&

除数を扱う組み込み関数を使用せずに、スレッド内の他の数学ソリューションと区別します。

入力は(例を使用) [{2, 3, 5}, {4, 1, 1}]


0

Perl 5、96バイト

明らかにこれは勝てないが、私は楽しみのためにそれを書くことにした。

それはサブルーチンです:

{($b,$e)=@_;$s=1;map$s*=$b->[$_]**$e->[$_],0..@$b-1;$_=1x$s;for$j(1..$s){$i+=$j*/^(.{$j})*$/}$i}

したがって、実際にそれを見てください:

perl -e'print sub{...}->([2,3,5],[4,1,1])'

使い方:

  • ($b,$e)=@_入力arrayref $b(ベース)および$e(指数)を読み取ります。
  • $s=1 製品を初期化します。
  • map$s*=$b->[$_]**$e->[$_],0..@$b-1$s連続する底指数の累乗で乗算します。これ$sが複合数です。
  • $_=1x$s$_1の文字列に等しい、$s長いセット。$i0で初期化されます。
  • for$j(1..$s){$i+=$j*/^(.{$j})*$/}試行は、あらゆる数の$j1との間で$s、破壊する$_として、最大$j文字数は何回でも繰り返します。可能な場合は、を$j分割し$s/^(.{$j})*$/1であり(それ以外の場合は0)、で$i補われ$jます。したがって、の$i同じサイズのパーティション内のパーティションの数に追加し$_ます。以下のようオマールE.ポルが指摘する$i我々が探している番号です。
  • $i最後にを返します$i

0

J、14バイト* 0.8 = 11.2

[:*/(^>:)%&<:[

使用法

   f =: [:*/(^>:)%&<:[
   2 3 5 f 4 1 1
744
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.