แสดงตัวเลขที่มีเพียง 0-9 และสี่การดำเนินการ


14

คำอธิบาย

Befungeเป็นโปรแกรมที่สองมิติที่ใช้สแต็ค

นั่นหมายความว่าในการทำ 5 + 6 คุณเขียน56+ความหมาย:

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)

อย่างไรก็ตามตามความฉลาดของคุณสังเกตเราไม่สามารถกดหมายเลข56ลงในสแต็กโดยตรง

ต้องการทำเช่นนั้นเราจะต้องเขียน78*แทนซึ่งคูณ7และ8และผลักดันสินค้าเข้ามาในสแต็ค

รายละเอียด

อินพุตสามารถถ่ายในรูปแบบใดก็ได้ซึ่งหมายความว่าสามารถเป็น STDIN หรือไม่ก็ได้ขึ้นอยู่กับดุลยพินิจของโปรแกรมเมอร์

อินพุตจะเป็นจำนวนเต็มบวก (ไม่มีโบนัสสำหรับการรวม0หรือจำนวนเต็มลบ)

ผลลัพธ์จะเป็นสตริงที่ประกอบด้วยอักขระเหล่านี้เท่านั้น: 0123456789+-*/(ฉันจะไม่ใช้% modulo)

เป้าหมายคือการค้นหาสตริงที่สั้นที่สุดที่สามารถเป็นตัวแทนของอินพุตโดยใช้รูปแบบที่อธิบายไว้ข้างต้น

ตัวอย่างเช่นถ้าใส่เป็นแล้วออกจะเป็น123 67*99*+เอาต์พุตควรถูกประเมินจากซ้ายไปขวา

หากมีมากกว่าหนึ่งผลงานที่ยอมรับได้ (เช่นยอมรับได้เช่นกัน99*67*+) สามารถพิมพ์ใด ๆ ก็ได้ (ไม่มีโบนัสสำหรับการพิมพ์ทั้งหมด)

คำอธิบายเพิ่มเติม

หากคุณยังไม่เข้าใจว่า67*99*+จะประเมินอย่างไรต่อไป123นี้เป็นคำอธิบายโดยละเอียด

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

โปรแกรมต้องการค้นหาที่สั้นที่สุดสตริงที่ที่สามารถเป็นตัวแทนของอินพุต (ตัวเลข) โดยใช้รูปแบบที่ระบุข้างต้น

หมายเหตุ

นี่เป็นความท้าทายของการดังนั้นรหัสที่สั้นที่สุดในหน่วยไบต์จะชนะ

วิกิพีเดีย

-สามารถเป็นได้ทั้งx-yหรือy-xขึ้นอยู่กับดุลยพินิจของโปรแกรม อย่างไรก็ตามตัวเลือกต้องสอดคล้องกันภายในโซลูชัน /ในทำนองเดียวกันสำหรับ

โปรแกรมตัวอย่าง

Lua, 1862 ไบต์ ( ลองออนไลน์ )

ตั้งแต่ฉันเป็นผู้เขียนฉันจะไม่เล่นกอล์ฟเลย

คำอธิบาย:

This uses the depth-first search method.

เพิ่มเติมเกี่ยวกับความลึกแรกค้นหา: ที่นี่

โปรแกรม:

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

โบนัส

เค้กให้คุณถ้าคุณใช้Befunge (หรือตัวแปรอื่น ๆ ) เพื่อเขียนโค้ด


3
มันอาจจะยากที่จะตัดสินใจรับคำตอบถ้ามันมักจะก่อให้เกิดสตริงที่เรียงลำดับ แนวคิดหนึ่งก็คือการสร้างตัวเลขและคะแนนจำนวน 30--50 ชุดโดยผลรวมของความยาวสตริงผลลัพธ์ทั้งหมด อย่างไรก็ตามฉันไม่แน่ใจว่าจะรวมคะแนนนั้นกับความยาวรหัสได้อย่างไร
Luis Mendo

4
ระบบย่อยของนี้
Addison Crump

2
คัดลอกเหนือความคิดของฉันจากการแชท : "ฉันคิดถึงมัน แต่ฉันยืนยันว่าชุดย่อยทำให้สิ่งต่าง ๆ ง่ายขึ้นมากเพราะ 1) ไม่มีเลขฐานสิบหก 2) ไม่มีลอยตัว 3) ไม่มีการซ้ำซ้อนและ 4) บวกเท่านั้น"
Sp3000

1
@CoolestVeto อันนี้แตกต่างกันมากพอที่จะทำให้คำตอบเก่าใช้ไม่ได้
2559

1
@CoolestVeto ฉันคิดว่าความท้าทายอื่น ๆ ควรถูกปิดเป็นความซ้ำซ้อนของสิ่งนี้
mbomb007

คำตอบ:


4

Python 2, 278 ไบต์

ทางออกที่ดีที่สุดของฉันซึ่งทุกครั้งให้คำตอบที่สั้นที่สุด (แต่ช้ามาก)

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 ไบต์

วิธีนี้มีความยาวมากกว่า แต่เร็วมาก และฉันค่อนข้างแน่ใจว่าจะให้ผลลัพธ์ที่สั้นที่สุดเสมอ

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
ยินดีต้อนรับสู่PPCG ! หวังว่าคุณจะมีช่วงเวลาที่ดีที่นี่
Leun Nun

1
@ pbochinak ฉันคิดว่าฉันอาจจะพบที่ถูกต้อง f(6551)ผลตอบแทน25*8*9*7+9*8+(13 ตัวอักษร) ในขณะที่9999***52*-(11 ตัวอักษร) ดีกว่า ตรวจสอบกับevalฟังก์ชั่นของฉันเองด้านบน (ในคำถาม)
Leun Nun

4
@pbochniak ในฐานะที่เป็นความคิดเห็นก่อนที่ฉันจะชี้ให้เห็นคำตอบนี้ไม่ถูกต้องในสถานะปัจจุบัน ขอแนะนำให้ลบมันชั่วคราวในขณะที่คุณกำลังทำงานกับการแก้ไข (ถ้าไม่มีอะไรอื่นเพื่อป้องกันไม่ให้ดึงดูด downvotes)
Dennis

1
ในขณะที่คุณสามารถwhile c:
Ven

คุณสามารถใช้;เพื่อแยกการมอบหมายให้กับตัวแปร (ซึ่งจะช่วยประหยัดไบต์ในบล็อกที่เว้าแหว่ง), เคล็ดลับของ ven, กำจัดช่องว่างระหว่างสัญลักษณ์และสิ่งอื่นใดและtสามารถไปได้
CalculatorFeline

4

Perl, 134 133 132 128 ไบต์

รวม +5 สำหรับ-Xlp(เพิ่มอีก 2 เพราะรหัสประกอบด้วย')

ทำงานด้วยหมายเลขเป้าหมายใน 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{$_}}{

มันไม่มีข้อ จำกัด ด้านการประดิษฐ์และมีแนวคิดค่อนข้างมีประสิทธิภาพ แต่ก็มีช่วงเวลาที่แย่มากแม้ว่าฉันจะเสียสละสักสองสามไบต์เพื่อเร่งความเร็ว การสร้างโซลูชันความยาว 11 (เช่นหมายเลขเป้าหมาย 6551) ใช้เวลาประมาณ 5 ชั่วโมงในระบบของฉัน

การเสียสละเพิ่มอีก 7 ไบต์ทำให้สามารถรับความเร็วได้ค่อนข้างมาก

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

17 นาทีสำหรับการแก้ปัญหาความยาว 11, ประมาณ 5 ชั่วโมงสำหรับการแก้ปัญหาความยาว 13 หมายเลขแรกที่ต้องการความยาว 15 คือ 16622 ซึ่งใช้เวลาประมาณ 2 วัน หมายเลขแรกที่ต้องการความยาว 17 คือ 73319

ให้สังเกตุว่าสมมติว่าการหารส่งคืนเลขจำนวนเต็มโดยการตัดเหลือ 0 (ตามข้อกำหนดของ befunge 93)


เครื่องหมายดอลลาร์ทำอะไร? (ฉันไม่พูดภาษา Perl เลย)
Leun Nun

1
@KennyLau $เข้าถึงค่าสเกลาร์ ที่ไหนในภาษาส่วนใหญ่คุณจะเขียนa=4, Perl $a=4จะใช้ แต่ยังใช้สำหรับการเข้าถึงสเกลาร์ของตัวแปรที่ซับซ้อนมากขึ้น เช่นการ$a{$b}ดึงข้อมูลจากแฮช (แผนที่พจนานุกรม) %aค่าสเกลาร์ที่คีย์$b
Ton Hospel

2

C, 550 545 ไบต์

#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 ไบต์หลังจากลบบรรทัดใหม่ที่ไม่จำเป็น (ทั้งหมดยกเว้นสามบรรทัดใหม่หลังจากคำสั่งประมวลผลล่วงหน้า)

@ Kenny Lau - มันสามารถรับเป็นอินพุตเป็นจำนวนเต็มระหว่าง 1 ถึง 9998 แต่ฉันคิดว่าช่วงของอินพุตที่คำนวณคำตอบที่ดีที่สุดนั้นมีขนาดเล็กกว่า 9998 ในทางกลับกันทั้งสองช่วงสามารถขยายได้ถ้าหน่วยความจำ อนุญาตให้มัน

โปรแกรมไม่สามารถดันลงในสแต็กใด ๆ ที่มีจำนวนสูงกว่า 9998 ได้ (9998 สามารถแก้ไขได้) ฉันรันโปรแกรมในเวอร์ชันอื่นแล้ววนซ้ำลูปรอบนอก (อันที่มี k) ตราบใดที่มีการปรับปรุงหมายเลขใด ๆ ระหว่าง 1 ถึง 9998 (ตามอัลกอริธึมของ Dijkstra) หลังจากการทำซ้ำสามครั้งไม่มีการปรับปรุง ดังนั้นเพื่อประหยัดไบต์ฉันฮาร์ดโค้ด k = 3

ในการขยายขอบเขตจำเป็นต้องใช้สองสิ่ง - แก้ไขค่าคงที่ 9999 และ 9998 เรียกใช้ด้วยการวนซ้ำของตัวแปรในลูป outter ตราบเท่าที่มีการปรับปรุงเพื่อดูว่าต้องใช้เวลานานเท่าใดจนกว่าจะไม่มีการแก้ไข ปรับเปลี่ยนค่าคงที่ k = 3 ให้เป็นค่านั้น


ยินดีต้อนรับสู่PPCG ! หวังว่าคุณจะมีช่วงเวลาที่ดีที่นี่
Leun Nun

นี่ผ่านการทดสอบ 6551 ของฉันอย่างสมบูรณ์แบบ ช่วงที่มีประสิทธิภาพของโปรแกรมนี้คืออะไร?
Leun Nun

ฉันเชื่อว่ามันคือ 9999 คุณช่วยเพิ่มข้อมูลนี้ในโซลูชันของคุณได้ไหม
Leun Nun

มันควรจะเป็น 9998. นอกจากนี้คุณยังสามารถที่จะกินไบต์บางส่วนโดยการเริ่มต้นi, jและก่อนที่จะk main()
Leun Nun

1
@Kenny Lau - ขอบคุณสำหรับการแก้ไข เกี่ยวกับการขยายช่วงฉันสังเกตว่าจริง ๆ แล้วมันใช้เวลาเพิ่มอีกหน่อยในการขยายช่วง ฉันรวมข้อมูลนั้นไว้ในคำตอบ
mIllIbyte

2

Python 2, 284 ไบต์

คำเตือน: ใช้เวลาชั่วครู่ตลอดไปสำหรับค่าบางอย่าง ... แต่ควรรับประกันว่าจะส่งคืนสตริงที่สั้นที่สุดเสมอและไม่มีการ จำกัด ช่วงที่กำหนดไว้ ... แม้จะใช้กับค่าลบ :)

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

ขั้นตอนวิธีการ:

  • เริ่มกับ i = 0
  • รับสตริงแทนค่าฐานสิบหกของiและแทนที่abcdด้วย+-*/ตามลำดับและลบใด ๆef
  • พยายามประมวลผลสตริงเป็นเครื่องหมาย postfix (RPN)
  • หากสำเร็จและผลลัพธ์ตรงกับค่าอินพุตให้ส่งคืนสตริงที่ใช้
  • มิฉะนั้นเพิ่มiและลองอีกครั้ง

"[t] akes [... ] ตลอดไปสำหรับค่าบางอย่าง" คุณเคยทดสอบหรือยัง? ค่าอะไร?
Leun Nun

@KennyLau ฉันเพิ่งเขียนการทดสอบที่คำนวณf(i)จาก0 <= i <= 6551(เพื่อจับ6551ค่าที่คุณใช้ในการทำให้การส่งต้นฉบับดั้งเดิมของ @pbochniak เป็นโมฆะ) ตอนนี้มันใช้งานได้เพียงไม่กี่นาทีและนี่เป็นผลลัพธ์สุดท้ายจากการทดสอบ: 91 : 49+7* 3.020 s (total 108.174 s, worst 89: 5.827 s) อัปเดต - เพิ่งเสร็จสิ้นด้วยค่า 92: 92 : 149+7*+ 258.761 s (total 366.935 s, worst 92: 258.761 s)
Ken 'Joey' Mosher

@KennyLau: การทดสอบใช้เวลานานกว่าหนึ่งชั่วโมงและมีมูลค่ามากขึ้น113... ดูผลการทดสอบเต็มรูปแบบได้ที่นี่ (pastebin)หากคุณสนใจ ...
Ken 'Joey' Mosher

2

Python 2, 182 ไบต์

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

ช้ามากอย่างหยาบคายฉันปล่อยให้มันรันเป็นเวลาหนึ่งชั่วโมงสำหรับอินพุต221และมันก็ยังไม่สิ้นสุด ความเชื่องช้าอย่างมากก็เพราะฉันใช้รายการเป็นคิวสำหรับการค้นหาที่กว้างเป็นอันดับแรกและ.pop(0)เป็นO(n)สำหรับรายการ

L เป็นเพียงคิวที่บรรจุ (stack, code to reach stack)คู่ ในแต่ละขั้นตอนจะมีการเพิ่มตัวเลขเสมอและตัวดำเนินการจะดำเนินการถ้าสแต็กมีองค์ประกอบอย่างน้อยสององค์ประกอบ การหารจะดำเนินการเฉพาะในกรณีที่องค์ประกอบสุดท้ายไม่ใช่ 0 แม้ว่าฉันจะมีความสงสัยอย่างมากว่าการแบ่งนั้นไม่จำเป็น (แม้ว่าฉันจะไม่มีวิธีพิสูจน์ได้

โปรแกรมจะยกเลิกผ่านทาง NameErrorหลังจากพิมพ์ผลลัพธ์ (ในที่สุด)


คืออะไร;Eที่ปลายทำ?
Leun Nun

@KennyLau นั่นคือการNameErrorยกเลิกเนื่องจากEไม่มีการกำหนดไว้ที่อื่น
Sp3000

ว้าวความฉลาดเช่นนี้
Leun Nun

1

CJam, 79

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

ลองออนไลน์

สิ่งนี้ไม่มีประสิทธิภาพอย่างน่ากลัว แต่เมื่อได้รับความทรงจำและเวลาเพียงพอแล้ว 123 หน่วยความจำไม่เพียงพอที่มี 16GB แต่ 120 และ 125 ก็โอเค


1

Pyth - 35 ไบต์

กำลังดุร้าย. สิ่งที่แปลกก็คือการป้อนข้อมูลโดยนัยใหม่ทำให้ฉันเจ็บจริง ๆเพราะดูเหมือนว่าจะทำงานให้กับ.vpyth_eval ด้วย

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

ลองมันออนไลน์ได้ที่นี่


0

Python 3, 183 ไบต์

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

ความเร็วไม่สมเหตุสมผลอย่างสมบูรณ์ (123, 221, 1237, 6551 ให้เสร็จตามลำดับวินาทีหรือนาที) การเปลี่ยนifคำสั่งเพื่อif j<=i and <k<2*nเพิ่มความเร็วมากขึ้นด้วยค่าใช้จ่ายอีก 9 ไบต์ ฉันออกจากการหาร ( /) เพราะฉันไม่เห็นว่ามันจะเป็นสิ่งจำเป็นได้อย่างไร


คำแนะนำ: จำเป็นต้องมีการหาร
Leun Nun
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.