素数の階乗の比として有理数を書く


19

注:このチャレンジはサンドボックスに投稿さています。

前書き

この課題は、学部の数学コンテストの問題である2009 Putnam B1に触発されました。問題は次のとおりです。

すべての正の有理数は、素数の階乗の積として書けることを示します(必ずしも別個ではない)。例えば、

$ \ frac {10} 9 = \ frac {2!\ cdot 5!} {3!\ cdot 3!\ cdot 3!}。$

チャレンジ

あなたの挑戦は、入力として正の有理数の分子と分母(または単に有理数自体)を表す、比較的素数の正の整数のペアを取り、素数の2つのリスト(または配列など)を出力することです入力された有理数は、最初のリストの素数の階乗の積と2番目のリストの素数の階乗の積の比に等しくなります。

ノート

  • 最初のリストと2番目のリストの両方に含まれる素数がない場合があります。ただし、素数は、どちらのリストでも何度でも表示できます。
  • 入力はそれぞれ(厳密には)1〜65535の間であると想定できます。ただし、出力する必要がある数値の階乗がこの範囲にあるとは限りません。

入力と出力の例

有効な入力と出力の例を次に示します。

input=>output
10,9 => [2,5],[3,3,3]
2,1 => [2],[]
3,1 => [3],[2]
1,5 => [2,3,2],[5]     (elements of a list may be in any order)
3,2 => [3],[2,2]
6,1 => [3],[]

入力(2,2)、(0,3)、(3,0)、(3,6)および(1,65536)は不正な入力です(つまり、プログラムは特定の方法で動作する必要はありません) )。不正な出力の例を次に示します。

1,2 => [2],[2,2] (2 is in both returned lists)
5,2 => [5],[2,4] (4 is not prime)
2,1 => [2],[1] (1 is not prime either)
3,2 => [3],[2] (3!/2! = 3, not 3/2)

得点

これはなので、バイト単位の最低スコアが勝ちです!


答えを表現する方法が複数ある場合、何らかの最小限の合理的な合理性を与える必要がありますか?例えば10/9= [2*5]/[3*3]= [(2!/1!) * (5!/4!)] / [(3!/2!) * (3!/2!)]= [2! * 5! * 2! * 2!] / [3! * 3! * 1! * 4!]= (2! * 2! * 2! *5!) / (3! * 3! * 4!)
デジタル外傷

@DigitalTraumaいいえ; ただし、4は素数ではないため、2番目は有効ではありません。私は、表現が一意であると信じています(そして、必要に応じて質問に証拠を書くことができます)。
カールシルトクラウト

10/9数値のペアではなく分数として入力を受け入れても大丈夫ですか?109
ミシャラヴロフ

@MishaLavrov確かに。それを反映するように質問を編集します。
カールシルドクラウト

@CarlSchildkrautありがとう-はい、それは役立ちます-私は何かが足りないと思った
デジタル外傷

回答:


5

05AB1E54 53 48 46 40 35 33 32 28バイト

[D¿÷Z#DÓ€gZD<ØŠQ*DˆR!*]¯øεʒĀ

オンラインでお試しください!編集:@ASCIIのみのおかげで2バイト保存されました。保存された1 2 3 4 @Emignaのおかげでバイト。(もう1つ保存するだけで、元のバイトカウントの半分になります!)説明:

[       Begin an infinite loop
D¿÷     Reduce to lowest terms
Z#      Exit the loop if the (largest) value is 1
DÓ€g    Find the index of the largest prime factor of each value
Z       Take the maximum
D<ØŠ    Convert index back to prime and save for later
Q       Convert to an pair of which value had the largest prime factor
*       Convert to an pair with that prime factor and zero
Dˆ      Save the pair in the global array for later
R!*     Multiply the other input value by the factorial of the prime
]       End of infinite loop
¯ø      Collect all the saved primes
εʒĀ     Forget all the saved 0s

「感情的な」スクリプトが大好き¦D
--RedClover



5

Mathematicaの、175の 177 169 154 108バイト

Join@@@Table[x[[1]],{s,{1,-1}},{x,r@#},x[[2]]s]&@*(If[#==1,1,{p,e}=Last@(r=FactorInteger)@#;p^e#0[p!^-e#]]&)

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

使い方

これは、2つの機能の構成です。最初の、ungolfsに

If[# == 1,
  1,
  {p,e} = Last[FactorInteger[#]];
  p^e * #0[p!^-e * #]
]&

は、目的の因数分解を実際に計算するための再帰関数です。具体的には、有理数の入力が与えられたx場合、その階乗が分子と分母にあるべき素数を計算し、それらの素数をすべて乗算した小数を返します。(たとえば、入力時には10/9 = 2!*5!/(3!*3!*3!)を返し10/27 = 2*5/(3*3*3)ます。)

すべてのステップで最大の素因数を扱うことでこれを行います。xの因数分解でp eが発生する場合、p を確認します。eは階乗分解で発生し、xをpで除算して再帰します!e

(以前は、pよりも前の素数を見ることで大きな数を回避するより賢い戦略がありましたが、Mathematicaは65521もの大きな数を簡単に処理できるので、意味がありません。歴史にある古いバージョンははるかに高速:私のコンピューターでは、このバージョンが1.6秒で処理する入力で0.05秒かかりました。)

2番目の関数は、最初の関数の出力を素数のリストに変換します。

Join @@@ 
  Table[x[[1]],
    {s,{1,-1}},
    {x,FactorInteger[#]},
    x[[2]]*s
  ]&

以下のためにs=1(正のパワー)とs=-1(負のパワー)、および用語ごとに{prime,exponent}因数分解ではr@#、我々は素数を繰り返しprime exponent*s何度も。

109 62バイトの非競合バージョン

If[#==1,∇1=1,{p,e}=Last@FactorInteger@#;(∇p)^e#0[p!^-e#]]&

上記と同じですが、リストとして出力する代わりに、階乗の代用として∇演算子(組み込みの意味がないため)を使用して、式として出力します。したがって、の入力は10/9(∇2*∇5)/(∇3)^3を表す出力を与えます(2!*5!)/(3!)^3

関数の2番目の部分をスキップするため、これは短くなります。


+2バイト:割り当て f=First Mathematicaが動揺しないように適切な場所でを行う必要があります。

-8バイト:実際にコードを短くした整数出力のバグを修正しました。

-15バイト: FactorIntegerソートされた出力を返します。これを利用できます。

-46バイト:実際に賢くする必要はありません。


2

Python 2、220 202 195183バイト

g=lambda a,b:a and g(b%a,a)or b;n,d=input();m=c=()
while n+d>2:
 t=n*d;f=p=2
 while t>p:
	if t%p:p+=1;f*=p
	else:t/=p
 if n%p:c+=p,;n*=f
 else:m+=p,;d*=f
 t=g(n,d);n/=t;d/=t
print m,c

オンラインでお試しください!編集:@ Mr.Xcoderのおかげで18 25バイトを保存しました。@JonathanFrechのおかげで12バイト節約されました。



あなたはインデントのタブで複数のスペースを置き換えることができますので、あなたは、Pythonの2で、さらにそれを短縮することができます
ミスターXcoder


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