Ceylon / Ceylon, 49,86 40,95 điểm
Phiên bản thứ ba sử dụng Ceylon 1.2 cho trình tạo và 509 byte mã:
import ceylon.language{S=String,I=Integer,e=expand}S q(I n)=>n==0then"0"else(n<0then"-"+p(-n,"-")else p(n,"+"));variable Map<[I,S],S>c=map{};S p(I n,S s){S v=c[[n,s]]else(n<8then s.join([1].repeat(n)))else(let(a="+-".replace(s,""))e(e{for(x in 2..8)let(l=(n^(1.0/x)).integer){for(r in l:2)if(r>1)let(w=r^x){if(w-n<n)"("+p(r,"+")+")^("+p(x,"+")+")"+(w<n then s+p(n-w,s)else(n<w then a+p(w-n,a)else""))}}}).reduce<S>((x,y)=>x.size<y.size then x else y))else"";c=[n,s]in c then c else map{[n,s]->v,*c};return v;}
Nó giảm xuống còn 35,22 điểm, nhưng tôi sẽ không đặt nó trong dòng tiêu đề vì Celyon 1.2 chỉ được xuất bản vào ngày 29 tháng 10. Tôi không nghĩ rằng tôi có thể thực hiện thuật toán này trong Ceylon 1.1 ở kích thước này.). Thêm chi tiết ở dưới đó, ở đây tôi sẽ mô tả phiên bản thứ hai. (Phiên bản đầu tiên có thể được nhìn thấy trong lịch sử - nó chỉ hỗ trợ các số dương, nhưng phù hợp với 256 byte.)
Phiên bản thứ hai
Bây giờ là phiên bản thứ hai, hỗ trợ các số nguyên âm (và 0), và thường tạo ra đầu ra ngắn hơn một chút bằng cách sử dụng thêm -
. (Phiên bản này thực sự sử dụng độ dài cho phép, phiên bản đầu tiên đã cố gắng ở dưới 256 byte thay vì 512.)
String proof(Integer n) {
if (n == 0) { return "0"; }
if (n < 0) { return "-" + p(-n, "-"); }
return p(n, "+");
}
String p(Integer n, String sign) {
if (n < 9) {
return sign.join([1].repeat(n));
}
value anti = (sign == "+") then "-" else "+";
value root = ((n^0.5) + 0.5).integer;
return "(" + p(root, "+") + ")^(1+1)" +
( (root^2 < n) then sign + p(n - root^2, sign) else
((n < root^2) then anti + p(root^2 - n, anti) else ""));
}
Mã có độ dài 487, vì vậy vẫn còn một số không gian để tối ưu hóa hơn sau này. (Ngoài ra còn có rất nhiều dự trữ dưới dạng khoảng trắng và tên biến dài.)
Điểm số:
Total positive: 42652
Average positive:42.652
Total negative: 43653
Average negative: 43.60939060939061
With bonus:39.24845154845155
Overall score: 40.95022577422577
Một số kết quả đầu ra mẫu:
27: 21: (1+1+1+1+1)^(1+1)+1+1
28: 23: (1+1+1+1+1)^(1+1)+1+1+1
29: 25: (1+1+1+1+1)^(1+1)+1+1+1+1
30: 27: (1+1+1+1+1)^(1+1)+1+1+1+1+1
31: 29: (1+1+1+1+1+1)^(1+1)-1-1-1-1-1
32: 27: (1+1+1+1+1+1)^(1+1)-1-1-1-1
33: 25: (1+1+1+1+1+1)^(1+1)-1-1-1
34: 23: (1+1+1+1+1+1)^(1+1)-1-1
-27: 22: -(1+1+1+1+1)^(1+1)-1-1
-28: 24: -(1+1+1+1+1)^(1+1)-1-1-1
-29: 26: -(1+1+1+1+1)^(1+1)-1-1-1-1
-30: 28: -(1+1+1+1+1)^(1+1)-1-1-1-1-1
-31: 30: -(1+1+1+1+1+1)^(1+1)+1+1+1+1+1
-32: 28: -(1+1+1+1+1+1)^(1+1)+1+1+1+1
-33: 26: -(1+1+1+1+1+1)^(1+1)+1+1+1
-34: 24: -(1+1+1+1+1+1)^(1+1)+1+1
993: 65: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1+1)^(1+1)+1+1+1+1+1
994: 63: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)-1-1-1-1-1
995: 61: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)-1-1-1-1
996: 59: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)-1-1-1
997: 57: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)-1-1
998: 55: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)-1
999: 53: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)
1000: 55: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)+1
-993: 66: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1+1)^(1+1)-1-1-1-1-1
-994: 64: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1)^(1+1)+1+1+1+1+1
-995: 62: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1)^(1+1)+1+1+1+1
-996: 60: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1)^(1+1)+1+1+1
-997: 58: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1)^(1+1)+1+1
-998: 56: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1)^(1+1)+1
-999: 54: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1)^(1+1)
-1000: 56: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1)^(1+1)-1
1: 1: 1
2: 3: 1+1
3: 5: 1+1+1
4: 7: 1+1+1+1
5: 9: 1+1+1+1+1
6: 11: 1+1+1+1+1+1
7: 13: 1+1+1+1+1+1+1
8: 15: 1+1+1+1+1+1+1+1
9: 13: (1+1+1)^(1+1)
10: 15: (1+1+1)^(1+1)+1
0: 1: 0
-1: 2: -1
-2: 4: -1-1
-3: 6: -1-1-1
-4: 8: -1-1-1-1
-5: 10: -1-1-1-1-1
-6: 12: -1-1-1-1-1-1
-7: 14: -1-1-1-1-1-1-1
-8: 16: -1-1-1-1-1-1-1-1
-9: 14: -(1+1+1)^(1+1)
-10: 16: -(1+1+1)^(1+1)-1
Như bạn có thể thấy, những cái tiêu cực luôn -
dài hơn một byte (hàng đầu ) so với những cái tích cực tương ứng.
Ý tưởng cơ bản giống như chương trình trước: tìm một hình vuông gần số mục tiêu của chúng tôi và đại diện cho gốc của nó và phần còn lại theo cách đệ quy. Nhưng bây giờ chúng tôi cho phép hình vuông của chúng tôi cũng lớn hơn số mục tiêu, sau đó làm cho phần còn lại âm. (Có +0.5
thể thay đổi thành một hằng số khác để điều chỉnh thuật toán, nhưng có vẻ như tôi đã đạt được mức tối ưu ở đây - cả 0,4 và 0,6 đều cho kết quả tồi tệ hơn.)
Để làm cho các giá trị âm trở thành âm (và mặt khác có cùng cấu trúc với các giá trị dương, chúng ta chuyển toán tử sign
cho hàm đệ quy p
- đó là "+"
hoặc"-"
. Chúng ta có thể sử dụng nó cho hàm nối trong các trường hợp tầm thường (ví dụ n <9) đối với phần còn lại nếu nó dương tính và sử dụng dấu ngược lại cho phần còn lại nếu nó âm tính.
Các proof
xử lý chức năng là dấu hiệu ban đầu (với một trường hợp đặc biệt cho 0), các p
chức năng thực hiện công việc thực tế, với đệ quy.
Phiên bản thứ ba, cho Ceylon 1.2
import ceylon.language { S=String, I=Integer,e=expand }
// output a base-proof Ceylon expression for an integer
// (i.e. using only 0 and 1 as digits).
//
// Question: http://codegolf.stackexchange.com/q/58084/2338
// My Answer: http://codegolf.stackexchange.com/a/58122/2338
//
// The goal is to produce an expression as short as possible, with
// the code staying under 512 bytes in length.
//
// This approach is to represent a positive integer as a square
// of a positive integer plus some remainder (where the remainder
// can be negative), and for negative integers replace the + on the
// outer level by -.
S q(I n) =>
n == 0 then "0"
else (n < 0 then "-" + p(-n, "-")
else p(n, "+"));
// cache for values of p
variable Map<[I, S],S> c = map { };
// Transforms a positive number into a base-proof term, using
// the given sign for the summation on the outer level.
S p(I n, S s) {
S v =
// look into the cache
c[[n, s]] else (
// hard-code small numbers
n < 8 then s.join([1].repeat(n)))
else
// do the complicated stuff
(let (a = "+-".replace(s,""))
e(e {
for (x in 2..8) // try these exponents
let (l = (n ^ (1.0 / x)).integer) // \[ sqrt[exp]{n} \] in LaTeX
{ for (r in l:2) // lowerRoot, lowerRoot + 1
if (r > 1)
let (w = r ^ x)
{ if (w-n < n) // avoid recursion to larger or same number
// format the string as r^x + (n-w)
"(" + p(r, "+") + ")^(" + p(x, "+") + ")" +
(w < n then s + p(n - w, s)
else (n < w then a + p(w - n, a)
else ""))
} } })
// and now find the shortest formatted string
.reduce<S>((x, y) => x.size < y.size then x else y))
// this should never happen, but we can't tell the compiler
// that at least some of the iterables are non-empty due to the if clause.
else "";
// this builds a new cache in each step – quite wasteful,
// as this also happens when the value was found in the cache,
// but we don't have more characters remaining.
//// c = map { [n, s] -> v, *c };
///better way:
c = [n,s] in c then c else map{[n,s]->v, *c};
return v;
}
Phiên bản được đánh gôn (nghĩa là bình luận và khoảng trắng bị xóa) được đăng ở trên cùng, với chính xác 509 byte mã.
Điều này sử dụng nguyên tắc cơ bản giống như phiên bản thứ hai, nhưng thay vì chỉ là hình vuông, nó cũng cố gắng sử dụng số lũy thừa cao hơn (thử số mũ từ 2 đến 8) và sử dụng kết quả ngắn nhất. Nó cũng lưu trữ kết quả, vì nếu không, điều này sẽ chậm đến mức không thể chấp nhận được đối với các số lớn hơn với nhiều cuộc gọi đệ quy.
Ghi điểm:
Total positive: 36622
Average positive: 36.622
Total negative: 37623
Average negative: 37.58541458541458
With bonus:33.826873126873124
Overall score: 35.22443656343656
Cấu trúc thụt lề lớn ở giữa là ba cách hiểu lặp lại lồng nhau, hai bên trong bên trong một biểu thức let. Chúng sau đó không được kiểm tra bằng cách sử dụng hàm mở rộng hai lần và reduce
hàm tìm thấy chuỗi ngắn nhất trong số các chuỗi đó.
Tôi đã gửi một yêu cầu tính năng để có thể thực hiện điều này trong một lần hiểu.
Bên trong sự hiểu biết, chúng tôi đang xây dựng một chuỗi từ gốc r
, số mũ x
và phần còn lại ( n-w
hoặc w-n
).
Các let
biểu hiện và các map
chức năng mới trong Ceylon 1.2. map
có thể đã được thay thế bằng HashMap
(cần thêm nhiều ký tự để nhập, mặc dù có thể sẽ nhanh hơn nữa, vì tôi sẽ không xây dựng bản đồ mới cho mỗi mục nhập mới). Các let
biểu thức như let (w = r ^ x)
có thể đã được thay thế bằng cách sử dụng một if
mệnh đề như if(exists w = true then r ^ x)
(và sau đó tôi sẽ không cần hai expand
cuộc gọi), nhưng điều này vẫn sẽ dài hơn một chút, không phù hợp với 511 byte được phép.
Ở đây, các đầu ra mẫu tương ứng với các đầu ra được chọn ở trên, tất cả chúng ngoại trừ các số thực sự nhỏ đều ngắn hơn:
27: 15: (1+1+1)^(1+1+1)
28: 17: (1+1+1)^(1+1+1)+1
29: 19: (1+1+1)^(1+1+1)+1+1
30: 21: (1+1)^(1+1+1+1+1)-1-1
31: 19: (1+1)^(1+1+1+1+1)-1
32: 17: (1+1)^(1+1+1+1+1)
33: 19: (1+1)^(1+1+1+1+1)+1
34: 21: (1+1)^(1+1+1+1+1)+1+1
-27: 16: -(1+1+1)^(1+1+1)
-28: 18: -(1+1+1)^(1+1+1)-1
-29: 20: -(1+1+1)^(1+1+1)-1-1
-30: 22: -(1+1)^(1+1+1+1+1)+1+1
-31: 20: -(1+1)^(1+1+1+1+1)+1
-32: 18: -(1+1)^(1+1+1+1+1)
-33: 20: -(1+1)^(1+1+1+1+1)-1
-34: 22: -(1+1)^(1+1+1+1+1)-1-1
993: 39: ((1+1+1)^(1+1)+1)^(1+1+1)-1-1-1-1-1-1-1
994: 37: ((1+1+1)^(1+1)+1)^(1+1+1)-1-1-1-1-1-1
995: 35: ((1+1+1)^(1+1)+1)^(1+1+1)-1-1-1-1-1
996: 33: ((1+1+1)^(1+1)+1)^(1+1+1)-1-1-1-1
997: 31: ((1+1+1)^(1+1)+1)^(1+1+1)-1-1-1
998: 29: ((1+1+1)^(1+1)+1)^(1+1+1)-1-1
999: 27: ((1+1+1)^(1+1)+1)^(1+1+1)-1
1000: 25: ((1+1+1)^(1+1)+1)^(1+1+1)
-993: 40: -((1+1+1)^(1+1)+1)^(1+1+1)+1+1+1+1+1+1+1
-994: 38: -((1+1+1)^(1+1)+1)^(1+1+1)+1+1+1+1+1+1
-995: 36: -((1+1+1)^(1+1)+1)^(1+1+1)+1+1+1+1+1
-996: 34: -((1+1+1)^(1+1)+1)^(1+1+1)+1+1+1+1
-997: 32: -((1+1+1)^(1+1)+1)^(1+1+1)+1+1+1
-998: 30: -((1+1+1)^(1+1)+1)^(1+1+1)+1+1
-999: 28: -((1+1+1)^(1+1)+1)^(1+1+1)+1
-1000: 26: -((1+1+1)^(1+1)+1)^(1+1+1)
1: 1: 1
2: 3: 1+1
3: 5: 1+1+1
4: 7: 1+1+1+1
5: 9: 1+1+1+1+1
6: 11: 1+1+1+1+1+1
7: 13: 1+1+1+1+1+1+1
8: 13: (1+1)^(1+1+1)
9: 13: (1+1+1)^(1+1)
10: 15: (1+1+1)^(1+1)+1
0: 1: 0
-1: 2: -1
-2: 4: -1-1
-3: 6: -1-1-1
-4: 8: -1-1-1-1
-5: 10: -1-1-1-1-1
-6: 12: -1-1-1-1-1-1
-7: 14: -1-1-1-1-1-1-1
-8: 14: -(1+1)^(1+1+1)
-9: 14: -(1+1+1)^(1+1)
-10: 16: -(1+1+1)^(1+1)-1
Ví dụ: bây giờ chúng ta có 1000 = (3 ^ 2 + 1) ^ 3, thay vì 1000 = (6 ^ 2-4) ^ 2-5 ^ 2 + 1.
0
hoặc1
theo mặc định không?