切换一些位并得到一个正方形


26

给定一个整数,您必须找到将N反转为平方数所需的最小位数。只允许将最高有效以下的反。N>3N

例子

  • 已经是一个平方数( 2 2),因此预期输出为 0N=4220
  • 可通过将1位取反来变成一个平方数: 11000 1100 1 25 = 5 2),因此预期输出为 1N=24110001100125=521
  • 通过反转的单个位不能被转变成平方数(可能的结果是 23 20 18 30),但它可以通过反转2位来实现: 10110 10 0 0 0 16 = 4 2) ,因此预期输出为 2N=2223201830101101000016=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]

几乎一半的答案都不会100048606在TIO上执行,这是一个问题吗?
魔术章鱼缸

@MagicOctopusUrn谢谢,我已经更新了规则,以使其更清晰,支持是可选的。N10000
阿纳尔德

1
这也是一个很好的最快代码问题(没有输入大小限制)
qwr

@qwr是的,可能是。或者,如果您想变硬:给定,找到最小的N,使f N = kkNf(N)=k
阿纳尔德

Answers:


14

Ruby,74个字节

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

在线尝试!

这将生成的序列(这是远远超过足够)中,用异或它Ñ,然后发生在其二进制表示的1的任一数,如果比特的数量是少等于或等于log 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

@Piccolo不能相信我错过了,谢谢!
门把手

6

果冻,12 字节

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

在线尝试!

查看测试套件!

单声道链接。应该是可打高尔夫球的。但是我太愚蠢了,无法想到一种摆脱³s的方法。这是我的第一个答案,我通常成功地使用过滤/映射/循环以及二元链\ o /

说明

²,BẈEðƇ²^B§Ṃ–完整程序/ Monadic链接。调用参数N。
     ðƇ–保留以下二进链的[1 ... N]过滤器:
²,BẈE–当前项目的平方具有与N相同的位长。
²–正方形。
 ,–与N配对。
  B –将它们都转换为二进制。
   Ẉ–检索其长度。
    E –并检查它们是否相等。
       ²^ –过滤后,将结果平方并与N进行异或。
         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个字节。RIP您完美的平方分数。
Xcoder先生18年

@ Mr.Xcoder:关于耻辱的比分。但我摆脱了一些,现在靶向16,P
ბიმო

5

Perl 6、65字节

{min map {+$^a.base(2).comb(~1) if sqrt($a+^$_)!~~/\./},^2**.msb}

在线尝试!

在数字的平方根的字符串表示形式中查找一个句点,对于测试一个完美的平方,我感到有点肮脏,但是...可以删除字节的任何东西。


4

05AB1E20 15 字节

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

-5字节,感谢@ Mr.Xcoder使用了Jelly答案的端口。

在线尝试验证所有测试用例(删除了最大的三个测试用例,因为它们在60秒后超时;与其他测试用例相比,仍然需要大约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先生,18年

1
@ Mr.Xcoder谢谢!我打高尔夫球后,我的测试套件几乎总是坏了。XD但现在也已修复。
凯文·克鲁伊森

我想我不太擅长在05AB1E上编写测试套件,\\ _(ツ)_ /¯,很高兴您已将其修复:)
Xcoder先生,18年


3

盖亚 18 字节

我的果冻答案近在咫尺。

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

在线尝试!

分解

s¦⟪,b¦l¦y⟫⁇⟪ ^ bΣ⟫¦⌋ –完整程序。我们将输入称为N。
s-对[1 ... N]范围内的每个整数取平方。
  ⟫⁇–选择运行时满足一定条件的那些
                     二元方块。使用二进位块可节省一个字节,因为
                     输入N被隐式用作另一个参数。
   ,–将当前元素与N配对。
    b¦ –将它们转换为二进制。
      l¦ –取得长度。
        y –然后检查它们是否相等。
           – –通过二进位块运行所有有效整数。
            ^ –与N进行异或。
             bΣ–转换为二进制和之和(以二进制数计1)
                 ⌋–最小值。

2

Brachylog56 41字节

它不会打破任何长度记录,但以为我还是会发布它

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

在线尝试!


刚意识到拉链是一回事。从餐厅回来后,我会把它缩短
Kroppeb '18

1
@Arnauld是的,主要的问题是,对于范围(0,n + 1)中的每个i,我都重新计算了范围,并将其平方并为二进制。将其放到外面需要几个字节,但是现在要快得多
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

很好,这甚至可以在不到一秒钟的时间内计算出最高的示例。

该算法的核心是通常的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

建议您movxchg
ceilingcat

据我所知,只有一个可以保存一个字节(mov %ecx,%eax),并且我不能让%ecx在那里死掉。
ObsequiousNewt

1

Wolfram语言(Mathematica),67字节

Min@DigitCount[l=BitLength;#~BitXor~Pick[s=Range@#^2,l@s,l@#],2,1]&

在线尝试!

需要 {1个2ñ}并将它们平方。然后,与BitLength输入相同的数字被Picked,并BitXor与输入一起被ed 。接下来,Minimum DigitCount1返回S IN的二进制文件。


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;}

在线尝试!


编辑:我认为我原来的解决方案(在线尝试!)无效,因为其中一个变量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个字节
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.