Thể hiện một số chỉ với 0-9 và bốn thao tác


14

Giải trình

Befunge là một chương trình hai chiều sử dụng ngăn xếp .

Điều đó có nghĩa là, để làm 5 + 6, bạn viết 56+, có nghĩa là:

56+
5    push 5 into stack
 6   push 6 into stack
  +  pop the first two items in the stack and add them up, and push the result into stack

(to those of you who do not know stacks, "push" just means add and "pop" just means take off)

Tuy nhiên, như sự thông minh của bạn đã quan sát, chúng tôi không thể đẩy số 56trực tiếp vào ngăn xếp.

Để làm như vậy, chúng ta phải viết 78*thay vào đó, mà nhân lên 78và đẩy sản phẩm vào ngăn xếp.

Chi tiết

Đầu vào có thể được thực hiện ở bất kỳ định dạng nào, có nghĩa là nó có thể là STDIN hoặc không, theo quyết định của lập trình viên.

Đầu vào sẽ là một số nguyên dương (không có phần thưởng cho bao gồm 0hoặc số nguyên âm).

Đầu ra sẽ là một chuỗi chỉ bao gồm các ký tự sau: 0123456789+-*/(Tôi sẽ không sử dụng %modulo.)

Mục tiêu là tìm chuỗi ngắn nhất có thể đại diện cho đầu vào, sử dụng định dạng được mô tả ở trên.

Ví dụ, nếu đầu vào là 123, thì đầu ra sẽ là 67*99*+. Đầu ra nên được đánh giá từ trái sang phải.

Nếu có nhiều hơn một đầu ra có thể chấp nhận (ví dụ: 99*67*+cũng được chấp nhận), bất kỳ đầu ra nào cũng có thể được in (không có phần thưởng cho việc in tất cả chúng).

Giải thích thêm

Nếu bạn vẫn không hiểu cách 67*99*+đánh giá 123, đây là một lời giải thích chi tiết.

stack    |operation|explanation
          67*99*+
[6]       6         push 6 to stack
[6,7]      7        push 7 to stack
[42]        *       pop two from stack and multiply, then put result to stack
[42,9]       9      push 9 to stack
[42,9,9]      9     push 9 to stack
[42,81]        *    pop two from stack and multiply, then put result to stack
[123]           +   pop two from stack and add, then put result to stack

TL; DR

Chương trình cần tìm chuỗi ngắn nhất có thể biểu thị đầu vào (số), sử dụng định dạng được chỉ định ở trên.

Ghi chú

Đây là một thử thách , vì vậy mã ngắn nhất tính bằng byte sẽ thắng.

Định hướng

-thể x-yhoặc y-x, theo ý của lập trình viên. Tuy nhiên, sự lựa chọn phải nhất quán trong giải pháp. Tương tự như vậy cho /.

Chương trình mẫu

Lua, 1862 byte ( thử trực tuyến )

Vì tôi là tác giả, tôi sẽ không chơi golf.

Giải trình:

This uses the depth-first search method.

Tìm hiểu thêm về tìm kiếm chuyên sâu: tại đây .

Chương trình:

local input = (...) or 81

local function div(a,b)
    if b == 0 then
        return "error"
    end
    local result = a/b
    if result > 0 then
        return math.floor(result)
    else
        return math.ceil(result)
    end
end

local function eval(expr)
    local stack = {}
    for i=1,#expr do
        local c = expr:sub(i,i)
        if c:match('[0-9]') then
            table.insert(stack, tonumber(c))
        else
            local a = table.remove(stack)
            local b = table.remove(stack)
            if a and b then
                if c == '+' then
                    table.insert(stack, a+b)
                elseif c == '-' then
                    table.insert(stack, b-a)
                elseif c == '*' then
                    table.insert(stack, a*b)
                elseif c == '/' then
                    local test = div(b,a)
                    if test == "error" then
                        return -1
                    else
                        table.insert(stack, a+b)
                    end
                end
            else
                return -1
            end
        end
    end
    return table.remove(stack) or -1
end

local samples, temp = {""}, {}

while true do
    temp = {}
    for i=1,#samples do
        local s = samples[i]
        table.insert(temp, s..'0')
        table.insert(temp, s..'1')
        table.insert(temp, s..'2')
        table.insert(temp, s..'3')
        table.insert(temp, s..'4')
        table.insert(temp, s..'5')
        table.insert(temp, s..'6')
        table.insert(temp, s..'7')
        table.insert(temp, s..'8')
        table.insert(temp, s..'9')
        table.insert(temp, s..'+')
        table.insert(temp, s..'-')
        table.insert(temp, s..'*')
        table.insert(temp, s..'/')
    end
    for i=1,#temp do
        if input == eval(temp[i]) then
            print(temp[i])
            return
        end
    end
    samples = temp
end

Tặng kem

Một chiếc bánh cho bạn nếu bạn sử dụng Befunge (hoặc bất kỳ biến thể nào của nó) để viết mã.


3
Có thể khó quyết định, đưa ra một câu trả lời, nếu nó luôn tạo ra chuỗi sắp xếp nhất. Một ý tưởng sẽ là tạo ra một tập hợp lớn gồm 30--50 số và ghi điểm bằng tổng tất cả độ dài chuỗi đầu ra. Tuy nhiên, tôi không chắc chắn cách kết hợp điểm số đó với độ dài mã
Luis Mendo

4
Tập hợp con này .
Addison Crump

2
Sao chép suy nghĩ của tôi từ trò chuyện : "Tôi đã nghĩ về nó nhưng tôi cho rằng tập hợp con làm mọi thứ đơn giản hơn nhiều vì 1) không hex, 2) không nổi, 3) không trùng lặp và 4) chỉ tích cực"
Sp3000

1
@CoolestVeto cái này đủ khác để làm mất hiệu lực các câu trả lời cũ.
R

1
@CoolestVeto Tôi nghĩ rằng thách thức khác nên được đóng lại như là một bản sao của thử thách này.
mbomb007

Câu trả lời:


4

Python 2, 278 byte

Giải pháp tốt nhất của tôi, mà mọi lúc mọi nơi cho câu trả lời ngắn nhất. (nhưng rất chậm)

def e(c):
 s=[];x,y=s.append,s.pop
 while c:
  d,c=c[0],c[1:]
  if"/"<d<":":x(d)
  else:a,b=y(),y();x(str(eval(b+d+a)))
 return int(y())
def g(v):
 s="0123456789+-*";t=list(s)
 while 1:
  for x in t:
   try:
    if e(x)==v:return x
   except:0
  t=[x+y for x in t for y in s]

Python 2, 437 byte

Giải pháp này dài hơn, nhưng rất nhanh (không phải vũ phu). Và tôi khá chắc chắn rằng nó luôn trả về kết quả ngắn nhất có thể.

r=range;l=len;a=input()
def f(n):
 if n<=9:return str(n)
 for d in r(9,1,-1):
  if n%d==0:return f(n/d)+"%d*"%d
 h=sum(map(int,list(str(n))))%9
 return f(n-h)+"%d+"%h
m={x:f(x) for x in r(a*9)}
for b in m:
 if a-b in m and l(m[b])+l(m[a-b])+1<l(m[a]):m[a]=m[a-b]+m[b]+"+"
 if a+b in m and l(m[b])+l(m[a+b])+1<l(m[a]):m[a]=m[a+b]+m[b]+"-"
 if b!=0 and a%b==0 and a/b in m and l(m[b])+l(m[a/b])+1<l(m[a]):m[a]=m[a/b]+m[b]+"*"
print m[a]

2
Chào mừng đến với PPCG ! Hy vọng bạn sẽ có một thời gian tuyệt vời ở đây.
Leaky Nun

1
@pbochinak Tôi nghĩ rằng tôi có thể đã tìm thấy một hợp lệ. f(6551)trả về 25*8*9*7+9*8+(13 ký tự), trong khi 9999***52*-(11 ký tự) là tốt hơn. Xác minh với evalchức năng của riêng tôi ở trên (trong câu hỏi).
Leaky Nun

4
@pbochniak Như nhận xét trước khi tôi chỉ ra, câu trả lời này không hợp lệ ở trạng thái hiện tại. Bạn nên tạm thời xóa nó trong khi bạn đang khắc phục sự cố (nếu không có gì khác, để ngăn chặn việc thu hút downvote).
Dennis

1
thời gian của bạn chỉ có thể làwhile c:
Ven

Bạn có thể sử dụng ;để phân tách các phép gán cho các biến (giúp lưu byte trong các khối thụt vào), mẹo của ven, thoát khỏi khoảng trắng giữa một biểu tượng và bất cứ thứ gì khác và tcó thể đi.
Máy

4

Perl, 134 133 132 128 byte

Bao gồm +5 cho -Xlp(thêm 2 vì mã chứa ')

Chạy với số mục tiêu trên STDIN:

perl -Xlp befour.pl <<< 123

befour.pl:

@1{1..9}=1..9;$.+=2,map{for$a(%1){"+-*/"=~s%.%"\$1{\$-=$a$&$_/'$1{$a}$1{$_}$&'=~/^.{$.}\$/}||=\$&"%eegr}}%1until$\=$1{$_}}{

Nó không có giới hạn nhân tạo và về mặt khái niệm có phần hiệu quả nhưng vẫn có thời gian chạy khủng khiếp mặc dù tôi đã hy sinh một vài byte để tăng tốc nó. Tạo một giải pháp dài 11 (ví dụ số mục tiêu 6551) mất khoảng 5 giờ trên hệ thống của tôi.

Hy sinh thêm 7 byte làm cho tốc độ có thể chịu đựng hơn.

@1{1..9}=1..9;$.+=2,map{for$a(@a){"+-*/"=~s%.%"\$1{\$-=$a$&$_/'$1{$a}$1{$_}$&'=~/^.{$.}\$/}||=\$&"%eegr}}@a=keys%1until$\=$1{$_}}{

17 phút cho một giải pháp dài 11, khoảng 5 giờ cho một giải pháp dài 13. Số đầu tiên cần độ dài 15 là 16622, mất khoảng 2 ngày. Số đầu tiên cần độ dài 17 là 73319.

Lưu ý rằng nó giả định rằng phép chia trả về một số nguyên bằng cách cắt về 0 (theo đặc tả befunge 93)


Những dấu hiệu đồng đô la làm gì? (Tôi hoàn toàn không nói Perl)
Leaky Nun

1
@KennyLau $truy cập giá trị vô hướng. Trường hợp trong hầu hết các ngôn ngữ bạn sẽ viết a=4, perl sẽ sử dụng $a=4. Nhưng cũng được sử dụng để truy cập vô hướng của các biến phức tạp hơn. Ví dụ: $a{$b}tìm nạp từ hàm băm (bản đồ, từ điển) %agiá trị vô hướng được khóa trên$b
TonMedel

2

C, 550 545 byte

#define L strlen
#define y strcpy
#define t strcat
char c[9999][99];i=1,k=3;main(j){for(;i<10;i++)*c[i]=i+'0';for(;k--;){
for(i=1;i<9999;i++)for(j=1;j<=i;j++)*c[i]&&*c[j]&&(i+j>9998||*c[i+j]&&
L(c[i+j])<L(c[i])+L(c[j])+2||t(t(y(c[i+j],c[i]),c[j]),"+"),
i*j>9998||*c[i*j]&&L(c[i*j])<L(c[i])+L(c[j])+2||t(t(y(c[i*j],c[i]),c[j]),"*"));
for(i=9999;--i;)for(j=i;--j;)*c[i]&&*c[j]&&(*c[i/j]&&
L(c[i/j])<L(c[i])+L(c[j])+2||t(t(y(c[i/j],c[i]),c[j]),"/"),
*c[i-j]&&L(c[i-j])<L(c[i])+L(c[j])+2||t(t(y(c[i-j],c[i]),c[j]),"-"));}
scanf("%d",&i);printf("%s",c[i]);}

550 545 byte sau khi xóa các dòng mới không cần thiết (tất cả trừ ba dòng mới sau các chỉ thị tiền xử lý).

@Kenny Lau - Nó có thể nhận là đầu vào một số nguyên trong khoảng từ 1 đến 9998, nhưng tôi nghĩ rằng phạm vi đầu vào mà giải pháp tối ưu được tính nhỏ hơn 9998. Mặt khác, cả hai phạm vi đều có thể được mở rộng, nếu bộ nhớ cho phép nó

Chương trình không thể đẩy lên ngăn xếp bất kỳ số nào cao hơn 9998. (9998 có thể được sửa đổi.) Tôi đã chạy chương trình trong một phiên bản khác, lặp lại vòng lặp bên ngoài (số có k) miễn là có cải thiện cho bất kỳ số nào từ 1 đến 9998 (như trong thuật toán của Dijkstra). Sau ba lần lặp lại không có cải thiện. Vì vậy, để tiết kiệm byte, tôi đã mã hóa k = 3.

Để mở rộng phạm vi, cần có hai điều - sửa đổi các hằng số 9999 và 9998, chạy nó với số lần lặp khác nhau qua vòng lặp bên ngoài miễn là có cải tiến, để xem mất bao lâu cho đến khi không có cải tiến, sau đó sửa đổi hằng số k = 3 thành giá trị đó.


Chào mừng đến với PPCG ! Hy vọng bạn sẽ có một thời gian tuyệt vời ở đây.
Leaky Nun

Điều này vượt qua bài kiểm tra 6551 của tôi một cách hoàn hảo. Phạm vi hiệu quả của chương trình này là gì?
Leaky Nun

Tôi tin rằng đó là 9999. Bạn có thể vui lòng thêm thông tin này vào giải pháp của mình không?
Leaky Nun

Nó phải là 9998. Ngoài ra, bạn có thể ăn một số byte bằng cách khởi tạo i, jktrước main().
Leaky Nun

1
@Kenny Lau - Cảm ơn bạn đã chỉnh sửa. Về việc mở rộng phạm vi, tôi nhận thấy rằng thực sự cần thêm một chút để mở rộng phạm vi. Tôi bao gồm thông tin đó trong câu trả lời.
mIllIbyte 30/03/2016

2

Python 2, 284 byte

Disclaimer: Đưa hoảng mãi mãi cho một số giá trị ... nhưng nên được đảm bảo để luôn luôn trả về chuỗi ngắn nhất, và đã áp đặt không nhân tạo giới hạn phạm vi ... thậm chí hoạt động trên các giá trị âm. :)

def f(v):
 i,z=0,'+-*/'
 while 1:
  s=('%x'%i).translate(__import__('string').maketrans('abcd',z),'ef');t=s;q=[];a,p=q.append,q.pop;i+=1
  try:
   while t:
    o,t=t[0],t[1:]
    if o in z:n,m=p(),p();a(eval(`m`+o+`n`))
    else:a(int(o))
   if p()==v and not q:return s
  except:pass

Thuật toán:

  • Bắt đầu với i = 0
  • Lấy chuỗi đại diện cho giá trị hex của ivà thay thế abcdbằng +-*/và loại bỏ bất kỳef
  • Cố gắng xử lý chuỗi dưới dạng ký hiệu hậu tố (RPN)
  • Nếu thành công và kết quả khớp với giá trị đầu vào, trả về chuỗi được sử dụng.
  • Nếu không, tăng ivà thử lại.

"[T] akes [...] mãi mãi cho một số giá trị" Bạn đã thử chưa? Giá trị gì?
Leaky Nun

@KennyLau tôi chỉ viết một bài kiểm tra đó là tính f(i)từ 0 <= i <= 6551(để nắm bắt những 6551giá trị mà bạn sử dụng để vô hiệu hóa @pbochniak 's nộp bản gốc). Ngay bây giờ, nó chỉ chạy được vài phút và đây là kết quả cuối cùng từ thử nghiệm: 91 : 49+7* 3.020 s (total 108.174 s, worst 89: 5.827 s) Cập nhật - nó vừa hoàn thành với giá trị 92: 92 : 149+7*+ 258.761 s (total 366.935 s, worst 92: 258.761 s)
Ken 'Joey' Mosher

@KennyLau: Thử nghiệm đã chạy được hơn một giờ và chỉ có giá trị 113... xem toàn bộ đầu ra thử nghiệm ở đây (pastebin) nếu bạn quan tâm ...
Ken 'Joey' Mosher

2

Python 2, 182 byte

n=input()
L=[[[],""]]
while 1:
 s,c=L.pop(0);L+=[[s+[i],c+`i`]for i in range(10)]+(s[1:]and[[s[:-2]+[eval(`s[-2]`+o+`s[-1]`)],c+o]for o in"/+-*"[s[-1]==0:]])
 if[n]==s[-1:]:print c;E

Quá chậm chạp, tôi đã để nó chạy trong một giờ với đầu vào 221và nó vẫn chưa kết thúc. Rất nhiều sự chậm chạp là bởi vì tôi đang sử dụng một danh sách như một hàng đợi cho tìm kiếm đầu tiên, và .pop(0)O(n) đối với danh sách.

Lchỉ là một hàng đợi chứa (stack, code to reach stack)các cặp. Ở mỗi bước, các chữ số luôn được thêm vào và các toán tử được thực hiện nếu ngăn xếp có ít nhất hai phần tử. Việc phân chia chỉ được thực hiện nếu phần tử cuối cùng không phải là 0, mặc dù tôi có một sự nghi ngờ mạnh mẽ rằng việc phân chia là không bao giờ cần thiết (mặc dù tôi không có cách nào để chứng minh điều đó, nhưng tôi đã kiểm tra đây là trường hợp lên tới 500).

Chương trình kết thúc thông qua một NameErrorsau khi in kết quả (cuối cùng).


Là những gì ;Ecuối cùng làm gì?
Leaky Nun

@KennyLau Đó là sự NameErrorchấm dứt, vì Ekhông được xác định ở bất kỳ nơi nào khác
Sp3000

Wow, sự thông minh như vậy.
Leaky Nun

1

CJam, 79

ri:M;A,:s:L;{L2m*{s,Y=},{~:A+AS*~!"/+-*">\f{\+}~}%Y2+:Y;_L@+:L;{S*~M=},:R!}gR0=

Dùng thử trực tuyến

Điều này là không hiệu quả khủng khiếp, nhưng được cung cấp đủ bộ nhớ và thời gian, cuối cùng nó hoạt động. 123 hết bộ nhớ với 16GB, nhưng 120 và 125 đều ổn.


1

Pyth - 35 byte

Lực lượng vũ phu. Một điều kỳ lạ là đầu vào ngầm mới thực sự làm tổn thương điểm số của tôi bởi vì nó dường như cũng đang hoạt động cho .vpyth_eval.

.V1IKfqQ.x.v+jd_T\;N^s+"+-*/"UTbhKB

Hãy thử trực tuyến tại đây .


0

Python 3, 183 byte

e,n=enumerate,input()
v=list('0123456789')+[' '*n]*n*2
for i,s in e(v):
 for j,t in e(v):
  for o,k in zip('+*-',(i+j,i*j,i-j)):
   if 9<k<2*n:v[k]=min(v[k],s+t+o,key=len)
print(v[n])

Tốc độ không hoàn toàn không hợp lý (123, 221, 1237, 6551 kết thúc theo thứ tự giây hoặc phút). Thay đổi ifcâu lệnh để tăng if j<=i and <k<2*ntốc nó hơn, với chi phí thêm 9 byte. Tôi rời khỏi bộ phận ( /), vì tôi không thể thấy nó cần thiết như thế nào.


Gợi ý: sự phân chia là cần thiết.
Nữ tu bị rò rỉ
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.