有理数のp進ノルムを計算する


11

有理数のp進ノルムを計算する

入力として3つの整数m,n,p(ここでpは正の素数)を取り|m/n|_p、(完全に縮小された)分数としてp進ノルム(で示される)を出力する関数またはプログラムを作成します。Fermatのマージンは非常に小さいことが知られていますが、かなり不明な点は、コンピューターの画面が非常に小さいことです。したがって、コードをできるだけ短くして、Fermatの画面に収まるようにしてください。

定義

プライム考えるとp、すべての画分は、m/n一意のように(サイン無視して)書き込むことができ(a/b)* p^e、そのようなe整数でp除算どちらaもがb。のp進ノルムm/nですp^-e。小数部が0の場合、特別なケースがあります|0|_p = 0

出力形式は次のとおりである必要がありますx/y(たとえば1/3、整数の場合は両方10または同等10/1に許可され、負の数の場合は先頭にマイナスが必要です(例-1/3

詳細

プログラムはstdin / stdoutを使用するか、有理数または文字列を返す関数のみで構成する必要があります。入力m/nが完全に削減されていないと想定する必要があります。あなたはそれpが素数であると仮定することができます。プログラムは、間の整数を処理できなければならない-2^28まで2^28、10秒以上を取るべきではありません。

組み込みの因数分解と素数チェック機能は許可されていません。また、組み込みの基本会話、およびp進の評価またはノルムを計算する組み込み関数も許可されていません。

例(wikipediaから盗まれた):

x = m/n = 63/550 = 2^-1 * 3^2 * 5^-2 * 7 * 11^-1
|x|_2 = 2
|x|_3 = 1/9
|x|_5 = 25
|x|_7 = 1/7
|x|_11 = 11
|x|_13 = 1

面白いトリビア

(この課題を知っている/読む必要はありませんが、動機として読むのがいいかもしれません。)

(間違った言葉を使ったり、他の何かが間違っている場合、英語でこれについて話すことに慣れていません。)

有理数をフィールドとして考えると、p進ノルムはp進メトリックを誘導しますd_p(a,b) = |a-b|_p。次に、このメトリックに関してこのフィールドを完成させることができます。つまり、すべてのコーシーシーケンスが収束する新しいフィールドを構築できます。これは、あるべきトポロジカルプロパティです。(たとえば、有理数にはありませんが、実数にはあります。)これらのp進数は、ご想像のとおり、数論で多く使用されています。

別の興味深い結果はオストロウスキーの定理です。これは基本的に、有理数の絶対値(以下で定義)は次の3つのいずれかです。

  • 些細なこと: |x|=0 iff x=0, |x|=1 otherwise
  • 標準(実際): |x| = x if x>=0, |x| = -x if x<0
  • p進(定義したとおり)。

絶対値 / メトリックは、距離と見なすものの単なる一般化です。絶対値|.|は次の条件を満たします。

  • |x| >= 0 and |x|=0 if x=0
  • |xy| = |x| |y|
  • |x+y| <= |x|+|y|

絶対値からメトリックを簡単に構築できることに注意してください。|x| := d(0,x)またはd(x,y) := |x-y|、その逆も同様です。つまり、加算 / 減算 / 乗算(整数ドメイン内)できる場合、それらはほぼ同じです。もちろん、この構造を使用せずに、より一般的なセットでメトリックを定義できます。


MathematicaのPadicNorm機能もあると思いますか?:P
アレックスA.

あなたは正しい/と仮定します。(ここで使用されているのはどれですか?)
flawr

興味のあるプロパティのセクションがチャレンジを完了するのに役立つ場合を除き、関心のある関係者の情報にリンクするだけの方がいいと思います。そうしないと、不必要に投稿が混乱します。
アレックスA.

明確にするために、出力は次のよう|x|_11 = 11になりますか?それとも11大丈夫ですか?そして、それはx=0ケースを処理する必要がありますか?
グレンO

@GlenO正しい、x=0大文字と小文字を処理する必要があります。この例では11、同様に出力できます11/1が、印刷する必要はありません|x|_11
flawr

回答:


3

ジュリア、94 80 75バイト

f(m,n,p)=(k=gcd(m,n)
g(m)=m%p>0?g(m÷p)p:1
m!=0?print(g(n÷k),/,g(m÷k)):0)

注:読みやすくするためにセミコロンの代わりに改行を使用すると、どちらの方法でも同じように機能します。

これは非常に簡単である- g(m,n)関数が再帰、残りを(使用して%抽出するために)p^n入力からの因子をm用いて、n=1デフォルトとして、次に乗じたp出力がされるように、再帰の各ステップにp^n。コードはそれをn/gcd(m,n)に適用し、次にに適用してm/gcd(m,n)適切な式を取得します。文字を保存するためにk=gcd(m,n)gcd(m,n)2回の計算を避けるために使用されます。m!=0は、次の場合を処理するテストx=0です。

出力はの形式であるN/11/N、必要に応じて、はNですp^e


1

J、35 34バイト

(,'/'&,)&":/@(%+./)@(]<.^+.|.@])x:

これは、p左引数として素数を取り、m n右引数として配列をとるバイナリ動詞です。常にスラッシュを出力し、if /を返します。次のように使用します。0/1m = 0

  f =: (,'/'&,)&":/@(%+./)@(]<.^+.|.@])x:
  5 f 63 550
25/1

説明

x:拡張精度のターンは、以来、私たちは非常に大きな数を扱うています。残りのコードは次のように機能します。

(,'/'&,)&":/@(%+./)@(]<.^+.|.@])
                        ^         Power: this gives the array p^n p^m
                         +.       Take element-wise GCD with
                           |.@]   the rotated array n m; this gives
                                  the largest powers of p that divide n and m
                      <.          Take element-wise minimum with
                     [            The array m n to handle the m=0 case correctly
              %+./                Divide this array by its GCD to get it to lowest terms
        &":/                      Convert both elements to strings
 ,'/'&,                           Insert the slash '/' between them


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