いくつかのビットを切り替えて、正方形を取得します


26

整数与えられた場合、を反転して正方数に変換する必要がある最小ビット数を見つける必要があります。最上位ビットより下のビットのみを反転できます。NN>3N

  • 2 2 0N=4すでに平方数()であるため、期待される出力はです。220
  • 11000 1100 1 25 = 5 2 1N=24は、1ビットを反転することにより2進数に変換できます:()。したがって、期待される出力はです。110001100125=521
  • 23 20 18 30 10110 10 0 0 0 16 = 4 2 2N=22単一のビットを反転させ平方数に変えることができない(可能な結果がある、、及び)が、2ビット反転させることによって行うことができる:()。したがって、期待される出力はです。23201830101101000016=422

ルール

  • コードが遅すぎるか、より大きなテストケースに対してエラーをスローする場合は問題ありませんが、少なくとも1分未満でサポートする必要があります。3<N<10000
  • これはです!

テストケース

    Input | Output
----------+--------
        4 | 0
       22 | 2
       24 | 1
       30 | 3
       94 | 4
      831 | 5
      832 | 1
     1055 | 4
     6495 | 6
     9999 | 4
    40063 | 6
   247614 | 7        (smallest N for which the answer is 7)
  1049310 | 7        (clear them all!)
  7361278 | 8        (smallest N for which the answer is 8)
100048606 | 8        (a bigger "8")

または、コピー/貼り付けに適した形式で:

[4,22,24,30,94,831,832,1055,6495,9999,40063,247614,1049310,7361278,100048606]

回答のほぼ半分が100048606TIOで実行されません、それは問題ですか?
魔法のタコ

@MagicOctopusUrnありがとう、ルールを更新して、サポートがオプションであることをより明確にしました。N10000
アーナルド

1
これは、(入力サイズの制限なしで)素敵な最速コードの質問にもなります
-qwr

@qwrはい、おそらく。または、ハードコアにしたい場合:与えられた場合、f N = kなるような最小のNを見つけます。kNf(N)=k
アーナルド

回答:


14

ルビー、74バイト

->n{(1..n).map{|x|a=(n^x*x).to_s 2;a.size>Math.log2(n)?n:a.count(?1)}.min}

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

これは、単にシーケンスを生成する(はるかに十分に超えている)とのXORをN、次にビット数が少ない場合、そのバイナリ表現のいずれか1の数をとりか等しいログ2 N、またはN、さもなければを。次に、反転した最小ビット数を取ります。反転した最上位ビットがlog 2 nより大きい場合、反転したビット数の代わりにnを返すと、これらのケースが最小値として選択されなくなります。n[12,22,,n2]nlog2nnnlog2nn 常にビット数よりも大きくなります。

バイトを保存してくれたPiccoloに感謝します。


あなたは使用してバイトを保存することができます(n^x*x).to_s 2;...代わりに(n^x*x).to_s(2);...
ピッコロ

@Piccolo見逃したなんて信じられない、ありがとう!
ドアノブ

6

ゼリー、12 バイト

²,BẈEðƇ²^B§Ṃ

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

テストスイートをチェックしてください!

モナドリンク。ゴルフができるはずです。しかし、³s を取り除く方法を考えるにはあまりにも愚かです。これは、ダイアディックチェーン\ o /とともに、一般的にフィルタリング/マッピング/ループを正常に使用する最初の回答です。

説明

²、BẈEðƇ²^B§Ṃ–フルプログラム/モナドリンク。引数Nを呼び出します。
     ðƇ–次のダイアディックチェーンでフィルターキープ[1 ... N]:
²、BẈE–現在のアイテムの正方形のビット長はNと同じです。
²–正方形。
 、– Nとペアリング
  B –両方をバイナリに変換します。
   Ẉ–長さを取得します。
    E –そしてそれらが一致するかどうかを確認します。
       ²^ –フィルタリング後、結果を2乗し、NとXORします。
         B –それぞれのバイナリ表現。
          §–それぞれの合計。1の数をバイナリでカウントします。
           Ṃ–最小。

5

、20バイト

▼mΣfo¬→S↑(Mo¤ż≠↔ḋİ□ḋ

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

説明

▼mΣf(¬→)S↑(M(¤ż≠↔ḋ)İ□ḋ) -- example input n=4
        S↑(           ) -- take n from n applied to (..)
                     ḋ  -- | convert to binary: [1,0,0]
                   İ□   -- | squares: [1,4,9,16,...]
           M(     )     -- | map with argument ([1,0,0]; example with 1)
                 ḋ      -- | | convert to binary: [1]
             ¤  ↔       -- | | reverse both arguments of: [1] [0,0,1]
              ż≠        -- | | | zip with inequality (absolute difference) keeping longer elements: [1,0,1]
                        -- | : [[1,0,1],[0,0,0],[1,0,1,1],[0,0,1,0,1],[1,0,1,1,1],....
                        -- : [[1,0,1],[0,0,0],[1,0,1,1],[0,0,1,0,1]]
    f(  )               -- filter elements where
       →                -- | last element
      ¬                 -- | is zero
                        -- : [[0,0,0]]
 mΣ                     -- sum each: [0]
▼                       -- minimum: 0

▼mΣfo¬←ṠMz≠ȯfo£İ□ḋπŀ2Lḋ2バイト節約します。完璧なスクエアスコアをリッピングします。
Mr Xcoder

@ Mr.Xcoder:; Pスコアについての恥...しかし、私は今16を標的に、いくつかのより多くを処分した
ბიმო


4

05AB1E20 15 バイト

Lnʒ‚b€gË}^b€SOß

@ Mr.XcoderがJelly answerのポートを使用して-5バイトに感謝します

オンラインそれを試してみたり、すべてのテストケースを確認します(彼らは60秒後にタイムアウトしているため、最大3つのテストケースが削除されているが、まだ他のテストケースと35〜45秒程度かかります)。

説明:

L            # Create a list in the range [1, input]
             #  i.e. 22 → [0,1,2,...,20,21,22]
 n           # Take the square of each
             #  i.e. [0,1,2,...,20,21,22] → [0,1,4,...,400,441,484]
  ʒ     }    # Filter this list by:
   ,         #  Pair the current value with the input
             #   i.e. 0 and 22 → [0,22]
             #   i.e. 25 and 22 → [25,22]
    b        #  Convert both to binary strings
             #   i.e. [0,22] → ['0','10110']
             #   i.e. [25,22] →  ['10000','11001']
     g      #  Take the length of both
             #   i.e. ['0','10110'] → [1,5]
             #   ['10000','11001'] → [5,5]
       Ë     #  Check if both are equal
             #   i.e. [1,5] → 0 (falsey)
             #   i.e. [5,5] → 1 (truthy)
^            # After we've filtered, Bitwise-XOR each with the input
             #  i.e. [16,25] and 22 → [6,15]
 b           # Convert each to a binary string again
             #  i.e. [6,15] → ['110','1111']
  S         # Change the binary strings to a list of digits
             #  i.e. ['110','1111'] → [['1','1','0'],['1','1','1','1']]
    O        # Take the sum of each
             #  i.e. [['1','1','0'],['1','1','1','1']] → [2,4]
ß            # And then take the lowest value in the list
             #  i.e. [2,4] → 2

1
それでは、有効な15バイト:Lnʒ‚b€gË}^b€SOß。これは、しかし、残念ながら、あなたのテストスイートを壊す
氏Xcoder

1
@ Mr.Xcoderありがとう!そして、私が何かをゴルフした後、ほとんどの場合、私のテストスイートは壊れます。
ケビンCruijssen

05AB1Eのテストスイートを書くのが苦手だと思います¯\ _(ツ)_ /¯、それを修正してくれてうれしいです:)
Xcoder氏18


3

ガイア、18 バイト

私のゼリーの答えの近くのポート。

s¦⟪,b¦l¦y⟫⁇⟪^bΣ⟫¦⌋

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

壊す

s¦⟪、b¦l¦y⟫⁇⟪ ^ bΣ⟫¦⌋ –完全なプログラム。入力をNと呼びましょう。
s¦ –範囲[1 ... N]の各整数を二乗します。
  ⟪⟫⁇–駆け抜けたときに特定の条件を満たすものを選択する
                     二項ブロック。ダイアディックブロックを使用すると、1バイト節約できます。
                     入力Nは、暗黙的に別の引数として使用されます。
   、–現在の要素とリスト内のNをペアにします。
    b¦ –それらをバイナリに変換します。
      l¦ –長さを取得します。
        y –次に、それらが等しいかどうかを確認します。
           ⟪ ⟫¦ –ダイアディックブロックを介してすべての有効な整数を実行します。
            ^ – NとそれぞれXOR
             bΣ–バイナリに変換して合計(バイナリで1をカウント)
                 ⌋–最小。

2

Brachylog56 41バイト

長さの記録を破るつもりはないが、とにかくそれを投稿すると思った

⟨⟨{⟦^₂ᵐḃᵐ}{h∋Q.l~t?∧}ᶠ{ḃl}⟩zḃᶠ⟩{z{∋≠}ᶜ}ᵐ⌋

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


ただ、ジッピングが重要だと気づきました。ダイナーから戻った後、短縮します
クロッペブ

1
@Arnauldええ、主な問題は、range(0、n + 1)の各iについて、範囲を再計算し、それを2乗して2進数にしたことです。これを外に置くとさらに数バイトが必要になりましたが、今ではずっと高速
です-Kroppeb

2

x86-64アセンブリ、37バイト

バイトコード:

53 89 fb 89 f9 0f bd f7 89 c8 f7 e0 70 12 0f bd
d0 39 f2 75 0b 31 f8 f3 0f b8 c0 39 d8 0f 42 d8
e2 e6 93 5b c3

素敵なことに、これは最高の例を1秒未満で計算します。

アルゴリズムの中心は、通常どおりxor / popcountです。

    push %rbx
    /* we use ebx as our global accumulator, to see what the lowest bit
     * difference is */
    /* it needs to be initialized to something big enough, fortunately the
     * answer will always be less than the initial argument */
    mov %edi,%ebx
    mov %edi,%ecx
    bsr %edi,%esi
.L1:
    mov %ecx,%eax
    mul %eax
    jo cont     /* this square doesn't even fit into eax */
    bsr %eax,%edx
    cmp %esi,%edx
    jnz cont    /* can't invert bits higher than esi */
    xor %edi,%eax
    popcnt %eax,%eax
    cmp %ebx,%eax   /* if eax < ebx */
    cmovb %eax,%ebx
cont:
    loop .L1
    xchg %ebx,%eax
    pop %rbx
    retq

の少なくとも1つをmovxchg
-ceilingcatで置き換えることを提案

私が知る限り、バイトを節約できるのは1つだけであり(mov %ecx,%eax)、そこで%ecxを停止させることはできません。
ObsequiousNewt


1

、31バイト

NθI⌊EΦEθ↨×ιι²⁼LιL↨θ²ΣE↨責⁼λ§ιμ

オンラインでお試しください!リンクは、コードの詳細バージョンです。説明:

Nθ                              Input N
       θ                        N
      E                         Map over implicit range
          ιι                    Current value (twice)
         ×                      Multiply
        ↨   ²                   Convert to base 2
     Φ                          Filter over result
               ι                Current value
                  θ             N
                 ↨ ²            Convert to base 2
              L L               Length
             ⁼                  Equals
    E                           Map over result
                       θ        N
                      ↨ ²       Convert to base 2
                     E          Map over digits
                           λ    Current base 2 digit of N
                             ι  Current base 2 value
                              μ Inner index
                            §   Get digit of value
                          ⁼     Equals
                         ¬      Not (i.e. XOR)
                    Σ           Take the sum
   ⌊                            Take the minimum
  I                             Cast to string
                                Implicitly print




1

C(gcc) 93  91バイト

g(n){n=n?n%2+g(n/2):0;}m;i;d;f(n){m=99;for(i=0;++i*i<2*n;m=g(d=i*i^n)<m&d<n/2?g(d):m);n=m;}

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


編集:元のソリューション(オンラインで試してみてください!)は、変数の1つm、グローバルをタイプを指定せずに数バイトを節約するため、外部で初期化されたf(n)ため、呼び出し間で再初期化する必要があったと思います


ゴルフされていないコードとコメントされたコード:

g(n){n=n?n%2+g(n/2):0;} // returns the number of bits equal to 1 in n
m; //miminum hamming distance between n and a square
i; //counter to browse squares
d; //bitwise difference between n and a square
f(n){m=99; //initialize m to 99 > size of int (in bits)
    for(
        i=0;
        ++i*i<2*n; //get the next square number, stop if it's greater than 2*n
        g(d=i*i^n)<m&&d<n/2&&(m=g(d)) //calculate d and hamming distance
//      ^~~~~~~~~~~^ if the hamming distance is less than the minimum
//                    ^~~~^ and the most significant bit of n did not change (the most significant bit contains at least half the value)
//                           ^~~~~~~^ then update m
       );
    n=m;} // output m

編集:

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