整数をエンコードする


33

与えられた正の整数n > 2。次のように配列に変換します。

  1. 2空の配列を返すことに等しい場合
  2. そうでない場合、すべてnの素因数の配列を昇順で作成し、各要素を素数の順序でそのインデックスに置き換え、最後に各要素を配列に変換します

たとえば、数値46を配列に変換できます。まず、それをその素因数の配列に変換します。

[2, 23]

数値239th番目の素数なので2、空の配列と23で置き換え[9]ます。配列は次のようになります。

[[], [9]]

の主な要因93および3ですので、

[[], [3, 3]]

両方について同じことを行います3

[[], [[2], [2]]]

そして最後に:

[[], [[[]], [[]]]]

今、それをエンコードするために、それぞれの開いている括弧をで置き換え1、それぞれの閉じている括弧を0で置き換えて1から、すべての終了ゼロを削除し、最後から1をドロップします。これは2進数です。上記の例を使用して:

[ ] [ [ [ ] ] [ [ ] ] ]

| | | | | | | | | | | |
| | | | | | | | | | | |
V V V V V V V V V V V V

1 0 1 1 1 0 0 1 1 0 0 0

ここで、最後の3つのゼロと最後のを単にドロップし1ます。数1011100118510進数になります。これが期待される出力です。メイン配列の配列からバイナリへの変換ブラケットには含まれていないことに注意してください。

入力

nより大きい正の整数2

出力

エンコードされた整数n

ルールとIO形式

  • 標準ルールが適用されます。
  • 入力は文字列または数値にすることができます(ただし、文字列の場合は、基数10でなければなりません)。
  • 出力は文字列または数値にすることができます(ただし、文字列の場合、基数10でなければなりません)。
  • これはで、バイト単位の最短回答が勝ちです!

テストケース

リクエストに応じてより多くのテストケース。

3 ---> 1
4 ---> 2
5 ---> 3
6 ---> 5
7 ---> 6
8 ---> 10
9 ---> 25
10 ---> 11
10000 ---> 179189987
10001 ---> 944359
10002 ---> 183722
10003 ---> 216499
10004 ---> 2863321
10005 ---> 27030299
10006 ---> 93754
10007 ---> 223005
10008 ---> 1402478

サンドボックス


テストケースは2、処理するために提出する必要がないため、削除する必要があります。
ミスターXcoder

4
主要なビルトインを持たない言語をリッピングします。
ミスターXcoder

3
@ポール。「[...]昇順でソートされたすべてのn個の素因数の配列を作成」

1
@Quelklef。私はATPの実装に取り​​組んでおり(楽しみのためだけで、深刻なことは何もありません)、ネストされた配列を使用してすべての数値をなんとかして表現しようとしました。それで、このエンコーディングは私が思いついた最初のアイデアです。

1
@WheatWizard。私は整数という言葉の正確な数学的意味を意味しません。私はそれを残すつもりです。:-)

回答:


12

35 31 30 29 26 25 24 22 20 19 15バイト

@Zgarbのおかげで-7バイト!

Zgarbのおかげで、間接的に余分な4バイトを節約しました

ḋhΣhgφṁȯ`Jḋ2⁰ṗp

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

説明

     φ             -- Define a recursive function which calls itself ⁰ and is applied to an Integer
      ṁ       p    -- map then concatenate over its prime factors
             ṗ     --   return their indices into the primes
            ⁰      --   and then recur, applying ⁰ to that number
       ȯ`Jḋ2       --   then surround it between the list [1,0] (binary 2)
    g              -- group adjacent equal elements
   h               -- drop last element (trailing 0s)
  Σ                -- concatenate
 h                 -- drop the last element
ḋ                  -- interpret as base 2

私が思うに、これは ...型推論中に27バイトのために働く必要がありますが、TIO回
Zgarb

2
気にせず、25バイトで動作します。最後φに、固定小数点ラムダのユースケースです!
-Zgarb

うわー、今までその使用例を本当に理解したことがない
-H.PWiz

複数行のプログラムが実装される前に、非常に早い段階でHuskにフィックスポイントラムダを追加しました。再帰を処理する最良の方法だと思ったのではないでしょうか。ただし、このような特殊なケースで1バイトを保存することは別として、それらはかなりあいまいです。
-Zgarb

`:0:1することができます`Jḋ2
-Zgarb

7

ゼリー 22 20  19 バイト

-1 Erik the Outgolferに感謝(t右側からではなく、両側からのテールゼロœr

ÆfÆC$ÐLŒṘO%3ḟ2Ḋt0ṖḄ

2より大きい整数を取り、0より大きい整数を返すモナドリンク(2は元の仕様に従って0を返します)。

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

どうやって?

これは、バイナリ配列を作成するための通常の操作だけで、与えられた説明をほぼ正確に複製します...

ÆfÆC$ÐLŒṘO%3ḟ2Ḋt0ṖḄ - Link: number n (>=2)
     ÐL             - loop until no more changes occur:
    $               -   last two links as a monad:
Æf                  -     prime factorisation (includes duplicates & vectorises)
  ÆC                -     count primes less than or equal (vectorises)
                    -   ...note for entries of 2 this yields [1]
                    -      then for entries of 1 it yields [], as required
       ŒṘ           - get a Python representation - just like in the OP,
                    -    something like: "[[], [[[]], [[]]]]" (for an input of 46)
         O          - convert to ordinals e.g. [91,91,93,44,32,91,91,91,93,93,44,32,91,91,93,93,93,93]
          %3        - modulo by 3         e.g. [ 1, 1, 0, 2, 2, 1, 1, 1, 0, 0, 2, 2, 1, 1, 0, 0, 0, 0]
            ḟ2      - filter discard twos e.g. [ 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0]
              Ḋ     - dequeue             e.g. [ 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0]
               t0   - strip zeros         e.g. [ 1, 0, 1, 1, 1, 0, 0, 1, 1]
                 Ṗ  - pop                 e.g. [ 1, 0, 1, 1, 1, 0, 0, 1]
                  Ḅ - binary to decimal   e.g. 185

ああ、はい、間違いなくできます。ありがとう。
ジョナサンアラン

6

Pythonの2212 177バイト

lambda n:int(g(n).rstrip("0")[1:-1],2)
g=lambda n:"1%s0"%"".join(map(g,p(n)))
def p(n,i=0,j=1):
 while n>1:
  j+=1;P=q=1;exec"P*=q*q;q+=1;"*~-j;i+=P%q
  while n%j<1:yield i;n/=j

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

プライムビルトインの欠如は、実際にバイトカウントを低下させ、より大きなプライムを使用するTIOではタイムアウトになります。用途XNORさん素数チェック。


Python 2 + gmpy2バイト

lambda n:int(g(n).rstrip("0")[1:-1],2)
g=lambda n:"1%s0"%"".join(map(g,p(n)))
def p(n,i=0,j=1):
 while n>1:
  j+=1;i+=is_prime(j)
  while n%j<1:yield i;n/=j
from gmpy2 import*

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

このバージョンは、より大きなテストケース(10000〜10008)ではタイムアウトしません。


5

Mathematica、125 119バイト

Flatten[#//.{{1}->{1,0},a_/;a>1:>{1,List/@PrimePi[Join@@Table@@@FactorInteger@a],0}}]/.{1,d__,1,0..}:>{d}~FromDigits~2&

少し異なるアプローチを使用します。プライムインデックスを{1, index, 0}に変換し、2をに変換し{1, 0}ます。

Wolfram Sandboxで試してみてください

使用法:

f = Flatten[ ...

f[10008]

1402478


元の答えは10008で機能しますが、これは失敗します
ケリーロウダー

1
@KellyLowder修正!
ジョンファンミン


2

J、74 73 66バイト

3 :'#.(}.~ >:@i.&1)&.|.2+}.;<@(_2,~_1,[:>:[:_1&p:q:) ::<"0@;^:_ y'

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

これは確かに、さらなるゴルフが必要な真の混乱です(明示的な関数定義の削除など)。私がやっているボクシングは、特にバイトカウントを引き起こしているものだと思います。なぜなら、そこで何をしているのか本当にわからないからです(多くの試行錯誤がありました)。また、私が忘れているビルトインがいくつかある確信しています(たとえば、_2,~_1,おそらくビルトインしているように感じます)。

説明(変更なし)

前文

これは簡単な説明にはならないので、しっかり座ってください。皮肉なことに、簡潔な言語は冗長な人とペアになっています。

これをいくつかの機能に分割します

encode  =. 3 : '<@(_2,~_1, [: >: [: _1&p: q:) ::<"0@;^:_ y'
convert =. 3 : '2 + }. ; y'
drop    =. (}.~ >:@i.&1)&.|.
decode  =. #.
  • encode [と]の代わりに_1と_2を使用して整数をエンコードします
  • convert _1と_2のリストを1と0のリストに変換します
  • drop 最後の1と末尾のゼロを削除します
  • decode バイナリリストから数値に変換します

46のサンプルコールを見ていきます。

   decode drop convert encode 46
185

エンコード

ここで説明することがたくさんあります。

3 : '<@(_2,~_1, [: >: [: _1&p: q:) ::< "0@;^:_ y'
                                           ^:_      Do until result converges
                                          ;          Raze (remove all boxing)
                                       "0            For each
                               q:                     Factorize
                         _1&p:                        Get index of prime
                   >:                                 Add 1 (J zero-indexes)
            _1,                                       Prepend -1
        _2,~                                          Append -2
     <                                                Box resulting array
                                   ::                If there is an error
                                     <                Box the element

明示的な関数定義ことに注意してください3 : '[function]'、それは右の引数がのすべてのインスタンス置き換えるとREPLにあったかのように機能を評価しy、私はキャップを(使用することを避けることができること(この手段[:)、atops( @)、およびATS( @:)の費用で数バイト)。

以下は、46の入力での各反復の様子です。

┌─────────┐    ┌──┬─────┬─────────┬──┐    ┌──┬──┬──┬──┬───────┬───────┬──┬──┐
│_1 1 9 _2│ => │_1│_1 _2│_1 2 2 _2│_2│ => │_1│_1│_2│_1│_1 1 _2│_1 1 _2│_2│_2│ =>
└─────────┘    └──┴─────┴─────────┴──┘    └──┴──┴──┴──┴───────┴───────┴──┴──┘

┌──┬──┬──┬──┬──┬─────┬──┬──┬─────┬──┬──┬──┐    
│_1│_1│_2│_1│_1│_1 _2│_2│_1│_1 _2│_2│_2│_2│ => the final iteration is just every
└──┴──┴──┴──┴──┴─────┴──┴──┴─────┴──┴──┴──┘    value in its own box

この関数は、逆::括弧()を使用して、値を「括弧」にネストします(ここで使用される括弧は-1および-2です)。基本的に、因数分解して素数インデックスに変換するたびに、_1が先頭に追加され、_2が追加されます。これらは括弧として機能します。これらの要素に対して関数が呼び出されるとq:、負の数を因数分解しようとするとエラーになるため、そのまま返されます。また、その幸運だq:ではない 1を因数分解しようとしているのエラー、代わりに(必要に応じて)空の配列を返します。

変換する

3 : '2 + }. ; y'
            ;     Raze (remove boxing)
         }.       Behead (remove head)
     2 +          Add 2

変換ははるかに簡単です。すべてのボクシングと最初の要素を削除し、すべてを1と0に変換します(2を追加するだけです)

ドロップ

(}.~ >:@i.&1)&.|.
             &.|.  Reverse, apply the left function, and then undo
 }.~ >:@i.&1        Drop the leading zeroes and first 1
        i.&1         Index of first one
     >:              Add 1
 }.~                 Drop

これにより、リストが逆になり、最初のリストが検索され、その値までのすべての値が削除されてから、リストが再び逆になります。

デコード

デコードは、#.1と0のリストを受け取り、それを2進数に変換する組み込み関数です。


2

網膜244の 227 225バイト

+%(G`
\d+
$*0¶$&$*
+`^00(0+)
0$1¶$0
A`^(00+?)\1+$
^0+
$0;1
+`(1+)¶0+(?=¶)
$0;1$1
+`¶(11+?)(\1)*$
¶$1¶1$#2$*1
1$

m`^11$
[]
m`^1+
[¶$.0$*0¶]
+s`(0+);(1+)(.+¶)\1¶
$1;$2$3$2¶
0+;1+¶

)`1+
$.0
T`[]¶`10_
10+$

1
01
+`10
011
^0+

1

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

これは、質問で示されたアルゴリズムに従う単純なアプローチです。プライムインデックスの生成は指数関数的な複雑さであるため、入力が大きくなるとタイムアウトします

説明:

+%(G`                Repeatedly apply on each line:
\d+                      If the line is a number, convert it to unary 0s and 1s
$*0¶$&$*
+`^00(0+)                Generate all prefixes of the zeros greater than 1
0$1¶$0
A`^(00+?)\1+$            Remove non-prime strings of zeros
^0+                      Index the first zero set (00) as 1
$0;1
+`(1+)¶0+(?=¶)           Index the rest of the zeroes as their prime index
$0;1$1
+`¶(11+?)(\1)*$          Compute prime factors of input value
¶$1¶1$#2$*1
1$                       Remove the 1 factor (not really prime)

m`^11$                   Turn all 2 prime factors to []
[]
m`^1+                    Surround all non-2 prime factors in brackets
[¶$.0$*0¶]
+s`(0+);(1+)(.+¶)\1¶     Convert non-2 prime factors to their index
$1;$2$3$2¶
0+;1+¶                   Remove the list of primes

)`1+                     Return all primes back to decimal ready to be repeated
$.0
T`[]¶`10_            Then convert all [ to 1 and ] to 0, and remove linefeeds
10+$                 Remove the final 1 and trailing zeroes

1                    Convert from binary to unary
01
+`10
011
^0+

1                    Convert from unary to decimal

1

ハスケル162 160 155バイト

sum.zipWith((*).(2^))[0..].tail.snd.span(<1).(r%)
r=zip[1..][x|x<-[2..],all((>0).mod x)[2..x-1]]
_%1=[]
((i,q):p)%n|mod n q<1=r%div n q++0:r%i++[1]|1<3=p%n

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

説明:

r=zip[1..][x|x<-[2..],all((>0).mod x)[2..x-1]] 素数のタプルとそのインデックスの無限リストを定義します: [(1,2),(2,3),(3,5),(4,7),(5,11),(6,13), ...]

関数(%)は、このリストrと数値nを取り、その数値を逆の因子配列表現に変換します。これはr、分裂する素数を見つけるまで段階的に行われますn。次に、この素​​数のインデックスの表現を再帰的に決定し、それを囲み01との表現先頭に追加nそのプライムで割った値を。

の場合n=46、これによりリスト[0,0,0,1,1,0,0,1,1,1,0,1]が生成され、そこから先頭のゼロ(snd.span(<1))と次のゼロ1tail)が削除されます。その後、リストは、2のべき乗のリストを要素ごとに乗算し、結果のリストを合計することにより、10進数に変換されますsum.zipWith((*).(2^))[0..]


0

JavaScript、289バイト

バイトは、コンマの後の改行なしのJavaScriptコード(フォーマットと読みやすさのためにのみ挿入されます)(256バイト)と、Chromeを使用するときに必要なコマンドラインスイッチの追加文字(33バイト)の合計です。

'use strict'
var f=(n,i=2,r=[])=>n>1?n%i?f(n,i+1,r):f(n/i,i,r.concat(i)):r,
c=(p,r=1,i=2)=>i<p?f(i)[1]?c(p,r,i+1):c(p,r+1,i+1):r-1?f(r).map(h):[],
h=a=>c(a),
s=a=>a.reduce((r,e)=>r+s(e),'1')+' ',
o=i=>+('0b'+s(f(i).map(h)).trim().replace(/ /g,'0').slice(1,-1))

より長く、読みやすいバージョン:

'use strict';
const f = (n,i=2,r=[]) => n>1 ? n%i ? f(n,i+1,r) : f(n/i,i,r.concat(i)) : r;
const c = (p,r=1,i=2) => i<p ? f(i)[1] ? c(p,r,i+1) : c(p,r+1,i+1) : r-1 ? f(r).map(h) : [];
const h = i => c(i);
const s = a => a.reduce((r,e) => r+s(e),'1')+' ';
const o = i => +('0b'+s(f(i).map(h)).trim().replace(/ /g,'0').slice(1,-1));

簡単な説明:

f は、純粋に機能的な末尾再帰分解アルゴリズムです。

cr素数pのシーケンス内で素数が発生する場所をカウントし、[](if p=2およびr=1)を返すかr、帰納法によって因数分解してさらに処理します。

h残念ながら、2番目と3番目の引数としてmap提供された関数を呼び出すために必要な小さなヘルパー関数であり、この関数を直接渡す場合に提供されたデフォルト値をオーバーライドします(この落とし穴を取得するのに時間がかかりました;交換numberOfCurrentElementwholeArraychその定義でと、数バイト長くなります)。

s生成された配列を文字列に変換します。blankではなくを使用して、で使用0できるようにtrim()oます。

oi出力を返す入力値で呼び出される関数です。仕様に必要なバイナリ文字列表現を生成し、それを(10進数の)数値に変換します。

編集:chrome --js-flags="--harmony-tailcalls"末尾再帰の最適化を有効にするには、Chromeを起動する必要があります(https://v8project.blogspot.de/2016/04/es6-es7-and-beyond.htmlを参照)。これには、厳格モードの使用も必要です。

次のテストは、一部の値については計算が少し遅いことを示しています(最長は10007コンピューター上で6秒以上です)。興味深いことに、末尾再帰の最適化がなければ、スタックオーバーフローがない場合、計算ははるかに高速です(約5倍)。

for (let i=3; i<=10008; i==10 ? i=10000 : ++i) {
    let time = new Date().getTime();
    let val = o(i);
    time = new Date().getTime() - time;
    document.write(i + ': ' + o(i) + ' (computed in ' + time + ' ms)<br>');
}

0

tinylisp、209バイト

(load library
(d [(q((N)(map(q((P)([(length(filter prime?(1to P))))))(reverse(prime-factors N
(d B(q((L)(c 1(insert-end 0(foldl concat(map B L
(d T(q((N)(if(mod N 2)(/ N 2)(T(/ N 2
(q((N)(T(from-base 2(t(B([ N

最後の行は、指定されたエンコードを計算する名前のない関数です。オンラインでお試しください!

ゴルフ前のバージョン

これは、ゴルフを始める前に持っていたコードです。

(load library)

(def prime-index
 (lambda (P)
  (length (filter prime? (1to P)))))

(def to-list
 (lambda (N)
  (map to-list
   (map prime-index
    (reverse (prime-factors N))))))

(def to-bits
 (lambda (L)
  (cons 1
   (insert-end 0
    (foldl concat
     (map to-bits L))))))

(def trim
 (lambda (N)
  (if (mod N 2)
   (div2 N 2)
   (trim (div2 N 2)))))

(def encode
 (lambda (N)
  (trim
   (from-base 2
    (tail (to-bits (to-list N)))))))

0

05AB1E、18バイト

ΔÒ.Ø>}¸»Ç3%2K0ܨ2β

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

説明:

Δ    }       # loop until a fixed point
 Ò           # replace each number with its prime factorization
  .Ø>        # replace each prime with its 1-based index
¸»           # after the loop: join to a string
  Ç          # get ASCII value of each character
   3%        # modulo 3 (maps '[' to 1, ']' to 0, ' ' to 2, ',' to 2)
     2K      # remove 2s
       0Ü    # trim trailing 0s
         ¨   # remove the last 1
          2β # parse as base 2
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.