すべての有理数のリストを出力します


13

数学のすべてのうち、常識を超えるいくつかの定理が常にあります。これらの1つは、さまざまなサイズの無限大があるという事実です。別の興味深い事実は、サイズが異なると思われる多くの無限大が実際には同じサイズであるという考えです。有理数と同様に、整数と同数の偶数があります。

この質問の一般的な概念は、無限という奇妙な現実に立ち向かうことです。このチャレンジでは、プログラムは以下を行うリストを出力します。

  • 特定の時点で、常に整数のエントリがあります
  • 最終的に、リスト全体に特定の(ゼロ以外の)有理数を正確に1回(十分に長く実行するために残した場合)
  • 制限のない数の空のスロットが含まれている(リスト上のエントリが不必要に0に設定されている)
  • 空きスロットの割合が100%の制限に近づいている
  • すべての正の整数Nに対して、N個の連続した空のスロットを持つ無限の場所があります

チャレンジ

あなたの課題は、次のルールを備えた特別なリストを出力する、可能な限り短いプログラムを書くことです。

  1. インデックスが平方数ではないすべてのエントリはゼロに設定する必要があります。したがって、最初のエントリはゼロ以外、2番目と3番目はゼロ、4番目はゼロ以外などになります。
  2. すべての有理数は、単純化された不適切な分数の形式(4/5や144/13など)になります。例外はゼロです0。これは単にです。
  3. プログラムが十分に長く、十分なメモリで実行される場合、最終的にすべての(正および負の)有理数がリストに表示されます。特定の有理数の場合、必要な時間は任意の長さですが、常に有限の時間です。
  4. 無限の時間実行した場合、ゼロ以外の有理数が2回現れることはありません。

ルール3では、さまざまな法的出力が無限に存在するため、ある程度のバリエーションが認められています。

出力は行のストリームになります。各行5: 2/3は、最初の番号がエントリ番号であり、その後に有理数が続く一般的な形式になります。1: 0常に出力の最初の行になることに注意してください。

出力のスニペットの例:

1: 1/1
2: 0
3: 0
4: 2/1
5: 0
6: 0
7: 0
8: 0
9: -2/1
10: 0
etc...

規則、規制、および注記

これはコードゴルフです。標準コードのゴルフ規則が適用されます。また、出力で許可されるバリエーションのため、少なくともリストにすべての可能な有理数が1回だけ含まれていると信じる理由と、解が正しいことを示す必要があります。

編集:素数は挑戦から気をそらしたので、私はそれを二乗数に変更しています。これは同じ目的を達成し、ソリューションを短縮します。


1
ルール1のポイントは何ですか?素数性をテストし、合理性を列挙するために、人々に2つの別々のプログラムを相互にゴルフさせたいですか?
ピーターテイラー

整数の非常に小さな部分が有理数の完全なセットと同じカーディナリティを保持する方法を示し、空のスロットの割合が100%に近づく(しかし決して到達しない)こともできます。
PhiNotPi

プログラムも一定量のメモリで実行する必要があると仮定しています。つまり、マシンが常により多くのメモリを割り当てることができるとは仮定できませんか?また、範囲が有限であることを知っているときに、リストインデックスにC intを使用することはルールに反しますか?(ただし、厳密な制限は実装によって異なります。)何らかの形式のbignumが必要ですか?
ブレッドボックス

1
@PhiNotPi、それを行うはるかに簡単な方法があり、それは質問のより興味深い部分からの注意散漫です。
ピーターテイラー

1
1: 0常に出力の最初の行になることに注意してください。–これはあなたの例と矛盾し、私にとっても意味がありません。
Wrzlprmft

回答:


6

Haskell、184文字

main=putStr.unlines$zip[1..](s>>=g)>>=h
s=(1,1):(s>>=f)
f(a,b)=[(a,a+b),(a+b,b)]
g x@(a,b)=[x,(-a,b)]
h(i,(a,b))=(i^2)%(u a++'/':u b):map(%"0")[i^2+1..i*(i+2)]
i%s=u i++": "++s
u=show

これはCalkin-Wilf Treeの幅優先走査を行い、すべての正の有理数を簡約形式で一度だけ生成します。次に、正と負を交互に切り替えて、すべての非ゼロの有理数をカバーし、正方形のエントリ間にゼロを埋め込みます。

出力(簡潔にするためにゼロ行を除く):

1: 1/1
4: -1/1
9: 1/2
16: -1/2
25: 2/1
36: -2/1
49: 1/3
64: -1/3
81: 3/2
100: -3/2
...

5

セージ、103 113 128

賢者は、簡単に論理式をリストできます!プログラムの要件に合うようにフォーマットすると、いつものように、すべてが台無しになります。

for i,q in enumerate(QQ):
 for j in[(i-1)^2+1..i*i]:print'%d:'%j,[0,'%d/%d'%(q.numer(),q.denom())][j==i*i]

セージはQQ高さに従って列挙します。GCD削減後の分子と分母の最大絶対値です。


次のように、を削除して1回だけx.next()使用するとprint、スコアが124になりますx=enumerate(QQ) for i,q in x: for j in[(i-1)^2+1..i*i]: print'%d: '%j,'%d/%d'%(q.numer(),q.denom())if j.is_square()else 0。これはコメントに適切に表示されませんが、私が言っていることはわかると思います。
解像度

ところで、最初の4つの肯定的な要素の後、セージの列挙は他の答えと同じではないことに気付きました。Calkin-Wilf式は、有理数の分母が次の有理数の分子であるシーケンスを与えます。例(...、1 / 3、3 / 2、2 / 3、...)、Sageの(...、1 / 3、3 / 1、2 / 3、...)と比較して。計算方法を確認するために、Sageの列挙に関するドキュメントを見つけることはできません。
解像度

@res、ありがとう!印刷ステートメントをマージしたかったのですが、[x..y]表記の使用を忘れていました。ここで別のSageユーザーに会えてうれしいです!
ブースビー

4

Python、162

f=lambda n:f(n/2)if n%2 else f(n/2)+f(n/2-1)if n else 1
n=i=1
while 1:
 print'%d:'%i,
 if i-n*n:s=0
 else: n+=1;s='%d/%d'%((-1)**n*f(n/2-1),f(n/2))
 print s
 i+=1

これは、Calkin&Wilf による「合理性の再カウント」で与えられた再帰を使用します。


2

Haskell、55バイト

mapM_ print$join$iterate(>>=(\x->[x+1,1/(1+1/x)]))[1%1]

出力

1 % 1
2 % 1
1 % 2
3 % 1
2 % 3
3 % 2
1 % 3
4 % 1
...

1%1はCalkin-Wilfツリーのルートです。反復は、各ノードの両方の子を追加します。結合により、レベルが1つのリストにまとめられます。

適切なインポート、0、およびネガを追加する場合は120文字:

import Data.Ratio
import Control.Monad
main=mapM_ print$0:(join(iterate(>>=(\x->[x+1,1/(1+1/x)]))[1%1])>>=(\x->[-x,x]))

出力

0 % 1
(-1) % 1
1 % 1
(-2) % 1
2 % 1
(-1) % 2
1 % 2
(-3) % 1
3 % 1
(-2) % 3
2 % 3
(-3) % 2
3 % 2
(-1) % 3
1 % 3
(-4) % 1
4 % 1
...

空のスロットを出力していますか?それは味が悪い:(「すべての肯定的な合理性のリスト」で私を持っていた


mapM_ print$fix((1%1:).(>>= \x->[x+1,1/(x+1)]))47文字です。haskellwikiから。haskell.orgの「try it」REPL でインポートなしでそのまま動作します(まあ、mapM_ print部品なしで...)
Will Ness

1

PHP 105バイト

注:正しく実行するには、このコードをiso-8859-1(ansi)として保存する必要があります。デフォルトでutf8へのすべての入力(ideoneなど)をエンコードするオンラインインタープリターは、誤った出力を生成します。

<?for($f=µ;$i++<$j*$j||++$j%2||(--$$f?$$f--:$f^=C);)echo"$i: ",$i==$j*$j?$j%2?$x=++$ö.~Ð.++$µ:"-$x":0,~õ;

Georg Cantorの列挙を使用(+/-値用にわずかに変更)。

上記のコードを実行するのに問題がある場合(おそらく通知メッセージが多すぎるため)、代わりにこれを使用してください(107バイト):

<?for($f=µ;$i++<$j*$j||++$j%2||(--$$f?$$f--:$f^=C);)echo"$i: ",$i==$j*$j?$j%2?$x=++$ö.'/'.++$µ:"-$x":0,'
';

1
このコードで実行時エラーが発生します(「$ö。〜Ð。」など、奇妙な文字が含まれているようです)。
解像度

ideoneで、このソリューションが機能することを実証できますか?エラーも発生します:ideone.com/ru1fo
mellamokb

Ideoneは、生成されるNOTICEメッセージの数が多すぎるとエラーになるようです。〜 '(「/」に等しい)と〜 "(「\ n」に等しい)の両方が、反復ごとにNOTICEを生成します。もちろん、通知がない場合は問題ありません。両方が置き換えられたペースト(107バイト):ideone.com/lFUbl
primo

IdeoneのPHPインタープリターが間違った出力を生成することに気づきました。コードをローカルで実行すると、正しいことがわかります。それとも、あなたは、このようなアナーキーゴルフのパフォーマンスチェッカーとして、有効なPHPのinterpretterでそれをテストすることができます:golf.shinh.org/checker.html(その保存をファイルアップロードに)
プリモ

修正したコードをANSIエンコーディングでファイルに保存すると、Anarchy Golfインタープリターで実行されます。ただし、現在は別の問題があります。これは、リストに「ゼロ以外の有理数が2回現れることはない」という要件に違反しています。実際、コードはすべての有理数を無限に何度もリストしているように見えます。1/2、2/4、3/6、...、などのために例えば1/1、2/2、3/3、...合理的な全て同じであり、同様に
resは

0

オクターブ、168バイト

a=b=p=1;do for i=(p-1)^2+1:p^2-1 printf("%d: 0\n",i)end
printf("%d: %d/%d\n",p^2,a,b)
a=-a;if a>0do if b==1 b=a+1;a=1;else a++;b--;end until 1==gcd(a,b)end
p++;until 0

解決策はそれほど洗練されたものではなく、有理数の「カーペット」を単純に斜めに走査するだけで、単純化できるすべての小数を破棄します。正の数の後、シーケンスの次a/bの数-a/bが進む前に、常に反対が出力されます。

すべての正の有理数の対角トラバース

すべての正の単純分数が印刷され、それらの反対の符号付き分数が印刷されるため、2つの異なる単純分数が同じ値を持つことは決して不可能なので、ゼロでない有理数はそれぞれ1回だけ印刷されます。

デゴルフド:

a=b=p=1
do
    for i=(p-1)^2+1:p^2-1
        printf("%d: 0\n",i)         # p=2,3,4: 1..3,5..8,10..15
    end
    printf("%d: %d/%d\n", p^2,a,b); # p=2,3,4: 4,9,16
    a=-a;
    if a>0                          # the rule is: after a/b, a>0 output -a/b
        do
            if b==1 b=a+1;a=1; else a++;b--; end
        until 1==gcd(a,b)
    end
    p++;
until 0
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.