查找具有各种长度的循环的函数


11

的功能被说成具有一个长度的周期n如果存在一个X在其结构域,使得˚F Ñ(X)= X˚F (X)≠X0 <M <N ,其中,上标Ñ表示ñ - f的折叠应用。请注意,长度为1的循环是不动点f(x)= x

您的任务是实现从整数到其自身的双射函数,该函数正好具有每个正长度n的一个周期。双射函数是一对一的对应关系,即每个整数都恰好映射到一次。具有一个长度为n的正好一个周期意味着正好有n个不同的数字x,对于0 <m <nf n(x)= xf m(x)≠x

这是x = 0周围的此类函数的示例:

x     ... -7 -6 -5 -4 -3 -2 -1  0  1  2  3  4  5  6  7 ...
f(x)  ...  2  4  6 -3 -1  1 -4  0 -2  5  7 -7 -6  3 -5 ...

该摘录包含长度为15的循环:

n   cycle
1    0
2   -2  1
3   -4 -3 -1
4   -5  6  3  7
5   -7  2  5 -6  4
...

请注意,以上我仅在数学意义上使用“函数”。您可以使用选择的语言编写函数或完整程序,只要它以单个(带符号)整数作为输入并返回单个(带符号)整数即可。通常,您可以通过STDIN,命令行参数,函数参数等进行输入,并通过STDOUT,函数返回值或函数(输出)参数等进行输出。

当然,许多语言不(轻松)支持任意精度整数。如果您的实现仅在您语言的本机整数类型的范围内有效,只要该范围至少覆盖[-127,127]范围,并且将语言的整数类型替换为任意整数,该方法就可以对任意整数有效,精度整数。

适用标准规则。


2
密切相关。尽管差异似乎很小,但它们意味着没有对旧方法进行大量修改就行得通,特别是我认为应对挑战的成功方法根本无法适应。
马丁·恩德

“每个长度正好有一个周期”,“每个长度都有许多周期”:这是唯一可以将其他东西区分开的区别吗?
2016年

@ Agawa001这是一个区别,另一个是另一个挑战是关于正整数的函数,而这个挑战要求在所有整数上都有一个函数。
马丁·恩德

1
我认为您对周期的定义需要包括n最小。否则,长度为2的循环也将计为长度4和6的循环,依此类推。
xnor

@xnor糟糕,要点。
马丁·恩德

Answers:


2

Pyth,27 18字节

_h?gQ0^2Q*.5@,Q-xh

说明(Pyth初始化Q为输入整数):

_                       negative of (
                          (
  ?gQ0                      if Q >= 0:
      ^2Q                     2**Q
                            else:
         *.5                  half of
            @        Q          element Q (modulo list length) in
             ,                    the two element list [
              Q                     Q,
                 hQ                 ((Q plus 1)
                x  Q                 XOR Q)
               -    Q               minus Q
                                  ]
 h                        ) plus 1
                        )

这有周期

(-1)
(0,-2)
(1,-3,-4)
(2,-5,-7,-6)
(3,-9,-13,-11,-8)
(4,- 17,-25,-21,-15,-10)
(5,-33,-49,-41,-29,-19,-12)
(6,-65,-97,-81,-57, -37,-23,-14)
(7,-129,-193,-161,-113,-73,-45,-27,-16)
(8,-257,-385,-321,-225 ,-145,-89,-53,-31,-18)
(9,-513,-769,-641,-449,-289,-177,-105,-61,-35,-20)

长度的循环Ñ由下式给出

n − 2,
−2 ^(n − 2)⋅1− 1,
−2 ^(n −3)⋅3− 1,
−2 ^(n − 4)⋅5− 1,
…,
−2 ^ 2 ⋅(2· n -7)-1,
-2 ^1⋅(2· n -5)-1,
-2 ^0⋅(2· n -3)-1)。

每个整数ķ ≥-1显示为(第一元件ķ + 2)-cycle。对于每个整数ķ <-1,我们可以唯一写1 - ķ = 2 ^ ⋅(2⋅ Ĵ + 1)对于一些Ĵ ≥0; 然后k出现为(i + j + 2)-周期的第(j + 2)个元素。


5

MATL,47字节

E|G0<-QXJ:tQ*2/0hStJ<f0))Q2MQ)&:J6M-)2/ttk>Eq*k

在线尝试!

一般说明

下面的功能2与@ Sp3000对相关挑战的回答中使用的功能相同。感谢@ Agawa001的注意。

该功能由三个部分组成:

  1. Z(整数)到N(自然数)的双射。
  2. NN的双射具有所需的特征(每个长度一个周期)。
  3. 函数1的逆函数。

之所以使用函数1和3是因为(我认为)在N中要比在Z中更容易实现所需的行为。

函数2如下:上一行是域,下一行是共域。为了清楚起见,使用逗号:

1,  2  3,  4  5  6,  7  8  9  10  ...
1,  3  2,  6  4  5, 10  7  8   9  ...

第一个块(1从上到下1)是长度为1的循环。第二个块(从2 33 2)为长度为2的循环,依此类推。在每个块中,下部(函数的图像)是循环移位的上部向右走一步。

功能1如下:

 -5  -4  -3  -2  -1   0  +1  +2  +3  +4  ...
+10  +8  +6  +4  +2  +1  +3  +5  +7  +9  ...

函数3与1相同,但两行互换了。

例子

的图片3-5。首先由功能1 3映射到7;然后由功能2 7映射到10;然后10通过函数3映射到-5`。

长度为1的循环为0。长度为2的循环为-1 1。长度-3周期-3 2 -2

代码说明

功能1和3很简单。

功能2通过查找相应输入块的下端点来工作。例如,如果9找到此函数的输入7(请参见上面的块)。然后选择10示例中的上端点。借助MATL基于1的模块化索引,可以实现块的循环移位。

         % FUNCTION 1
         % Implicit input
E|       % Multiply by two. Absolute value
G0<      % 1 if input is negative, 0 otherwise
-        % Subtract
Q        % Add 1
XJ       % Copy to clipboard J. Used as input to the next function

         % FUNCTION 2
:        % Range [1 2 ... J], where J denotes the input to this function
tQ*      % Duplicate, increment by 1, multiply
2/       % Divide by 2
0hS      % Prepend a 0. This is needed in case J is 0
tJ<f     % Duplicate. Find indices that are less than the input J
0)       % Pick the last index.
)        % Apply as index to obtain input value that ends previous block
Q        % Add 1: start of current block
2M       % Push the two arguments to second-to-last function call
Q)       % Add 1 and use as index: end of current block
&:       % Inclusive binary range: generate input block 
J        % Push J (input to function 2)
6M-      % Subtract start of block
)        % Apply as index (1-based, modular). This realizes the shifting

         % FUNCTION 3
2/       % Divide by 2
ttk>     % Duplicate. 1 if decimal part is not 0; 0 otherwise
Eq       % Multiply by 2, add 1
*        % Multiply
k        % Round down
         % Implicit display

这是sp3000的功能的转折吗?
2016年

@ Agawa001哦,是吗?我没有看到其他挑战。我来看一下
路易斯·门多

哦。肯定是。至少这澄清了我的推理,如果不是原始的话,是正确的:-)
路易斯·门多

令人惊讶的是,不止一个人的思想被紧密地组织以散发出相近的想法。
2016年

4

Python 2,55个字节

g=lambda n,k=1:n/k and~g(~n+k*(n>0),k+1)+k*(n>0)or-~n%k

59个字节:

g=lambda n,k=1:n<0and~g(~n,2)or n/k and k+g(n-k,k+2)or-~n%k

创建周期

[0]
[-1, -2]
[1, 2, 3]
[-3, -4, -5, -6]
[4, 5, 6, 7, 8]
...

我对先前挑战的解决方案中修改而来,该挑战是从Sp3000的构造中修改而来

功能

g=lambda n,k=1:n/k and k+g(n-k,k+2)or-~n%k

产生奇数大小的非负数周期

[0]
[1, 2, 3]
[4, 5, 6, 7, 8]
...

要找到正确的周期大小k,请n向下移动输入k=1,3,5,7,...直到结果在间隔内[0,k)。通过操作循环此间隔n->(n+1)%k,然后撤消对输入所做的所有减法。这是由递归实现的k+g(n-k,k+2)

现在,我们需要负数才能形成偶数周期。请注意,如果我们修改g为以k=2in 开头,则会g得到大小相等的周期

[0, 1]
[2, 3, 4, 5]
[6, 7, 8, 9, 10, 11]
...

这些通过位补码变成负数~。因此,当n为负数时,我们简单地评估g(n)~g(~n,2)


我不知道它是否有帮助,但是另一种计算方法k似乎是Math.floor(Math.sqrt(n))*2+1
尼尔

@Neil我研究了算术确定边界和循环大小,甚至以这种方式进行了整个计算,但是这些表达式在Python中很长,我发现递归会更短。
xnor

3

Python 3,110个字节

我仍然没有弄清楚如何在其中获取lambda

如果n是一个三角形数字[1、3、6、10、15、21、28等...],则f(n)是列表中的阶乘以负1。如果数字为负数,则给它+下一个最小的三角数。否则,增加。

示例:5不是三角形数字,因此加1。

在下一个迭代中,我们有6。6是一个三角形数字,它是列表中的第3个,因此为-3。

该程序给出了这些清单

长度1:[0]

长度2:[1,-1]

长度3:[2,3,-2]

长度4:[4,5,6,-3]

长度5:[7,8,9,10,-4]

x=int(input())
if x<0:print((x**2+x)/2+1)
else:
 a=((8*x+1)**.5-1)/2
 if a%1:print(x+1)
 else:print(-a)

编辑:再次感谢@TuukkaX删除多余的字符。


1
你可以改变0.5.5input('')input()
伊西(Yytsi)

2

Python 3,146个字节

对于每个大于0的数字,都有偶数循环(len 2,4,6,8 ...),而小于0的奇数循环(1,3,5,7)。0映射到0。

(-3,-2,-1),(0),(1,2),(3,4,5,6)

映射到

(-2,-1,-3),(0),(2,1),(6,3,4,5)

f=lambda x:1+2*int(abs(x)**.5)if x<1 else 2*int(x**.5+.5)
x=int(input());n=f(x)
if x>0:b=n*(n-2)/4
else:b=-((n+1)/2)**2
print(b+1+(x-b-2)%n)

编辑:@TuukkaX从先前的解决方案中删除了8个字节。还有3。


1
认为您可以在第一行的if语句之前删除空格。并且mi可以更改为较小的值,例如b
Yytsi '16

这是打出同样的节目:f=lambda x:1+2*int(abs(x)**0.5)if x<1 else 2*int(x**0.5+0.5) x=int(input()) n=f(x) if x>0:b=n*(n-2)/4 else:b=-((n+1)/2)**2 print(b+1+(x-b-2)%n)
Yytsi '16

1
谢谢@TuukkaX。我忘记了2个字符变量“ mi”。
洋红色

1
我也改为input('')input()。引号是无用的,因为当我们只想获取输入内容时,不必在控制台上打印任何内容。
伊西(Yytsi)'16

1
甚至更短。删除点之前的零。f=lambda x:1+2*int(abs(x)**.5)if x<1 else 2*int(x**.5+.5) x=int(input());n=f(x) if x>0:b=n*(n-2)/4 else:b=-((n+1)/2)**2 print(b+1+(x-b-2)%n)
伊西(Yytsi)

2

Matlab的(423)

function u=f(n),if(~n)u=n;else,x=abs(n);y=factor(x);for o=1:nnz(y),e=prod(nchoosek(y,o)',1);a=log(x)./log(e);b=find(a-fix(a)<exp(-9),1);if ~isempty(b),k=e(b);l=fix(a(b));break;end;end,if(abs(n)==1)k=2;l=0;end,if(k==2)l=l+1;x=x*2;end,e=dec2base(l,k)-48;o=xor(e,circshift(e,[0 1]));g=~o(end);if(~o|nnz(o==1)~=numel(e)-g),u=n*k;else,if((-1)^g==sign(n)),u=sign(n)*k^(base2dec([e(2:end-1) 1]+48,k)-(k==2));else,u=n*k;end,end,end
  • 非竞争性的,因为它打破了最后一个排名的良好记录,而我正在努力地尽可能缩短它。

  • 关于matlab准确性的一些荒谬的错误,除了使我的代码显得过大之外,我找不到其他出路。另一方面,我选择的映射是基于素数和n元对数的。

执行

 f(2)

 1

 f(1)

 2

 f(-2)

 -4

 f(-4)

 -8

 f(-8)

 -1

 f(0)

 0



 ----------------------------

说明

  • 首先,Knowwing可以将任何数字写为质数指数的乘积N=e1^x1*e2^x2...,因此我选择对周期图像进行映射,C这些图像是从最小因数(不一定是质数)的最大指数中提取出来的,N是N的完美幂。

  • 用简单的话来说,让N=P^xP是最小的理想根,x精确地表示周期的两个基本项:x=Ʃ(r*P^i),一个项P是周期的基数以及主数N的理想根,并且k是周期的度数C=p^k,其中i在1到k之间变化,r对于任何后续原像,系数增加1,并由P-1界定,直到所有系数设置为r = 1,因此我们移至该循环的开始。

  • 为避免循环之间发生冲突,质数而不是其乘积的取幂选择是准确的,因为作为两个碱基的循环的示例,3并且2它们之间的相交点可以是3*2,因此可以避免这种情况,因为一个循环的程度大于其次数。 base,并且满足点还有一个base 6和degree 1的循环。

  • 负数是一个例外,为此,我为负数保留了奇数度,为其余数保留了偶数度。怎么会这样 ?

    对于嵌入在一个循环中的任何数字N P^k,将其写为P^(a0*P^i0+a1*P^i1+...)(a0*P^i0+a1*P^i1+...)则将其以P元为单位转换为a0,a1,....,以澄清这一点,如果(p = 2)序列必须以二进制为基础。众所周知,在没有设置正/负度数和(+/- 1)例外的情况下,k当且仅当序列A写为1111..{k+1}..10111..{k}..1针对所有基数时,数字N才在度数循环的边缘上不需要旋转,因此分别k/k'为它们的奇数/偶数度指定负/正条件,这两个奇数序列以形式写出,偶数序列以形式101..{k}..100写出101..{k'}..10分别为负/正数循环的起始边缘。

    例:

    取一个数字N=2^10x=10=2^1+2^3序列A被写入A=1010,这种类型的序列表示正数周期的有限边,即C=2^3,因此下一个图像是起始边的边A=011,即8但是,将结果标准化为(+ / -)1个异常2^10/2映射到8/2并且上一个图像不得旋转。

    取一个数字N=-3^9x=9=3^2序列A被写入A=100,这种类型的序列表示负数循环的有限边,即C=3^1,因此下一个图像是开始边的负边A=01,即3,但是,通过使该结果适应负/正条件-3^9映射到-3

  • 对于这对夫妇(-/+)1,我设想将其2插入一定数量的循环基中,以掩盖一个普通的循环基团序列{2,4}{8,16,32,64}..以另一种形式构成的方式{1,2}{4,8,16,32}..,这可以防止先前元素的任何损失,并且操作只是随着弹出而改变一个新元素。


结果:

运行以下代码表以验证循环数的第一个合理范围:

for (i=1:6) 
index=1;if(max(factor(i))>=5) index=0;end
for ind=0:index
j=f(((-1)^ind)*i); while(((-1)^ind)*i~=j)fprintf('%d ',j);j=f(j);end,fprintf('%d \n',(-1)^ind*i),pause,end,
end

这导致这个结果

 2 1 
 -2 -4 -8 -1 
 1 2 
 -4 -8 -1 -2 
 9 27 3 
 -9 -27 -81 -243 -729 -2187 -6561 -19683 -3 
 8 16 32 64 128 256 512 4 
 -8 -1 -2 -4 
 25 125 625 3125 5 
 36 216 1296 7776 46656 6 
 -36 -216 -1296 -7776 -46656 -279936 -1679616 -10077696 -60466176 -362797056 -2.176782e+009 -1.306069e+010 ??? Error using ==> factor at 27

最后一个是细分错误,但它适合[-127,127]标准有符号整数范围。


我前一段时间使用此技术在我的旧C程序中定义哈希函数,它的工作原理很简单!
2016年

0

JavaScript(ES6),73个字节

f=(n,i=0,j=0,k=0,l=1,m=i<0?-i:~i)=>n-i?f(n,m,k++?j:i,k%=l,l+!k):++k-l?m:j

通过枚举序列(0,-1,1,-2,2,-3,3,...)直到找到n,对循环进行计数来进行工作。i包含当前条目;j包含当前循环的开始,循环k内的索引,l当前循环的长度以及m序列中的下一个条目。一旦找到,n我们就开始j是否处于周期的末尾m

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.