Hàm tính toán ℤ →


23

Đó là trivially có thể tạo ra một song ánh hàm từ Z (tập hợp tất cả các số nguyên) để (ví dụ như chức năng nhận dạng).Z

Cũng có thể tạo một hàm tính toán từ đến Z 2 (tập hợp tất cả các cặp của 2 số nguyên; sản phẩm cartesian của ZZ ). Ví dụ: chúng ta có thể lấy mạng biểu diễn các điểm nguyên trên mặt phẳng 2D, vẽ một đường xoắn ốc từ 0 ra ngoài và sau đó mã hóa các cặp số nguyên thành khoảng cách dọc theo đường xoắn ốc khi nó giao nhau với điểm đó.ZZ2ZZ

Xoắn ốc

(Một hàm thực hiện điều này với các số tự nhiên được gọi là hàm ghép nối .)

Trong thực tế, tồn tại một họ các chức năng phỏng đoán này:

fk(x):ZZk

Các thách thức

Xác định một họ các hàm fk(x) (trong đó là số nguyên dương) với thuộc tính mà ánh xạ một cách tổng hợp các số nguyên thành -tuples của các số nguyên.kfk(x)k

Trình của bạn nên, đưa ra đầu vào k và , trả về .xfk(x)

Đây là , vì vậy câu trả lời hợp lệ ngắn nhất (tính bằng byte) sẽ thắng.

Thông số kỹ thuật

  • Bất kỳ gia đình có thể được sử dụng miễn là nó đáp ứng các tiêu chí trên.fk(x)
  • Bạn được khuyến khích thêm một mô tả về cách hoạt động của họ hàm, cũng như một đoạn mã để tính toán nghịch đảo của hàm (điều này không được bao gồm trong số byte của bạn).
  • Sẽ ổn nếu chức năng nghịch đảo là không thể tính toán được, miễn là bạn có thể chứng minh được chức năng đó là tính từ.
  • Bạn có thể sử dụng bất kỳ biểu diễn phù hợp nào cho các số nguyên đã ký và danh sách các số nguyên đã ký cho ngôn ngữ của bạn, nhưng bạn phải cho phép các đầu vào cho chức năng của bạn không bị ràng buộc.
  • Bạn chỉ cần hỗ trợ các giá trị của lên tới 127.k

Có thể lấy một phiên bản chuỗi kxthay vì số nguyên không?
JungHwan tối

@JungHwanMin Chuỗi đại diện cho các số đầu vào là tốt.
Esolanging Fruit

Câu trả lời:


19

Alice , 14 12 byte

/O
\i@/t&Yd&

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

Hàm nghịch đảo (không được đánh gôn):

/o     Q
\i@/~~\ /dt&Z

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

Giải trình

Alice có một phần tử tích hợp giữa 2 , có thể được tính toán với Y(giải nén) và nghịch đảo Z (gói) của nó. Đây là một đoạn trích từ các tài liệu giải thích về sự lựa chọn:

Các chi tiết của bijection có thể không liên quan đến hầu hết các trường hợp sử dụng. Điểm chính là nó cho phép người dùng mã hóa hai số nguyên thành một và trích xuất lại hai số nguyên sau đó. Bằng cách áp dụng lệnh pack nhiều lần, toàn bộ danh sách hoặc cây số nguyên có thể được lưu trữ trong một số duy nhất (mặc dù không theo cách đặc biệt hiệu quả bộ nhớ). Ánh xạ được tính toán bởi hoạt động gói là một hàm tính toán ℤ 2 (tức là ánh xạ một-một). Đầu tiên, các số nguyên {..., -2, -1, 0, 1, 2, ...} được ánh xạ tới các số tự nhiên (bao gồm 0) như {..., 3, 1, 0, 2, 4 , ...} (nói cách khác, các số nguyên âm được ánh xạ tới các số tự nhiên lẻ và các số nguyên không âm được ánh xạ tới các số tự nhiên). Hai số tự nhiên sau đó được ánh xạ thành một thông qua chức năng ghép nối Cantor, viết các chữ số tự nhiên dọc theo các đường chéo của góc phần tư thứ nhất của lưới số nguyên. Cụ thể, {(0,0), (1,0), (0,1), (2,0), (1,1), (0,2), (3,0), ...} là ánh xạ tới {0, 1, 2, 3, 4, 5, 6, ...} . Số tự nhiên thu được sau đó được ánh xạ trở lại các số nguyên bằng cách sử dụng nghịch đảo của mệnh đề trước đó. Lệnh unpack tính toán chính xác nghịch đảo của ánh xạ này.

Như đã nói ở trên, chúng ta có thể sử dụng thao tác giải nén này để ánh xạ đến k . Sau khi áp dụng nó cho số nguyên ban đầu, chúng ta có thể giải nén số nguyên thứ hai của kết quả một lần nữa, nó cung cấp cho chúng ta danh sách ba số nguyên. Vì vậy, các ứng dụng k-1Y cung cấp cho chúng tôi k số nguyên là kết quả.

Chúng ta có thể tính toán nghịch đảo bằng cách đóng gói danh sách Ztừ cuối.

Vì vậy, chương trình có cấu trúc này:

/O
\i@/...d&

Đây chỉ là một mẫu cơ bản cho một chương trình đọc số lượng các số nguyên thập phân khác nhau làm đầu vào và in ra một số biến là kết quả. Vì vậy, mã thực tế chỉ là:

t   Decrement k.
&   Repeat the next command k-1 times.
Y   Unpack.

Một điều tôi muốn giải quyết là "tại sao Alice lại tích hợp sẵn cho một bij → 2 , không phải là lãnh thổ ngôn ngữ golf"? Như với hầu hết các công cụ dựng sẵn của Alice, lý do chính là nguyên tắc thiết kế của Alice rằng mọi lệnh đều có hai ý nghĩa, một cho chế độ Hồng y (số nguyên) và một cho chế độ Thông thường (chuỗi) và hai ý nghĩa này phải bằng cách nào đó liên quan đến cung cấp cho Cardinal và Ordinal chế độ cảm giác rằng chúng là vũ trụ gương trong đó mọi thứ giống nhau nhưng cũng khác nhau. Và khá thường xuyên, tôi có một lệnh cho một trong hai chế độ tôi muốn thêm, và sau đó phải tìm ra lệnh nào khác để ghép với nó.

Trong trường hợp YZchế độ Thông thường xuất hiện đầu tiên: Tôi muốn có một hàm để xen kẽ hai chuỗi (zip) và tách chúng lại (giải nén). Chất lượng của điều này mà tôi muốn nắm bắt trong chế độ Cardinal là tạo thành một số nguyên từ hai và có thể trích xuất hai số nguyên sau đó, điều này làm cho sự lựa chọn tự nhiên như vậy trở thành sự lựa chọn tự nhiên.

Tôi cũng hình dung rằng điều này thực sự sẽ rất hữu ích khi chơi golf, bởi vì nó cho phép bạn lưu trữ toàn bộ danh sách hoặc thậm chí cây số nguyên trong một đơn vị bộ nhớ (phần tử ngăn xếp, ô băng hoặc ô lưới).


Giải thích tuyệt vời như mọi khi
Luis Mendo

Tìm kiếm YZtrong các tài liệu Alice thực sự là điều thôi thúc tôi đăng thử thách này (tôi đã suy nghĩ về nó trong một thời gian, nhưng điều này nhắc nhở tôi).
Esolanging Fruit

11

Python, 96 93 byte

def f(k,x):
 c=[0]*k;i=0
 while x:v=(x+1)%3-1;x=x//3+(v<0);c[i%k]+=v*3**(i//k);i+=1
 return c

Về nguyên tắc, điều này hoạt động bằng cách chuyển đổi số đầu vào xthành ternary cân bằng , và sau đó phân phối các trits (chữ số ternary) ít có ý nghĩa đầu tiên giữa các tọa độ khác nhau theo kiểu vòng tròn. Vì vậy, k=2ví dụ, mọi trit vị trí chẵn sẽ đóng góp vào xtọa độ và mọi trit vị trí lẻ sẽ đóng góp vào ytọa độ. Vì k=3bạn có những đóng góp thứ nhất, thứ tư và thứ bảy (v.v ...) x, trong khi đóng góp thứ hai, thứ năm và thứ tám, và đóng góp ythứ ba, thứ sáu và thứ chín z.

Ví dụ, với k=2, hãy nhìn vào x=35. Trong ternary cân bằng, 35110T(sử dụng ký hiệu của bài viết Wikipedia trong đó Tđại diện cho một -1chữ số). Chia các trits lên cho 1T(các trits thứ nhất và thứ ba, tính từ bên phải) cho xtọa độ và 10(trits thứ hai và thứ tư) cho ytọa độ. Chuyển đổi từng tọa độ trở lại thập phân, chúng tôi nhận được 2, 3.

Tất nhiên, tôi không thực sự chuyển đổi toàn bộ số thành ternary cân bằng cùng một lúc trong mã golf. Tôi chỉ tính toán một trit tại một thời điểm (trong vbiến) và thêm giá trị của nó trực tiếp vào tọa độ thích hợp.

Đây là một hàm nghịch đảo không có danh sách, lấy danh sách tọa độ và trả về một số:

def inverse_f(coords):
    x = 0
    i = 0
    while any(coords):
        v = (coords[i%3]+1) % 3 - 1
        coords[i%3] = coords[i%3] // 3 + (v==-1)
        x += v * 3**i
        i += 1
    return x

fChức năng của tôi có lẽ đáng chú ý cho hiệu suất của nó. Nó chỉ sử dụng O(k)bộ nhớ và mất O(k) + O(log(x))thời gian để tìm kết quả, vì vậy nó có thể hoạt động với các giá trị đầu vào rất lớn. f(10000, 10**10000)Ví dụ, hãy thử và bạn sẽ nhận được câu trả lời ngay lập tức (thêm một số 0 vào số mũ, vì vậy xsẽ 10**100000mất 30 giây hoặc lâu hơn trên PC cũ của tôi). Hàm nghịch đảo không nhanh như vậy, chủ yếu là vì nó khó để biết khi nào nó hoàn thành (nó quét tất cả các tọa độ sau mỗi thay đổi, do đó, nó mất một cái gì đó như O(k*log(x))thời gian). Nó có thể được tối ưu hóa để nhanh hơn, nhưng nó có thể đủ nhanh cho các tham số bình thường.


Bạn có thể xóa khoảng trắng (dòng mới) bên trong vòng lặp while
Ông Xcoder

Cảm ơn, tôi đã nhầm tưởng rằng có một số loại xung đột giữa một vòng lặp và sử dụng ;để xâu chuỗi các câu lệnh trên một dòng.
Blckknght

9

Husk , 10 byte

§~!oΠR€Θݱ

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

Hàm nghịch đảo cũng là 10 byte.

§o!ȯ€ΠRΘݱ

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

Giải trình

Hướng về phía trước:

§~!oΠR€Θݱ  Implicit inputs, say k=3 and x=-48
        ݱ  The infinite list [1,-1,2,-2,3,-3,4,-4,..
       Θ    Prepend 0: [0,1,-1,2,-2,3,-3,4,-4,..
 ~    €     Index of x in this sequence: 97
§    R      Repeat the sequence k times: [[0,1,-1,..],[0,1,-1,..],[0,1,-1,..]]
   oΠ       Cartesian product: [[0,0,0],[1,0,0],[0,1,0],[1,1,0],[-1,0,0],[0,0,1],..
  !         Index into this list using the index computed from x: [-6,1,0]

Hướng ngược lại:

§o!ȯ€ΠRΘݱ  Implicit inputs, say k=3 and y=[-6,1,0]
     ΠRΘݱ  As above, k-wise Cartesian product of [0,1,-1,2,-2,..
   ȯ€       Index of y in this sequence: 97
§o!         Index into the sequence [0,1,-1,2,-2,.. : -48

Sản phẩm của Cartesian tích hợp Πhoạt động độc đáo cho các danh sách vô hạn, liệt kê mỗi k -tuple chính xác một lần.


[[0,1,-1,..],[[0,1,-1,..],[[0,1,-1,..]]phần này được cho là [[0,1,-1,..],[0,1,-1,..],[0,1,-1,..]]?
Erik the Outgolfer

@EriktheOutgolfer Umm yeah, đã sửa ngay bây giờ.
Zgarb

Thật là đẹp Là một lập trình viên J, bạn có biết có cách nào tốt để chuyển đổi một giải pháp danh sách lười biếng như thế này thành J không, điều này không hỗ trợ họ? ^:^:_loại giải pháp thường kết thúc cồng kềnh hơn nhiều ...
Jonah

@Jonah Tôi không chắc. Bạn có thể thử tính toán mảng của tất cả các k với các mục từ i: xvà sắp xếp nó theo tổng các giá trị tuyệt đối, sau đó lập chỉ mục vào đó. Ý tưởng là các mảng này là tiền tố của một "mảng vô hạn" có chứa tất cả các k- tuples.
Zgarb

7

Ngôn ngữ Wolfram (Mathicala) , 61 byte

SortBy[Range[-(x=2Abs@#+Boole[#>=0]),x]~Tuples~#2,#.#&][[x]]&

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

(Lấy số nguyên và sau đó là độ dài của bộ dữ liệu làm đầu vào.)

Nghịch đảo:

If[OddQ[#],#-1,-#]/2&@Tr@Position[SortBy[Range[-(x=Ceiling@Norm@#),x]~Tuples~Length@#,#.#&],#]&

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

Làm thế nào nó hoạt động

Ý tưởng rất đơn giản: chúng tôi biến đầu vào số nguyên thành số nguyên dương (bằng cách ánh xạ 0,1,2,3, ... thành 1,3,5,7, ... và -1, -2, -3, ... Đến 2,4,6, ...) và sau đó lập chỉ mục vào tất cả các k- tuples, được sắp xếp theo khoảng cách từ gốc và sau đó theo phá vỡ mặc định của Mathicala.

Nhưng chúng tôi không thể sử dụng danh sách vô hạn, vì vậy khi chúng tôi tìm kiếm k -tuple thứ n , chúng tôi chỉ tạo k -tuples các số nguyên trong phạm vi {- n , ..., n }. Đây là đảm bảo được đủ, bởi vì n thứ nhỏ nhất k -tuple bởi tiêu chuẩn có mức ít hơn n , và tất cả các bộ định mức n hoặc ít hơn có trong danh sách này.

Đối với nghịch đảo, chúng ta chỉ cần tạo một danh sách k -tuple đủ dài , tìm vị trí của k -tuple đã cho trong danh sách đó, sau đó đảo ngược thao tác "gấp thành số nguyên dương".


2
Chạy với đầu vào [15, 5]đã làm hỏng PC của tôi ...
JungHwan Min

2
Điều đó sẽ xảy ra. Về nguyên tắc, thuật toán hoạt động cho mọi thứ, nhưng trong trường hợp của bạn, nó hoạt động bằng cách tạo ra tất cả 5 bộ dữ liệu từ phạm vi {-31, .., 31} và sau đó lấy số thứ 31, do đó, nó khá tốn bộ nhớ.
Misha Lavrov

3

J, 7 byte

#.,|:#:

Mã J để làm điều này đơn giản đáng xấu hổ

Một hàm ghép nối rất đơn giản (hoặc, hàm tupling) chỉ đơn giản là xen kẽ các chữ số của khai triển nhị phân của mỗi số. Vì vậy, ví dụ (47, 79)sẽ được ghép nối như vậy:

1_0_0_1_1_1_1
 1_0_1_1_1_1
-------------
1100011111111

hoặc, 6399. Rõ ràng, chúng ta có thể khái quát hóa một cách tầm thường cho bất kỳ n-tuple nào.

Hãy xem xét cách thức hoạt động của động từ bằng động từ.

#:là chống cơ sở hai, khi được sử dụng một cách đơn điệu, nó trả về sự mở rộng nhị phân của một số. #: 47 79đưa ra kết quả:

0 1 0 1 1 1 1
1 0 0 1 1 1 1

|:là toán tử chuyển vị, chỉ đơn giản là xoay một mảng. Xoay kết quả #: 47 79cho:

0 1
1 0
0 0
1 1
1 1
1 1
1 1

Khi được sử dụng một cách đơn điệu, ,là toán tử ravel, nó tạo ra một danh sách 1 chiều từ một bảng:

0 1 1 0 0 0 1 1 1 1 1 1 1 1

Cuối cùng, #.chuyển đổi mở rộng nhị phân trở lại, cho chúng ta kết quả 6339.

Giải pháp này sẽ làm việc cho bất kỳ chuỗi số nguyên.


7
Làm thế nào điều này làm việc cho số âm?
Neil

2

Perl 6 , 148 byte

my@s=map ->\n{|grep {n==abs any |$_},(-n..n X -n..n)},^Inf;my&f={$_==1??+*!!do {my&g=f $_-1;my@v=map {.[0],|g .[1]},@s;->\n{@v[n>=0??2*n!!-1-2*n]}}}

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

Ung dung:

sub rect($n) {
    grep ->[$x,$y] { abs($x|$y) == $n }, (-$n..$n X -$n..$n);
}

my @spiral = map { |rect($_) }, ^Inf;

sub f($k) {
    if ($k == 1) {
        -> $_ { $_ }
    } else {
        my &g = f($k-1);
        my @v = map -> [$x, $y] { $x, |g($y) }, @spiral;
        -> $_ { $_ >= 0 ?? @v[2*$_] !! @v[-1-2*$_] }
    }
}

Giải trình:

  • rect($n)là một hàm trợ giúp tạo tọa độ của các điểm tích phân trên cạnh của hình chữ nhật từ tọa độ (-$n,$n)đến($n, $n) .

  • @spiral là một danh sách lười biếng, vô hạn của các điểm tích phân trên các cạnh của hình chữ nhật có kích thước tăng dần, bắt đầu từ 0.

  • f($k)trả về một hàm là một mệnh đề từ các số nguyên thành $k-tuples của các số nguyên.

Nếu $k1,f trả về ánh xạ danh tính -> $_ { $_ }.

Nếu không thì, &g$k-1Mặt là ánh xạ đệ quy thu được từ các số nguyên đến -tuples của các số nguyên.

Sau đó, chúng tôi @spiralxuất phát từ điểm gốc và tại mỗi điểm tạo thành một $k-tuple bằng cách lấy tọa độ X và kết quả làm phẳng của việc gọi gvới tọa độ Y. Ánh xạ tạo ra lười biếng này được lưu trữ trong mảng @v.

@vchứa tất cả $k-tuples bắt đầu bằng chỉ số 0, vì vậy để mở rộng việc lập chỉ mục cho các số nguyên âm, chúng tôi chỉ ánh xạ các đầu vào dương tới các số chẵn và đầu vào âm thành các số lẻ. Một hàm (đóng) được trả về mà tìm kiếm các phần tử @vtheo cách này.


2

JavaScript, 155 byte

f=k=>x=>(t=x<0?1+2*~x:2*x,h=y=>(g=(v,p=[])=>1/p[k-1]?v||t--?0:p.map(v=>v&1?~(v/2):v/2):[...Array(1+v)].map((_,i)=>g(v-i,[...p,i])).find(u=>u))(y)||h(y+1))(0)

Phiên bản hoàn thiện:

k => x => {
  // Map input to non-negative integer
  if (x > 0) t = 2 * x; else t = 2 * -x - 1;
  // we try to generate all triples with sum of v
  g = (v, p = []) => {
    if (p.length === k) {
      if (v) return null;
      if (t--) return null;
      // if this is the t-th one we generate then we got it
      return p;
    }
    for (var i = 0; i <= v; i++) {
      var r = g(v-i, [...p, i]);
      if (r) return r;
    }
  }
  // try sum from 0 to infinity
  h = x => g(x) || h(x + 1);
  // map tuple of non-negative integers back
  return h(0).map(v => {
    if (v % 2) return -(v + 1) / 2
    else return v / 2;
  });
}
  • Đầu tiên, chúng tôi ánh xạ tất cả các số nguyên cho tất cả các số nguyên không âm từng cái một:
    • nếu n> 0 thì kết quả = n * 2
    • mặt khác kết quả = -n * 2 - 1
  • Thứ hai, chúng tôi cung cấp cho tất cả các bộ dữ liệu với số nguyên không âm có độ dài k:
    • tính tổng của tất cả các phần tử, phần tử nhỏ hơn đến trước
    • nếu tổng bằng nhau, so sánh từ trái sang phải, nhỏ hơn đến trước
    • Kết quả là, chúng tôi đã có được bản đồ cho tất cả các số nguyên không âm thành các bộ dữ liệu với k số nguyên không âm
  • Cuối cùng, ánh xạ các số nguyên không âm trong tuple được đưa ra trong bước thứ hai cho tất cả các số nguyên có công thức tương tự trong bước đầu tiên

Tôi nghĩ x<0?~x-x:x+xtiết kiệm 2 byte.
Neil

2

Ngôn ngữ Wolfram (Mathicala) , 107 byte

(-1)^#⌈#/2⌉&@Nest[{w=⌊(√(8#+1)-1)/2⌋;x=#-w(w+1)/2,w-x}~Join~{##2}&@@#&,{2Abs@#-Boole[#<0]},#2-1]&

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

Nghịch đảo, 60 byte

(-1)^#⌈#/2⌉&@Fold[+##(1+##)/2+#&,2Abs@#-Boole[#<0]&/@#]&

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

Giải trình:

Z -> N0 qua f(n) = 2n if n>=0 and -2n-1 if n<0

N0 -> N0 ^ 2 thông qua nghịch đảo của chức năng ghép nối

N0 -> N0 ^ k Liên tục áp dụng cách trên vào số ngoài cùng bên trái cho đến khi chúng ta có được độ dài k

N0 ^ k -> Z ^ k thông qua f(n) = (-1)^n * ceil(n/2), yếu tố khôn ngoan


Toán học, 101 byte

(-1)^#⌈#/2⌉&@Nest[{a=#~IntegerExponent~2+1,#/2^a+1/2}~Join~{##2}&@@#&,{2Abs@#+Boole[#<=0]},#2-1]&

Tương tự như trên (sử dụng N thay vì N0), nhưng sử dụng nghịch đảo của bijection f: N ^ 2 -> N thông qua f(a, b) = 2^(a - 1)(2b - 1)


Ý bạn là ... không có Mathicala tích hợp sẵn cho điều đó (khi Alice có)? Tôi không nói nên lời.
JayCe

1

JavaScript, 112 byte

k=>x=>(r=Array(k).fill(''),[...`${x<0?2*~x+1:2*x}`].map((c,i,s)=>r[(s.length-i)%k]+=c),r.map(v=>v&1?~(v/2):v/2))
  1. chuyển đổi sang không âm
  2. (n * k + i) chữ số thứ i đến số thứ i
  3. chuyển đổi trở lại

@HermanLauenstein không cần quay lại?
tsh

Tôi nghĩ x<0?~x-x:x+xtiết kiệm 2 byte.
Neil

-5 byte bằng cách sử dụng [...BT${x<0?~x-x:x+x}BT].reverse().map((c,i)=>r[i%k]+=c),(ghi có vào @Neil cho x<0?~x-x:x+x). .reverse()được sử dụng thay (s.length-i)vì nó tránh sự cần thiết của tham số thêm svào đầu tiên .map. Không cần phải đảo ngược vì mảng tạm thời không được sử dụng lại. (Tôi chưa thử nghiệm nhưng có lẽ nó sẽ hoạt động)
Herman L

Một byte khác có thể được lưu bằng cách thay thế .fill('')bằng .fill(0), vì số 0 đứng đầu không tạo ra sự khác biệt (ít nhất là không khi được thử nghiệm trong Safari)
Herman L

@HermanLauenstein Bạn đã thử .fill`` chưa? Nó có thể tiết kiệm một vài byte.
Neil


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.