0-9와 4 개의 연산만으로 숫자를 표현하십시오.


14

설명

Befunge스택 을 사용하는 2 차원 프로그램입니다 .

즉, 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+-*/( 모듈로를 사용 하지 않습니다% .)

목표는 위에서 설명한 형식을 사용하여 입력을 표시 할 수있는 가장 짧은 문자열 을 찾는 것입니다 .

예를 들어, 입력이 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프로그래머의 재량에 따라. 그러나 솔루션 내에서 선택의 일관성이 있어야합니다. 마찬가지로 /.

샘플 프로그램

루아, 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) 16 진수, 2) 수레 없음, 3) 중복 및 4) 긍정적만으로 인해 하위 집합이 일을 훨씬 간단하게 만든다고 주장합니다.
Sp3000

1
@CoolestVeto 이것은 이전 답변을 무효화 할만 큼 다릅니다.
Rɪᴋᴇʀ

1
@CoolestVeto 다른 도전은 이것의 복제로 폐쇄되어야한다고 생각합니다.
mbomb007

답변:


4

파이썬 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]

파이썬 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에 오신 것을 환영합니다 ! 좋은 시간 보내시길 바랍니다.
Leaky Nun

1
@ pbochinak 유효한 것을 찾은 것 같습니다. (13 자)를 f(6551)반환 25*8*9*7+9*8+하지만 9999***52*-(11 자)가 더 좋습니다. eval위의 내 기능으로 확인되었습니다 (질문에서).
Leaky Nun

4
@pbochniak 내 지적 이전에 언급 했듯이이 답변은 현재 상태에서 유효하지 않습니다. 수정 작업을 수행하는 동안 일시적으로 삭제하는 것이 좋습니다.
Dennis

1
당신의 시간이 될 수 있습니다while c:
Ven

당신은 사용할 수 있습니다 ;,의 벤 팁 (들여 쓰기 블록의 바이트를 저장하는) 변수에 별도의 할당에 기호와 다른 것 사이의 공백을 없애, 그리고 t갈 수 있습니다.
CalculatorFeline

4

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{$_}}{

길이 11 용액의 ​​경우 17 분, 길이 13 용액의 경우 약 5 시간. 길이 15가 필요한 첫 번째 숫자는 16622이며 약 2 일이 걸립니다. 길이 17이 필요한 첫 번째 숫자는 73319입니다.

나누기가 0쪽으로 잘림으로써 정수를 반환한다고 가정합니다 (befunge 93 사양에 따라)


달러 표시는 무엇을합니까? (나는 전혀 Perl을 말하지 않는다)
Leaky Nun

1
@KennyLau $는 스칼라 값에 액세스합니다. 대부분의 언어로 쓰는 곳은 a=4perl이 사용 $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 바이트 (전처리 지시문 뒤의 세 줄 바꿈 제외).

@ 케니 라우-1에서 9998 사이의 정수를 입력으로 수신 할 수 있지만 최적의 솔루션이 계산되는 입력 범위는 9998보다 작다고 생각합니다. 반면에 메모리가 있으면 두 범위를 모두 확장 할 수 있습니다 허용합니다.

프로그램은 9998보다 큰 수를 스택에 넣을 수 없습니다. (9998은 수정할 수 있습니다.) 다른 버전에서 프로그램을 실행하여 수에 대한 개선이있는 한 외부 루프 (k가있는 것)를 반복합니다. 1에서 9998 사이 (Dijkstra의 알고리즘에서와 같이). 세 번의 반복 후에는 개선이 없습니다. 바이트를 절약하기 위해 k = 3을 하드 코딩했습니다.

범위를 확장하려면 두 가지가 필요합니다-상수 9999 및 9998을 수정하고 개선이있는 한 외부 루프에서 가변 반복 횟수로 실행하여 개선이 일어나지 않을 때까지 걸리는 시간을 확인한 다음 상수 k = 3을 해당 값으로 수정하십시오.


PPCG에 오신 것을 환영합니다 ! 좋은 시간 보내시길 바랍니다.
Leaky Nun

이것은 내 6551 테스트를 완벽하게 통과합니다. 이 프로그램의 효과적인 범위는 무엇입니까?
Leaky Nun

9999라고 생각합니다.이 정보를 솔루션에 추가 할 수 있습니까?
Leaky Nun

그것은 당신이 초기화하여 몇 바이트를 먹을 수있다, 또한 9998.해야한다 i, j그리고 k전에 main().
Leaky Nun

1
@ 케니 라우-편집 주셔서 감사합니다. 범위 확장에 대해 실제로 범위를 확장하는 데 약간의 시간이 더 걸린다는 것을 알았습니다. 나는 그 정보를 답에 포함시켰다.
mIllIbyte

2

파이썬 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
  • 의 16 진수 값을 나타내는 문자열을 가지고 i, 및 교체abcd+-*/ 각각 하고ef
  • 문자열을 다음과 같이 처리하려고 시도 후위 표기법 (RPN)
  • 성공하고 결과가 입력 값과 일치하면 사용 된 문자열을 반환합니다.
  • 그렇지 않으면 증분 i후 다시 시도하십시오.

"[t] 만약 [...] 어떤 가치를 위해"당신은 그것을 테스트 했습니까? 어떤 가치?
Leaky Nun

@KennyLau 난 그냥 계산하는 것 테스트 썼다 f(i)에서을 0 <= i <= 6551(캡처하는 6551당신의 원본 제출을 @pbochniak 무효화하는 데 사용되는 값). 현재 몇 분 동안 만 실행 중이며 테스트 결과는 다음과 같습니다. 91 : 49+7* 3.020 s (total 108.174 s, worst 89: 5.827 s) Update-값 92로 끝났습니다. 92 : 149+7*+ 258.761 s (total 366.935 s, worst 92: 258.761 s)
Ken 'Joey'Mosher

@KennyLau : 테스트는 한 시간 동안 진행되었으며 최대 가치까지만 113... 관심있는 경우 여기에서 전체 테스트 출력 (페이스트 빈)을 참조하십시오 ...
Ken 'Joey'Mosher

2

파이썬 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이 아닌 경우에만 수행되지만 나누기가 필요하지 않다는 강한 의혹이 있지만 (증거 방법은 없지만 최대 500까지 확인했습니다).

프로그램 NameError은 결과를 인쇄 한 후 ( 종료)를 통해 종료됩니다 .


;E결국 무엇을 하고 있습니까?
Leaky Nun

@KennyLau 그것은 다른 곳에서 정의되지 않았기 NameError때문에 종료를위한 E것입니다
Sp3000

와우, 그런 영리함.
Leaky Nun



0

파이썬 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*n9 바이트 추가 비용으로 더 빠르게 처리 할 수 ​​있습니다. /어떻게해야하는지 알 수 없기 때문에 나눗셈 ( )을 생략했습니다 .


힌트 : 나눗셈이 필요합니다.
Leaky Nun
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.