Tìm một hàm với chu kỳ của mọi độ dài


11

Một chức năng được cho là có một chu kỳ có độ dài n nếu có tồn tại một x trong phạm vi của nó mà f n (x) = xf m (x) ≠ x cho 0 <m <n , nơi superscript n biểu thị n - ứng dụng gấp của f . Lưu ý rằng một chu kỳ có độ dài 1 là một điểm cố định f (x) = x .

Nhiệm vụ của bạn là thực hiện một chức năng phỏng đoán từ các số nguyên cho chính chúng, có chính xác một chu kỳ của mỗi độ dài dương n . Hàm sinh học là một tương ứng một-một, tức là mọi số nguyên được ánh xạ tới chính xác một lần. Có chính xác một chu kỳ có độ dài n có nghĩa là có chính xác n số x riêng biệt mà f n (x) = xf m (x) ≠ x với 0 <m <n .

Dưới đây là một ví dụ về chức năng như vậy có thể trông như thế nào xung quanh 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 ...

Đoạn trích này chứa các chu kỳ có độ dài từ 1 đến 5 :

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

Lưu ý rằng ở trên tôi chỉ sử dụng "hàm" theo nghĩa toán học. Bạn có thể viết một hàm hoặc một chương trình đầy đủ bằng ngôn ngữ bạn chọn, miễn là nó lấy một số nguyên (đã ký) làm đầu vào và trả về một số nguyên (đã ký). Như thường lệ, bạn có thể nhận đầu vào qua STDIN, đối số dòng lệnh, đối số hàm, v.v. và đầu ra qua STDOUT, giá trị trả về hàm hoặc đối số hàm (out), v.v.

Tất nhiên, nhiều ngôn ngữ không (dễ dàng) hỗ trợ các số nguyên chính xác tùy ý. Sẽ tốt nếu việc triển khai của bạn chỉ hoạt động trên phạm vi loại số nguyên gốc của ngôn ngữ của bạn, miễn là nó bao gồm ít nhất phạm vi [-127, 127] và nó sẽ hoạt động cho các số nguyên tùy ý nếu loại số nguyên của ngôn ngữ được thay thế bằng tùy ý- số nguyên chính xác.

Luật tiêu chuẩn được áp dụng.


2
Quan hệ gần gũi. Mặc dù sự khác biệt có vẻ nhỏ, nhưng chúng ngụ ý rằng không có cách tiếp cận cũ nào hoạt động mà không sửa đổi đáng kể, và đặc biệt tôi không nghĩ cách tiếp cận chiến thắng từ thách thức đó có thể được điều chỉnh hoàn toàn.
Martin Ender

"Có chính xác một chu kỳ của mỗi độ dài", "có nhiều chu kỳ chiều dài": đây có phải là sự khác biệt duy nhất làm mất đi sự khác biệt?
Abr001am

@ Agawa001 Đó là một điểm khác biệt, thách thức khác là về các chức năng trên các số nguyên dương, trong khi thử thách này yêu cầu một chức năng trên tất cả các số nguyên.
Martin Ender

1
Tôi nghĩ rằng định nghĩa của bạn về chu kỳ cần bao gồm n là tối thiểu. Mặt khác, chu kỳ của bạn có độ dài 2 cũng được tính là chu kỳ của bạn có độ dài 4 và 6, v.v.
xnor

@xnor Rất tiếc, điểm tốt.
Martin Ender

Câu trả lời:


2

Bình thường, 27 18 byte

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

Giải thích (Pyth khởi tạo Qcho số nguyên đầu vào):

_                       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
                        )

Điều này có chu kỳ

(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)

Chu kỳ của chiều dài n được cho bởi

( n - 2,
2 ^ ( n - 2) 1 - 1,
2 ^ ( n - 3) ⋅3 - 1,
2 ^ ( n - 4) 5 - 1, Cách
,
−2 ^ 2 ⋅ (2 · n - 7) - 1,
−2 ^ 1⋅ (2 · n - 5) - 1,
−2 ^ 0⋅ (2 · n - 3) - 1).

Mỗi số nguyên k ≥ 1 xuất hiện dưới dạng phần tử đầu tiên của ( k + 2)-mô-đun. Với mỗi số nguyên k <1, chúng ta có thể viết duy nhất 1 - k = 2 ^ i (2⋅ j + 1) cho một số i , j ≥ 0; sau đó k xuất hiện dưới dạng phần tử ( j + 2) của ( i + j + 2) − Motorcycle.


5

MATL , 47 byte

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

Hãy thử trực tuyến!

Giải thích chung

Hàm 2 bên dưới giống như được sử dụng trong câu trả lời của @ Sp3000 cho thử thách liên quan. Cảm ơn @ Agawa001 đã chú ý.

Hàm này là thành phần của ba:

  1. Đồ thị từ Z (số nguyên) đến N (số tự nhiên).
  2. Bảo vệ từ N đến N với đặc tính mong muốn (một chu kỳ của mỗi chiều dài).
  3. Nghịch đảo chức năng 1.

Chức năng 1 và 3 được sử dụng vì nó dễ dàng hơn (tôi nghĩ) để đạt được hành vi mong muốn trong N so với Z .

Hàm 2 như sau: dòng trên là miền, dòng dưới là tên miền. Dấu phẩy được sử dụng cho rõ ràng:

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

Khối đầu tiên (từ trên 1xuống dưới 1) là một chu kỳ có độ dài 1. Khối thứ hai (từ 2 3đến 3 2) là một chu kỳ có độ dài 2, v.v ... Trong mỗi khối, phần dưới (hình ảnh của hàm) là phần trên được dịch chuyển tròn một bước sang phải

Chức năng 1 như sau:

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

Hàm 3 giống như 1 với hai dòng được hoán đổi.

Ví dụ

Hình ảnh của 3-5. Đầu tiên 3được ánh xạ tới 7chức năng 1; sau đó 7được ánh xạ tới 10hàm 2; sau đó 10được ánh xạ tới -5` bởi chức năng 3.

Chu kỳ dài 1 là 0. Chu kỳ 2 chiều dài là -1 1. Chu kỳ dài 3 là -3 2 -2, v.v.

Mã giải thích

Hàm 1 và 3 rất đơn giản.

Hàm 2 hoạt động bằng cách tìm điểm cuối thấp hơn của khối đầu vào tương ứng. Ví dụ, nếu đầu vào cho chức năng này là 9nó tìm thấy 7(xem các khối ở trên). Sau đó, nó chọn điểm cuối trên, 10trong ví dụ này. Sự dịch chuyển vòng tròn của khối đạt được nhờ lập chỉ mục mô-đun, dựa trên 1 của MATL.

         % 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

đây là một sự thay đổi của chức năng sp3000 s phải không?
Abr001am

@ Agawa001 Ồ phải không? Tôi không thấy thử thách nào khác. Tôi sẽ xem xét
Luis Mendo

Oh. Nó chắc chắn là như vậy. Ít nhất điều đó làm rõ rằng lý luận của tôi, nếu không phải là nguyên bản, là chính xác :-)
Luis Mendo

thật đáng ngạc nhiên khi có nhiều hơn một tâm trí được đóng khung chặt chẽ để thể hiện những ý tưởng gần gũi.
Abr001am

4

Python 2, 55 byte

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

59 byte:

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

Tạo chu kỳ

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

Được sửa đổi từ giải pháp của tôi trong thử thách trước đó , được sửa đổi từ cấu trúc của Sp3000 .

Chức năng

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

tạo các chu kỳ kích thước lẻ của các số không âm

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

Để tìm kích thước chu kỳ chính xác k, hãy dịch chuyển đầu vào nxuống k=1,3,5,7,...cho đến khi kết quả nằm trong khoảng [0,k). Xoay vòng khoảng thời gian này với thao tác n->(n+1)%k, sau đó hoàn tác tất cả các phép trừ được thực hiện trên đầu vào. Điều này được thực hiện đệ quy bởi k+g(n-k,k+2).

Bây giờ, chúng ta cần tiêu cực để thực hiện các chu kỳ chẵn. Lưu ý rằng nếu chúng ta sửa đổi gđể bắt đầu với k=2tại g, chúng tôi muốn có được chu kỳ thậm chí kích thước

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

Những phản hồi này để phủ định thông qua bổ sung bit ~. Vì vậy, khi ntiêu cực, chúng tôi chỉ đơn giản là đánh giá g(n)~g(~n,2).


Tôi không biết liệu nó có giúp ích gì không, nhưng kdường như một cách tính toán khác Math.floor(Math.sqrt(n))*2+1.
Neil

@Neil Tôi đã xem xét việc xác định ranh giới và kích thước chu kỳ một cách hợp lý và thậm chí thực hiện toàn bộ tính toán theo cách đó, nhưng các biểu thức này dài bằng Python và tôi thấy đệ quy ngắn hơn.
xnor

3

Python 3, 110 byte

Tôi vẫn chưa tìm ra cách để có một lambda trong đó

if n là số tam giác [1,3,6,10,15,21,28, v.v ...] thì f (n) là thứ tự trong danh sách nhân với số âm. nếu số âm, cho nó 1 + số tam giác nhỏ nhất tiếp theo. khác, gia tăng.

Ví dụ: 5 không phải là số tam giác, vì vậy hãy thêm 1.

Lặp lại tiếp theo, chúng ta có 6. 6 là một số tam giác, và nó là thứ 3 trong danh sách, do đó xuất hiện -3.

Chương trình đưa ra những danh sách này

độ dài 1: [0]

độ dài 2: [1, -1]

độ dài 3: [2,3, -2]

dài 4: [4,5,6, -3]

dài 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)

Chỉnh sửa: Một lần nữa xin cảm ơn @TuukkaX vì đã loại bỏ các charcters dư thừa.


1
Bạn có thể thay đổi 0.5để .5input('')để input().
Yytsi

2

Python 3, 146 byte

Với mỗi số lớn hơn 0, có các vòng lặp chẵn (len 2,4,6,8 ...) và nhỏ hơn 0, các vòng lặp lẻ (1,3,5,7). 0 bản đồ thành 0.

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

bản đồ đến

(-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)

Chỉnh sửa: @TuukkaX lấy ra 8 byte từ giải pháp trước đó. Và 3 cái khác.


1
Tôi nghĩ bạn có thể xóa một khoảng trắng trước câu lệnh if ở dòng đầu tiên. Và micó thể được thay đổi thành một cái gì đó nhỏ hơn, chẳng hạn như b.
Yytsi

Đây là chương trình tương tự được đánh xuống: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

1
Cảm ơn, @TuukkaX. Tôi quên mất biến 2 ký tự 'mi'.
Magenta

1
Tôi cũng đổi input('')thành input(). Các trích dẫn là vô ích vì chúng tôi không phải in bất cứ điều gì lên bàn điều khiển khi chúng tôi muốn nhận đầu vào.
Yytsi

1
Thậm chí ngắn hơn. Loại bỏ các số 0 trước các dấu chấm. 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
  • Không cạnh tranh bởi vì nó phá vỡ một kỷ lục tốt về việc được xếp hạng cho bảng xếp hạng cuối cùng, trong khi tôi đang cố gắng rút ngắn nó hết mức có thể.

  • Một số lỗi không liên quan đến độ chính xác trong matlab mà tôi không thể tìm thấy bất kỳ cách nào ngoại trừ làm cho mã của tôi trở nên lớn hơn, mặt khác, ánh xạ mà tôi chọn là về mặt chính và logarit n-ary.

Chấp hành

 f(2)

 1

 f(1)

 2

 f(-2)

 -4

 f(-4)

 -8

 f(-8)

 -1

 f(0)

 0



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

Giải trình

  • Trước tiên, Knonwing, rằng bất kỳ số nào cũng có thể được viết là tích của số mũ của số nguyên tố N=e1^x1*e2^x2...từ cơ sở này, tôi đã chọn ánh xạ các chu kỳ Cđược trích từ số mũ lớn nhất của yếu tố nhỏ nhất (không nhất thiết là số nguyên tố) mà N là một công suất hoàn hảo của .

  • nói một cách đơn giản hơn, hãy để N=P^xP là gốc hoàn hảo nhỏ nhất, xbiểu thị chính xác hai thuật ngữ thiết yếu cho chu trình : x=Ʃ(r*P^i), thuật ngữ Plà cơ sở của chu kỳ cũng là một gốc hoàn hảo cho số chính N và klà mức độ của chu kỳ C=p^k, trong đó ikhác nhau giữa 1 và k, hệ số rđược tăng thêm 1 và giới hạn bởi P-1 cho bất kỳ hình ảnh trước nào sau đó cho đến khi tất cả các hệ số được đặt thành r = 1, vì vậy chúng tôi chuyển sang bắt đầu chu kỳ đó.

  • Để tránh va chạm giữa các chu kỳ, việc lựa chọn lũy thừa các số nguyên tố thay vì các sản phẩm của chúng là chính xác, vì như một ví dụ về hai chu kỳ của các cơ sở 32một điểm gặp gỡ giữa chúng có thể 3*2, vì vậy điều này được tránh vì một chu kỳ được xác định bởi mức độ của nó nhiều hơn mức độ của nó cơ sở, và đối với điểm gặp gỡ có một chu kỳ khác của cơ sở 6và mức 1.

  • Các số âm đặt một ngoại lệ, như đối với nó, tôi dành các mức độ lẻ cho các số âm và thậm chí các độ cho các phần còn lại. Làm sao vậy

    đối với bất kỳ số N nào được nhúng trong một chu kỳ P^k, được ghi là P^(a0*P^i0+a1*P^i1+...), số lượng (a0*P^i0+a1*P^i1+...)được chuyển mã trong cơ sở P-ary như a0,a1,...., để làm rõ điểm này nếu (p = 2) chuỗi phải ở trong cơ sở nhị phân. Như đã biết một cách tự nhiên mà không đặt điều kiện về mức độ dương / âm và ngoại lệ (+/- 1), một số N nằm trên các cạnh của một chu kỳ độ kkhi và chỉ khi chuỗi Ađược viết là 1111..{k+1}..10hoặc 111..{k}..1cho tất cả các cơ sở, nếu không không cần quay, do đó việc gán điều kiện âm / dương cho một mức độ lẻ / chẵn tương ứng k/k'cho cả hai tạo ra một chuỗi lẻ được viết dưới dạng 101..{k}..100, một chuỗi chẵn được viết ở dạng 101..{k'}..10cho cạnh đầu của chu kỳ số âm / dương tương ứng .

    Thí dụ:

    Tham gia một số N=2^10, x=10=2^1+2^3, dãy A được viết A=1010, loại chuỗi symptomizes một lợi thế cạnh hữu hạn của dương số chu kỳ, đó là C=2^3, vì vậy hình ảnh tiếp theo là việc bắt đầu cạnh A=011đó là 8, Nhưng , bởi standarizing kết quả này để (+ / -) 1 2^10/2bản đồ ngoại lệ đến 8/2và hình ảnh trước đó không được xoay.

    Tham gia một số N=-3^9, x=9=3^2, dãy A được viết A=100, loại chuỗi symptomizes một lợi thế cạnh hữu hạn của âm số chu kỳ, đó là C=3^1, vì vậy hình ảnh tiếp theo là việc bắt đầu cạnh A=01đó là 3, Nhưng, bằng cách áp dụng kết quả này để tiêu cực / tích cực -3^9bản đồ điều kiện để -3.

  • Đối với cặp vợ chồng (-/+)1, tôi dự tính sẽ xâm nhập nó trong một số cơ sở chu kỳ 2, trong một chiêu bài rằng một chuỗi các nhóm tuần hoàn thông thường {2,4}{8,16,32,64}..được tạo thành ở một hình thức khác {1,2}{4,8,16,32}.., điều này ngăn chặn bất kỳ sự mất mát nào của các yếu tố trước đó và sự thay đổi được thực hiện chỉ là thay đổi với popping một yếu tố mới trong.


Các kết quả:

chạy bảng mã nhỏ này để xác minh phạm vi số chu kỳ hợp lý đầu tiên:

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

Điều này dẫn đến kết quả này

 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

Cái cuối cùng là lỗi phân đoạn nhưng nó phù hợp với phạm vi số nguyên đã ký tiêu chuẩn [-127,127].


Tôi đã sử dụng kỹ thuật này một lúc trước để xác định hàm băm trong một chương trình C cũ của tôi, nó hoạt động rất gọn gàng!
Abr001am

0

JavaScript (ES6), 73 byte

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

Hoạt động bằng cách liệt kê chuỗi (0, -1, 1, -2, 2, -3, 3, ...) cho đến khi tìm thấy n, đếm các chu kỳ khi nó đi. ichứa mục hiện tại; jchứa phần bắt đầu của chu kỳ hiện tại, kchỉ mục trong chu kỳ, lđộ dài của chu kỳ hiện tại và mmục tiếp theo trong chuỗi. Khi chúng tôi tìm thấy, nchúng tôi sẽ thực hiện jnếu chúng tôi ở cuối chu kỳ hoặc mnếu không.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.