10進数表現の期間


16

単一の正の整数nを取り、1 / nの 10進表現の期間を返す関数を作成します。

テストケース:

1 -> 1               # 1/1 = 1.0000...... = 1._0
2 -> 1               # 1/2 = 0.5000...... = 0.5_0
3 -> 1               # 1/3 = 0.3333...... = 0._3
7 -> 6               # 1/7 = 0.14285714.. = 0._142857
13 -> 6
14 -> 6
123 -> 5
345 -> 22
654 -> 108
12345 -> 822
67890 -> 120

これはです。ピリオドを直接返すビルトインまたはライブラリは許可されていません。少なくとも100000までの数字は、妥当な時間内(最大で数分)に機能するはずです。


質問は、「少なくとも100000までの数字は妥当な時間内に機能するはずです」と述べていますが、プログラムはこれより大きい数字に対して正しい答えを与える必要がありますか?または、最大100000のみ正確なアルゴリズムを使用することは許容されますか?
FireFly 14年

1
@FireFlyアルゴリズムは正しい答えを提供する必要があります。
ハワード14年

2
1が1を返すのはなぜですか?私は0だと思いますか?
ティムテック14年

@Timtech1.00000000000000000000000000000000000
たけた

@Cruncherああ、ありがとうございます。
ティムテック14年

回答:


11

APL、19文字/バイト*

{(↑⍳⍨1∘↓)⌽⍵|10x*⍳⍵}

Nars2000。前のバージョンはいくつかの数字で間違っていました、これは正しいはずです。50までのすべての数値で手動でチェックしました。

繰り返しますが、Ben Reichは、10^i (mod x)

分解図

{                     ⍳⍵}   generate all naturals up to the argument ⍵
                 10x*       raise 10 to each of them, with unlimited precision
              ⍵|            compute the respective remainders mod ⍵
            ⌽               reverse the list
 (  ⍳⍨    )                 (fork) find the position of the first occurrence
  ↑                         of the fist element of the list
       1∘↓                  in the remainder of the list

      {(↑⍳⍨1∘↓)⌽⍵|10x*⍳⍵}¨1 2 3 7 13 14 123 345 654 12345 67890
1 1 1 6 6 6 5 22 108 822 120

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
*:APLは、上位128のバイト値にAPLシンボルをマッピングし、独自の(レガシー)シングルバイト文字セットに書き込むことができます。したがって、スコアリングの目的のために、ASCII文字とAPLシンボルのみを使用する N文字のプログラムは、Nバイト長と見なすことができます。


たとえばinputに対して正しい答えが得られません20。確認してもらえますか?
ハワード14

あなたが投稿した例に従いました。あなたの例では、1/2 = 0.5-> 1なので、当然1/20 = 0.05-> 2です。
トビア14

1/20 = 0.05_0_であるため、正解は1になります。
ハワード14

そうですか。少し教えてください、答えを修正します。
トビア14

4は、間違った答えを与えるようです10 != 100 (mod 4)
ピーターテイラー14

7

GolfScript(42 27)

{:x)1\[{.10*x%}*]-1%(?)}:P;

ベンチマーク時間:5秒。ベンチマークコード:

'"The time is #{Time.now#1
}"'~ puts
[1 2 3 7 13 14 123 345 654 12345 67890 99991]{[P]p}%
'"The time is #{Time.now#2
}"'~ puts

ベンライヒの期間を見ることのコアアイデアの功績10^i (mod x)

説明

周期pは、十分に大きいすべてに対して、最小の正の整数として定義されiますfrac(10^i * 1/x) = frac(10^(i+p) * 1/x)。それを少し単純化することができfrac(10^i / x) = frac(10^(i+p) / x)ます。さて、frac(a / x) = frac(b / x)IFF a == b (mod x)、我々はそのように、すべて十分に大きいため最小の正の整数を探しているのでi10^i == 10^(i+p) (mod x)

とし10^i == 10^(i+p) (mod x)ます。その後10^(i+1) == 10 * 10^i == 10 * 10^(i+p) == 10^(i+p+1) (mod x); したがって、繰り返しを取得すると、壊れないサイクルになります。

x明確な値のみがある(mod x)ので、ハトの原理によって、私たちはの最初のx + 1値で繰り返しを得なければなりません10^i (mod x)

したがって、上記のコードx + 210^i (mod x)*の値を計算します。次に、最後のものは繰り返しであることが保証されており、リストを逆にして検索することで、最新の発生を見つけることができます。さらに、1回の検索のみを行うため、これは擬似線形時間です。

*余分なものは特別な場合を処理するx = 1ことです、私が減らさない10^0 (mod x)ので、私は0inを探しているので[1]


驚くばかり!より良い解決策から答えを削除しました!-
ベン・ライヒ

7

Golfscript-26バイト

{:i.)+.,{;10*i%.}%i>|,}:f;

編集:110進表現の長さではなく、10進が終了した場合に出力するように更新されました。

かなり効率的なバージョン。値67890は約10秒で実行され、99991は約20秒で実行されます。反復される範囲が2倍になり、前半は無視されるため、以前よりも少し遅くなります(ほぼ半分の速度)。

代替、26バイト

{:i.)+.n*{*i%.}%i>)^^,}:f;

これはstringを反復処理することで機能します。"\n"*(2*i+1)ここiで、値は関数に渡されます。毎回ブロックに渡される値は、の序数値であり"\n"10です。

これ)^^は少しの回避策です。文字列から文字をunconsすると、上記のように、結果は削除された文字の序数値になります。ただし、その値を再び追加すると、文字ではなくその数値の文字列表現が追加されます-かなり非対称的な動作であり、私の意見では設計上の欠陥です。実際にそれを実行したい場合、最初に文字列化するのにかかるコストは1バイトだけです。

最終値の余分なコピーが既にスタックにあるため、最終値を再度削除)し、文字列でxorし、次にxorし、最初のxorで追加または削除された文字が復元されるようにします。int op string文字列表現で)^^はなく文字として扱われた場合、に置き換えることができます|

文字列(Golfscriptではintの配列として格納されます)が256の modの各文字の値を表示しますが、各文字の値自体がこの範囲外になる可能性があることに注意してください。一意性(集合演算を介して)または包含性(を介して)をテストする?場合、表示値ではなく実際の値が比較されます。

現在のGolfscriptインタープリターのパッチファイル:

61c61
<       to_gs
---
>       Gstring.new([self])

上記意志のみの動作に影響を与えるstring op int(およびその逆)opの一つです
+-|&^。の動作を含め、他のすべては影響を受けませんGint`

次の24バイトソリューションが有効になります。

{:i.)+.n*{*i%.}%i>|,}:f;

そして、これは他の多くの本当にい回避策も修正します。


Python-48バイト

f=lambda n:len(set(10**-~i%n for i in range(n)))

最も効率的なソリューションではありませんが、100000未満の値には妥当です。

FWIW、コア要素は、10進数の循環数生成するための私のソリューションと同じです。

同じコードのより効率的なバージョン(70バイト):

 def f(n):
  a=[];i=10%n
  while i not in a:a+=i,;i=i*10%n
  return len(a)

99991は1秒未満かかります。


@PeterTaylorはor、空の文字列に配列を追加します。セットワイズ操作であるため、すべての重複は事前に削除されます。
プリモ14年

しかし、空の文字列はどこから来たのでしょうか?関数が自己完結型である場合、余分なバイトを費やして作成する必要があると思います.|
ピーターテイラー14年

1
@PeterTaylorが修正されました
プリモ14年

1
の動作を変更するstring int +と、多くのプログラムが破損します。他のopがそのタイプペアでどれくらいの頻度で使用されるかはわかりません。
ピーターテイラー14年

@PeterTaylor同意します。しかし、検討します。charへの変換int型を:[]+''+''+。intを文字列として文字列に追加します:[]++vs +。文字列表現としてintを文字列に追加します:+vs `+。現在の実装でint''+は、と同義ですint`。これは、配列を強制し、ascii charが必要な場合は文字列を強制しなければならないという冗長性を考慮すると無駄が多いようです。
プリモ14年

3

GolfScript、48 47 46

@PeterTaylorに2つの文字を削除してくれてありがとう。

{2{1$1$%!{.@\/\d}*}:d~;5d;9{2$%}{10*9+}/+,}:f;

私はJを使用してみましたが、それはあらゆる種類の奇妙な結果を与え続けました。

オンラインでテストする

これは基本的に数から2と5を除算し(2と5は10の素因数であり、それらの逆数は終了し、アルゴリズムを詰め込みます)、最小の整数nは結果の数が10 ^ n-1を除算するようになります期間。


3
どちらが関数の最初の呼び出しであるかがわかっている場合は、そこで定義をインライン化できます。すなわち、{...}:d;...dあなたの代わりに1文字を保存します...{...}:d~
ピーターテイラー14年

@PeterTaylorありがとう、それを考えていなかった
ボラティリティ14年

1
fスタックに残らないことについてBenにコメントしたところ、あなたもそれをやっていることに気づきました。;他の言語との公正な比較のために、実際に関数をポップするためにa を追加する必要があります。
ピーターテイラー14年

2
別のマイクロ最適化:int array ,)\;はに短縮できますint array +,
ピーターテイラー14年

2

Perl、52文字

sub f{($p,%r)=1;1until$r{$p=$p*10%$_[0]}++;~~keys%r}

これは、直接的なアプローチの単純な実装です。(幸いなことに、直接的なアプローチは非常に効率的です。モジュロ算術のおかげで、数学は入力値の10倍以上の数を扱う必要はありません。)

チャレンジが関数を指定したので、私は変数を(再)初期化することを余儀なくされました。これは、完全なプログラムのために気にしないことです。同様に、~~関数がスカラーコンテキストで呼び出されることが確実である場合、最終ステートメントのinは不要です。


20間違った結果が生じる入力で試してください。
ハワード14

2

Clojure、 102、117、115、106

書式なし:

(defn r([n](r{}(iterate #(mod(* % 10)n)10)0))([a[f & s]i](if(a f)(- i(a f))(recur(assoc a f i)s(inc i)))))

フォーマット済み:

(defn r
  ([n] (r {} (iterate #(mod (* % 10) n) 10) 0))
  ([a [f & s] i]
    (if (a f)
      (- i (a f))
      (recur
        (assoc a f i)
        s
        (inc i)))))

実行時間は期間に比例します。サンプル値については、コンピューター上でほぼ瞬時に。

基本的に、これは長い除算の各ステップの後に減算の結果を計算します。いずれかの時点で、その数がその前に計算された数と同じである場合、サイクルが検出されます。


コードはinputで中断します20。確認してもらえますか?
ハワード14

あなたは正しい、上記の解決策は不完全です。修正できるかどうか確認します。
RedDeckWins 14

20の予想される出力は何ですか?
RedDeckWins 14

正解は1になります
ハワード

行くには良いことがあり、最初のアルゴリズムは、例えば、12と20のために、入力の多くに失敗する
RedDeckWins

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