Collat​​zパス:Collat​​z予想に沿った前方および後方


8

Collat​​z予想は非常によく知られている予想です。正の整数をとります。偶数の場合は、2で割り、それ以外の場合は、3を掛けて1を加えます。到達する1か、何か他のことが起こるまで繰り返します。推測では、このプロセスは常にに達し1ます。

プロセスを逆にすることもできます。で開始し1、2を掛け、multiply by 3 and add 1数値に分岐するには1 (mod 3)、偶数、つまり1に達したときに、1を引いて3で割ります。

Collat​​zパスは2つを組み合わせて、4つの演算で1つの数値から別の数値に移動しようとします。

たとえば、次の場所に移動するに201

1     *2
2     *2
4     *2
8     *2
16    *2
5     (-1)/3
10    *2
20    *2

1を引いて3で割ることによっても、3そこから得ることができ10ます。

これらのツールを使用すると、ある番号から別の番号にCollat​​zパスをトラバースできます。例えば、からパス20には、3(3による除算、1を引く)、(2分周)です。

つまり、使用可能な操作は次のとおりです。

n * 2       always
n // 2      if n % 2 == 0
n * 3 + 1   if n % 2 == 1
(n-1) // 3  if n % 6 == 4

注:すべてのCollat​​zパスが短いわけではありません。a(7,3)走れる

7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1, 2, 4, 8, 16, 5, 10, 3

しかし、より短いパスは

7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 3

チャレンジ

任意の2つの正の整数間の最短このCollat​​zパスの長さを見つけ、pq

  • 入力は、2^20整数オーバーフローを回避するために、2未満の正の整数です。入力方法はゴルファーの裁量に任されています。整数は同じである場合があり0ます。その場合、Collat​​zパスの長さはです。
  • 出力は、pとの間の最短Collat​​zパスの長さを示す1つの整数である必要がありqます。

テストケース

a(2,1)
1

a(4,1)
1         # 4 -> 1

a(3,1)
6         # 3 -> 10 -> 5 -> 16 -> 8 -> 4 -> 1

a(11,12)
11        # 11 -> 34 -> 17 -> 52 -> 26 -> 13
          # -> 40 -> 20 -> 10 -> 3 -> 6 -> 12

a(15,9)
20        # 46 -> 23 -> 70 -> 35 -> 106 -> 53 -> 160 -> 80 -> 40 -> 13
          # -> 26 -> 52 -> 17 -> 34 -> 11 -> 22 ->  7 -> 14 -> 28 -> 9

この課題を明確にしてくれたorlpに感謝します。

いつものように、問題が不明な場合はお知らせください。幸運と良いゴルフを!


1
私たちのコンピューターは、少なくとも2 ^ 31要素の配列に耐えられません。

@MatthewRohチャレンジはその後編集されました。
Sherlock9

これは、グラフ理論による 経路探索の課題です。そして、私たちは以前にほぼ同じものを持っていると確信しています。
flawr


2
@flawr複製に同意しません。はい、どちらの課題でもグラフ内のパスを見つけたいと思っていますが、グラフは異なり、回答のグラフ構造をエンコードすることがIMOのユニークな部分です。たとえば私の答えを見て、それをあなたの「重複する」質問の答えと比較してください。
orlp

回答:


3

Haskell、170158157146146137135112109108106100 99バイト

a!b=length$fst$break(elem b)$iterate(>>= \n->2*n:cycle[div n 2,n*3+1]!!n:[div(n-1)3|mod n 6==4])[a]

元のバージョンがもっとゴルフに適しているとは思いませんでした。これは、@ nimi @Lynnと@Laikoniの作品でもあります。

1バイトは@ Laikoni、11 14 20 21バイトは@ Lynn、8バイトは@nimiに感謝します。

これにより、訪問番号(で始まるa)のツリーが段階的に展開され、指定された番号に到達したかどうかが各ステップでチェックされますb


1つのスペースを逃しました:iterate s [a] -> iterate s[a]
Laikoni

Sweet〜インライン化sはさらに3バイトを節約します!iterate(nub.concat.map f)[a]また、本当に必要nubですか?
リン、

ゴルフが終わったら教えてください:Dありがとうございます。残念ながら、私はまだモナドを理解するのに苦労しています。
flawr

@nimi繰り返しますが、どうもありがとうございました。これほどゴルフができるとは思っていませんでした。知らなかったbreakspan、本当に役に立った!
flawr

1
で置き換える[div n 2,n*3+1]!!mod n 2と、cycle[div n 2,n*3+1]!!nもう1バイト節約されます:)
Lynn

2

Python 2、110バイト

a=lambda p,q,s={0}:1+a(p,q,s.union(*({p,n*2,[n/2,n*3+1][n%2]}|set([~-n/3]*(n%6==4))for n in s)))if{q}-s else-1

1

Pyth、30バイト

|q*FQ2ls-M.pm.u&n2N?%N2h*3N/N2

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

使い方

2つの入力番号で始まり、2で終わる2つの前方Collat​​zシーケンスの対​​称差の長さを取ります。唯一の例外は、入力が[1, 2]またはの場合で[2, 1]、これは特殊なケースです。

  *FQ                        product of the input
|q   2                       if that equals 2, return 1 (True), else:
            m                  map for d in input:
             .u                  cumulative fixed-point: starting at N=d, iterate N ↦
               &n2N?%N2h*3N/N2     N != 2 and (N*3 + 1 if N % 2 else N/2)
                                 until a duplicate is found, and return the sequence
          .p                   permutations
        -M                     map difference
       s                       concatenate
      l                        length

1

パイソン2、156 179 191 209 181 172の 177 171バイト

Collat​​zパスは、両方のシーケンスに共通であり、元のCollat​​z予想である最初の数として想像a(1,p)およびa(1,q)結合できるためa(1,n)、この関数はpand のCollat​​zシーケンスをq計算し、そこから長さを計算します。これはきれいなゴルフではないので、ゴルフの提案は大歓迎です。唯一の例外は、p or q == 1です。私たちはから直接スキップすることができますので、その後、41定期的にこのCollat​​zシーケンスとは対照的に、我々は結果からステップを減算する必要があります。

編集:多くのバグ修正。

編集:たくさんのバグ修正

f=lambda p:[p]if p<3else f([p//2,p*3+1][p%2])+[p]
def a(p,q):
 i=1;c=f(p);d=f(q)
 if sorted((p,q))==(1,2):return 1
 while c[:i]==d[:i]!=d[:i-1]:i+=1
 return len(c+d)-2*i+2

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


あなたのアプローチは機能しません。たとえばa(3,1)、最短経路は6を返すはずですが、7を返す必要があります3 -> 10 -> 5 -> 16 -> 8 -> 4 -> 1
flawr

@flawr編集。うまくいけば、今はうまくいく
Sherlock9

説明したアルゴリズムが機能すると想定しているのはなぜですか?最短経路は、「往復」する複数回で構成できませんか?
flawr

2
してみましょうf一歩前進、意味bcollat​​zのシーケンスの後方のステップを。パターンは、b->f(それが同一であるように、最短経路であることができないf取り消すれるb最短経路のみパターンからなることができるようにします。いずれの場合も)f->ff->bおよびb->b。つまり、最短パスは常にf->f->...->for b->b->...->bまたはor の形式になりますf->...->f->b->...->b
flawr

3
PS:私はあなたのバイト数が間違った方向に進んでいるような印象を持っています。:D
flawr

0

JavaScript(ES6)、135バイト

f=(x,y,a=[(s=[],s[0]=s[x]=1,x)],z=a.shift())=>z-y?[z*2,z/2,z%2?z*3+1:~-z/3].map(e=>e%1||s[e]?0:s[a.push(e),e]=-~s[z])&&f(x,y,a):~-s[y]

幅優先検索を実行します。x開始番号であり、y先、a試験値の配列、sからチェーンに含め工程数のアレイxz現在の値。場合zy、計算に等しくされていないz*2z/2のいずれかz*3+1、または(z-1)/3、かどうかに応じて、z奇数または偶数であり、その後の画分と以前に見られた値をフィルタリングし、検索リストに追加します。


0

Python 2、80バイト

p=lambda n:n-2and{n}|p([n/2,n*3+1][n%2])or{n}
lambda m,n:m*n==2or len(p(m)^p(n))

2つの入力番号で始まり、2で終わる2つの前方Collat​​zシーケンスの対​​称差の長さをとります。唯一の例外は、入力が1、2または2、1の場合で、これは特殊なケースです。

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