ประเทศศรีลังกา / ศรีลังกา 49.86 40.95 คะแนน
รุ่นที่สามใช้ Ceylon 1.2 สำหรับเครื่องกำเนิดไฟฟ้าและรหัส 509 ไบต์:
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;}
มันลดลงเหลือ 35.22 จุด แต่ฉันจะไม่ใส่มันในบรรทัดหัวเรื่องเพราะ Celyon 1.2 เท่านั้นที่เผยแพร่ในเดือนตุลาคม 29 ฉันไม่คิดว่าฉันจะสามารถใช้อัลกอริทึมนี้ใน Ceylon 1.1 ในขนาดนี้ได้) รายละเอียดเพิ่มเติมที่นี่ฉันจะอธิบายรุ่นที่สอง (รุ่นแรกสามารถเห็นได้ในประวัติศาสตร์ - รองรับเฉพาะตัวเลขบวก แต่มีขนาดพอดีกับ 256 ไบต์)
รุ่นที่สอง
ตอนนี้รุ่นที่สองซึ่งสนับสนุนจำนวนเต็มลบ (0) -
และโดยทั่วไปจะสร้างผลผลิตบิตสั้นโดยใช้นอกเหนือ (รุ่นนี้ใช้ความยาวที่ได้รับอนุญาตจริงคนแรกพยายามอยู่ภายใต้ 256 ไบต์แทน 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 ""));
}
รหัสมีความยาว 487 ดังนั้นจึงมีพื้นที่เหลือสำหรับการปรับแต่งเพิ่มเติมในภายหลัง (นอกจากนี้ยังมีปริมาณสำรองในรูปแบบของช่องว่างและชื่อตัวแปรแบบยาว)
คะแนน:
Total positive: 42652
Average positive:42.652
Total negative: 43653
Average negative: 43.60939060939061
With bonus:39.24845154845155
Overall score: 40.95022577422577
ตัวอย่างผลลัพธ์บางส่วน:
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
อย่างที่คุณเห็นว่าค่าลบนั้นเป็นหนึ่งไบต์ (นำหน้า-
) นานกว่าค่าบวกที่สอดคล้องกันเสมอ
แนวคิดพื้นฐานเหมือนกับโปรแกรมก่อนหน้า: ค้นหาสี่เหลี่ยมจัตุรัสใกล้กับจำนวนเป้าหมายของเราและแสดงถึงรากและส่วนที่เหลือซ้ำ แต่ตอนนี้เราอนุญาตให้สแควร์ของเรามีขนาดใหญ่กว่าจำนวนเป้าหมายซึ่งทำให้ส่วนที่เหลือเป็นลบ ( +0.5
สามารถเปลี่ยนเป็นค่าคงที่ที่แตกต่างกันเพื่อปรับแต่งอัลกอริทึม แต่ดูเหมือนว่าฉันได้ตีที่เหมาะสมแล้วที่นี่ - ทั้ง 0.4 และ 0.6 ให้ผลลัพธ์ที่แย่ลง)
ในการทำให้ค่าลบเป็นลบ (และมีโครงสร้างเดียวกันกับค่าบวกเราจะส่งโอเปอเรเตอร์sign
ไปยังฟังก์ชันเวียนเกิดp
- นั่นคือ"+"
หรือ"-"
เราสามารถใช้มันสำหรับผู้เข้าร่วมในกรณีเล็ก ๆ น้อย ๆ (เช่น n <9) สำหรับส่วนที่เหลือถ้ามันเป็นบวกและใช้เครื่องหมายตรงข้ามสำหรับส่วนที่เหลือถ้ามันเป็นลบ
proof
ฟังก์ชั่นจับสัญญาณเริ่มต้น (กับกรณีพิเศษ 0) ที่p
ฟังก์ชั่นไม่ทำงานจริงกับการเรียกซ้ำ
รุ่นที่สามสำหรับ 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;
}
รุ่น golfed (เช่นความคิดเห็นและลบช่องว่าง) ถูกโพสต์ที่ด้านบนที่รหัส 509 ไบต์
สิ่งนี้ใช้หลักการพื้นฐานเดียวกับเวอร์ชั่นที่สอง แต่แทนที่จะใช้กำลังสองมันจะพยายามใช้กำลังของตัวเลขที่สูงขึ้น (ลองเลขชี้กำลังจาก 2 เป็น 8) และใช้ผลลัพธ์ที่สั้นที่สุด นอกจากนี้ยังเก็บผลลัพธ์เช่นกันเพราะจะทำให้ช้าลงสำหรับหมายเลขที่ใหญ่กว่าด้วยการโทรซ้ำหลายครั้ง
เกณฑ์การให้คะแนน:
Total positive: 36622
Average positive: 36.622
Total negative: 37623
Average negative: 37.58541458541458
With bonus:33.826873126873124
Overall score: 35.22443656343656
โครงสร้างเยื้องขนาดใหญ่ที่อยู่ตรงกลางคือความเข้าใจที่ซ้ำซ้อนสามระดับซ้อนกันและสองชั้นภายในที่อยู่ในนิพจน์ให้ สิ่งเหล่านี้จะไม่ถูกรบกวนโดยใช้ฟังก์ชัน expand สองครั้งและreduce
ฟังก์ชันจะค้นหาสตริงที่สั้นที่สุด
ฉันได้ส่งคำขอคุณสมบัติเพื่อให้สามารถทำสิ่งนี้ได้ในความเข้าใจเดียว
ภายในความเข้าใจเรากำลังสร้างสตริงจากรากr
เลขชี้กำลังx
และส่วนที่เหลือ ( n-w
หรือw-n
)
การlet
แสดงออกและmap
ฟังก์ชั่นใหม่ใน Ceylon 1.2 map
อาจถูกแทนที่ด้วยHashMap
(ซึ่งจะต้องมีอักขระมากขึ้นสำหรับการนำเข้าแม้ว่ามันอาจจะเร็วกว่านี้เพราะฉันจะไม่สร้างแผนที่ใหม่สำหรับแต่ละรายการใหม่) การlet
แสดงออกเช่นlet (w = r ^ x)
นี้อาจถูกแทนที่โดยใช้if
ประโยคเช่นif(exists w = true then r ^ x)
(แล้วฉันก็ไม่ต้องการทั้งสองexpand
สาย) แต่นี่จะยังคงนานกว่านี้เล็กน้อยไม่เหมาะกับไบต์ที่อนุญาต 511
ตัวอย่างผลลัพธ์ที่ตรงกับที่เลือกไว้ด้านบนทั้งหมดทั้งหมดยกเว้นจำนวนน้อยจริง ๆ จะสั้นกว่า:
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
ตัวอย่างเช่นตอนนี้เรามี 1,000 = (3 ^ 2 + 1) ^ 3 แทน 1,000 = (6 ^ 2-4) ^ 2-5 ^ 2 + 1
0
หรือ1
โดยค่าเริ่มต้นได้หรือไม่