운영자 우선 순위 : 내가 얼마나 잘못 될 수 있습니까?


65

표현이 있다고 가정 해보십시오.

9 * 8 + 1 - 4

이 표현식은 연산자 우선 순위에 따라 6 가지 방식으로 해석 될 수 있습니다.

(((9 * 8) + 1) - 4) = 69 (* + -)
((9 * 8) + (1 - 4)) = 69 (* - +)
((9 * (8 + 1)) - 4) = 77 (+ * -)
(9 * ((8 + 1) - 4)) = 45 (+ - *)
((9 * 8) + (1 - 4)) = 69 (- * +)
(9 * (8 + (1 - 4))) = 45 (- + *)

내가 개발자이고 우선 순위표 등을 기억하는 것을 좋아하지 않는다고 가정하면 추측 할 것입니다.

이 경우 가장 큰 오차 한계는 45-77이며 이는 32의 차이입니다. 이는 내 추측이 최대 32까지만 해제됨을 의미합니다.

도전

번호 이루어지는 식 주어 +, -, *, /(정수 나눗셈) 및 %운영자의 우선 순위에 기초하여, 출력이 식의 크고 작은 가능한 값의 절대 차이.

사양

  • 입력 표현식은 괄호를 포함하지 않으며 모든 연산자는 왼쪽 연관입니다.
  • 입력 표현식은 음이 아닌 정수만 포함합니다. 그러나 하위 식은 음성으로 평가 될 수 있습니다 (예 :) 1 - 4.
  • 합리적인 형식으로 표현을 취할 수 있습니다. 예를 들면 다음과 같습니다.
    • "9 * 8 + 1 - 4"
    • "9*8+1-4"
    • [9, "*", 8, "+", 1, "-", 4]
    • [9, 8, 1, 4], ["*", "+", "-"]
  • 입력에는 1 ~ 10 명의 연산자가 포함됩니다.
  • 0으로 나누기 또는 모듈로를 포함하는 표현식은 무시해야합니다.
  • 모듈로에 음의 피연산자가 주어지지 않는다고 가정 할 수 있습니다.

테스트 사례

9 * 8 + 1 - 4             32
1 + 3 * 4                  3
1 + 1                      0
8 - 6 + 1 * 0              8
60 / 8 % 8 * 6 % 4 * 5    63

1
@AndersKaseorg %두 번째 예제에서 두 가지 우선 순위를 갖는 것으로 간주됩니다.
Esolanging 과일

1
'6'중 3 개는 다른 2 개와 동일합니다. 6 건이 아닌 3 건의 실제 사례가 남았습니다.
207421

3
%연산자가 음수에서 어떻게 작동합니까? C 또는 Python과 같은 방식입니까?
tsh

8
간단히 말해서 설명에 "그리고 게으른"부분을 추가 할 필요는 없습니다. 당신이 개발자라고 말하는 것만으로 충분합니다. :)
그리폰

1
@tsh 모든 동작. 너가 원하는 것을해라. 당신은 악마를 내 코에서 날아갈 수 있습니다 .
Esolanging 과일

답변:


27

파이썬 2 , 171,156 바이트

lambda a:max(e(a))-min(e(a))
u=')%s('
def e(a,t=u):
 try:b=[eval(a)]
 except:b=[]
 return sum([e('(%s)'%a.replace(o,t%o),u%t)for o in"+-*/%"if' '+o in a],b)

온라인으로 사용해보십시오!

작동 원리

우리는 각 연산자를 다른 수의 바깥 쪽을 향한 괄호로 묶어 서로 다른 우선 순위를 (모든 가능한 방법으로) 시뮬레이트하고 전체 문자열 주위에 충분한 안쪽을 향하는 괄호를 감싸서 전체 표현식을 얻을 수 있습니다 eval. 예를 들어

+)+(
*))*((
-)))-(((

우리는 얻는다

9 * 8 + 1 - 4(((9 ))*(( 8 )+( 1 )))-((( 4)))= 77.


대괄호 레이어를 제거하기 위해 or바깥 쪽 을 움직여 2 바이트를 절약 할 수 있습니다 sum. sum([...],[])or[eval(a)]대신sum([...]or[[eval(a)]],[])
Strigoides

@Strigoides 필자는 sum인수가 비어 있지 않고 비어있을 수 있기 때문에 동등하지 않다고 생각 했지만 실제로는 eval반드시 실패해야 하기 때문에 괜찮습니다 . 감사.
Anders Kaseorg

8

젤리 , 126 바이트

"운영자 우선 순위? 괄호? Pah, 누가 필요합니까?" -운영자 우선 순위 도전에 젤리를 사용하는 문제.

⁾[]i$€Ḥæ%3+\¬œp¹Ḋ€
ǵḟØDO%9µÐṀṪɓœṣ⁹,ṚÑj@¥/
ǵVṾµ1ĿFḟØDḟ”-Lµ?ÐL
5Ḷx@€“]“[”ż⁸j/€,@y³Fɓ³i@€Ṁ’x@“[“]”jÇ
“+_×:%”Œ!Ç€µṾL_L’ỊµÐfV€ṢIS

온라인으로 사용해보십시오!

입력은 문자열로 간주됩니다 (예 : "1 + 2_3 × 4 : 5 % 6"). 곱셈은 ​​"*"대신 "×"를 사용하고 나누기는 "/"대신 ":"을 사용하고 빼기는 "-"대신 "_"를 사용합니다.

작동 원리 프로그램은 서로 다른 연산자 우선 순위의 모든 표현식 생성, 평가 및 최대 값과 최소값의 차이를 리턴하는 세 부분으로 나뉩니다.

모든 표현식은 다음 코드로 생성됩니다.

5Ḷx@€“]“[”ż⁸j/€,@y³Fɓ³i@€Ṁ’x@“[“]”jÇ (4) helper link: returns all outputs given a permutation. Input e.g. "_+:×%"
5Ḷx@€“]“[”           - repeat outer brackets to get ["",""],["]","["],["]]","[["],["]]]","[[["],["]]]]","[[[["]
          ż⁸j/€      - insert the operations in to get "_","]+[","]]:[[","]]]×[[[","]]]]%[[[["
               ,@    - turn this into a mapping equivalent to "_"↦"_","+"↦"]+[",":"↦"]]:[[","×"↦"]]]×[[[","%"↦"]]]]%[[[["
                 y³F - use this mapping to get the right number of outward brackets on each operation. e.g. "1]+[3]]]×[[[4"
ɓ³i@€Ṁ’x@“[“]”j      - add the right number of brackets to the end to get e.g."[[[1]+[3]]]×[[[4]]]"
               Ç     - this calls the link which evaluates the expression
“+_×:%”Œ!Ç€                          (5a) main link. Input e.g. "1+3×4"
“+_×:%”                                 - the string "+_×:%"
       Œ!                               - all permutations
         ǀ                             - apply link (4) to each permutation

링크는 이것으로 평가됩니다 (아마 다른 구조로 향상시킬 수 있습니다).

⁾[]i$€Ḥæ%3+\¬œp¹Ḋ€      (1) Helper link: Outputs a list of expressions within brackets, e.g. "[[[1]+[3]]]×[[[4]]]"↦"[[1]+[3]]","[[4]]"
⁾[]i$€Ḥæ%3                 - map "[" to 2, "]" to -2, and any other character to 0.
          +\¬              - cumulative sum negated: 1s at characters not in brackets (includes opening brackets), 0s otherwise (includes closing brackets)
             œp¹           - partition the input, not including borders, based on the sum to get "[[[1]+[3]]","[[[4]]"
                Ḋ€         - remove opening brackets
ǵḟØDO%9µÐṀṪɓœṣ⁹,ṚÑj@¥/ (2) Return the input to this link with one of the expressions from (1) evaluated
ǵVṾµ1ĿFḟØDḟ”-Lµ?ÐL     (3) link called from part 1: Evaluates expressions
 µ  µ          µ?          - if:
     1ĿFḟØDḟ”-L            - the input contains no operators within brackets:         
  VṾ                         - evaluate this one expression with normal Jelly calculation and return to string
                           - otherwise:
Ç                            - evaluate one subexpression using link (2)
                  ÐL       - repeat this until a single output is determined

최대 값과 최소값의 차이는 링크 (5)의 코드로 계산됩니다.

µṾL_L’ỊµÐfV€ṢIS (5b) determine difference between minimum and maximum
µ      µÐf        - filter out outputs involving division or modulo by 0. Determined with:
 ṾL_L’Ị           - actual numbers have their unevaled form Ṿ no more than one byte longer than the non-unevaled form.
          V€      - evaluate each of these valid numbers to get integers from strings
            Ṣ     - sort
             IS   - return the sum of all difference between consecutive elements.

4
아마도 내가 본 것 중 가장 긴 젤리 답변 (포함 된 데이터 없음). 잘 했어!
Keyu Gan

@KeyuGan 더 긴 젤리 답변을 원하면 이 답변을보십시오 . 압축없이 다른 긴 젤리 답변을 생각할 수 없습니다.
fireflame241'7

6

파이썬 (2) , 235 (234) 233 226 바이트

Anders Kaseorg 덕분에 -1 바이트 (및 수정) !

Step Hen 덕분에 -7 바이트 !

from itertools import*
def f(e,a=()):
 for o in permutations("+-*/%"):
	l=e[:]
	for c in o:
	 for i in range(len(l),0,-1):
		if l[i-1]==c:l[i-2:i+1]=["("+l[i-2]+l[i-1]+l[i]+")"]
	try:a+=eval(*l),
	except:0
 print max(a)-min(a)

온라인으로 사용해보십시오!


1
기능 제출은 재사용 할 수 있어야합니다 . a목록 대신 튜플을 사용 하여 문제를 해결할 수 있으며 그렇게하면 1 바이트를 절약 할 수도 있습니다 ( a=(), a+=eval(*l),).
Anders Kaseorg

허, 틸. 팁 고마워!
notjagan

1
파이썬 2에 있기 때문에 들여 쓰기를 위해 공백과 탭을 번갈아 가면 바이트를 절약 할 수 있습니다 (이 경우 2 공백-> 탭, 3 공백-> 탭 + 공백, 4 공백-> 2 탭) 온라인으로 사용해보십시오!
Stephen

4

하스켈 582 바이트

이것은 내가 바라는 것처럼 거의 가지 못했습니다 ...

import Data.List
f x=case x of '+'->(+);'-'->(-);'*'->(*);'/'->div;_->rem
e _ s[]=s
e 1 s(')':x:a)|0<-(read$e 0""a),(x=='%'||x=='/')=""|""<-(e 0""s)=""|""<-(e 0""a)=""|0<3=show$(f x)(read$e 0""s)$read$e 0""a
e 1 s")"=e 0""s
e n s(')':a)=e(n-1)(s++")")a
e 0 s('(':a)=e 1 s a
e n s('(':a)=e(n+1)(s++"(")a
e n s(x:a)=e n(s++[x])a
n?s=take n$cycle s
a!b=e 0""(9?"("++(concat$zipWith(++)a(b++[[]]))++9?")")
c#b|l<-[read x|x<-map(c!)(a b),x/=""]=maximum l-minimum l
a c=transpose$map(\x->map((\(Just q)->q).lookup x)$map(\a->zipWith(\x y->(y,x?")"++y:x?"("))[1..5]a)$permutations"+-*%/")c

온라인으로 사용해보십시오!

긴 프로그램을 골프하려고하면 나쁜 코드를 작성하게됩니다.

Haskell에서 Anders의 알고리즘을 사용하려고 시도했지만 제어가 불가능했습니다.

함수 e는 특정한 eval 케이스와 같습니다. (#)은 정수 및 연산자 문자열을 나타내는 문자열 목록을 사용하여 가능한 최대 값과 최소값의 차이를 반환합니다. 예 :

(#) ["9","8","1","4"] "*+-" => 32

1
로 이름 ###바꾸면 다음 과 같이 이름 e을 바꿀 (#)수 있습니다.(n#s)(x:a)=...
Esolanging Fruit

일반적으로 사용되는 다음 세 가지 기능의 별칭을 지정하면 6 바이트를 더 절약 할 수 있습니다. r=read;j=zipWith;o=map그런 다음 해당 기능을 문자 별명으로 바꿉니다.
maple_shaft

또한 582가 아닌 594 바이트를 계산합니다.
maple_shaft

3

Pyth, 45 바이트

KS.nm.x.vj\ u.nm+*H/kHckHGd]s.iFQY.p_{eQ-eKhK

더 많은 최적화를 수행 할 수 있다고 확신하지만 지금까지는 좋아합니다.

다음과 같은 입력을 [9, 8, 1, 4], ["*", "+", "-"]받습니다 : .

온라인으로 사용해보십시오!


2
설명을 추가 할 수 있습니까?
Jim

2

매쓰, 186 (164) 159 바이트

eMax@#-Min@#&[Fold[#//.{m___,x_,#2[[0]],y_,n___}:>{m,x~Last@#2~y,n}&,e,#]&/@Permutations@{"+"@Plus,"-"[#-#2&],"*"@Times,"/"@Quotient,"%"@Mod}/. 0/0|1/0->{}]

\[Function] 3 바이트가 걸립니다.

일부 대안 (바이트 수를 동일하게 유지)

#2-#&@MinMax[...] 교체 Max@#-Min@#&[...]

Head@#2 교체 #2[[0]]

http://sandbox.open.wolframcloud.com 에서 온라인으로 시험해보십시오 : 테스트 사례를 위해 위의 코드 ( .... )[{60, "/", 8, "%", 8, "*", 6, "%", 4, "*", 5}]....대체하여 입력하십시오 60 / 8 % 8 * 6 % 4 * 5. 눌러 Shift + enter평가합니다.


2

자바 스크립트, 280 바이트

참고 : 정수 나누기는 floor 함수를 사용하여 반올림되므로 음수가 0에서 멀어집니다.

이 솔루션은 이 답변을 기반으로 합니다 .

b=>(Math.max(...(f=(a,h="(",i=")",r=[...a[d="replace"](/[^-+*/%]|(.)(?=.*\1)/g,"")])=>(r[0]?(r.map((c,j)=>s=s.concat(f(h+a[d](RegExp("\\"+(n=r.concat()).splice(j,1),"g"),i+c+h)+i,h+"(",i+")",n)),s=[]),s):(a=eval(`(${a})`[d](/\(/g,"Math.floor(")))==a&&1/a?a:r))(b))-Math.min(...f(b)))

코드 스 니펫 예제 :

g=

b=>(Math.max(...(f=(a,h="(",i=")",r=[...a[d="replace"](/[^-+*/%]|(.)(?=.*\1)/g,"")])=>(r[0]?(r.map((c,j)=>s=s.concat(f(h+a[d](RegExp("\\"+(n=r.concat()).splice(j,1),"g"),i+c+h)+i,h+"(",i+")",n)),s=[]),s):(a=eval(`(${a})`[d](/\(/g,"Math.floor(")))==a&&1/a?a:r))(b))-Math.min(...f(b)))

for(k=0;k<5;k++)
  v=["9*8+1-4","1+3*4","1+1","8-6+1*0","60/8%8*6%4*5"][k],
  console.log(`g(${v}) = ${g(v)}`)


a / b 케이스를 a / b | 0으로 교체하여 준수하는 것이 얼마나 어려울까요?
trlkly

@trlkly a/b|0나누기 / 모듈로 0 오류 검사를 중지하지만 Math.floor(a/b)작동했습니다
Herman L

2

하스켈 , 254 바이트

import Data.List.Split
import Data.List
f s=(-)<$>maximum<*>minimum$permutations(zip"+-*/%"[p(+),p(-),p(*),c$div,c$mod])>>=(s!)
p=((pure.).)
c o a b=[o a b|b/=0]
s![]=[read s]
s!((x,o):y)=case splitOn[x]s>>=(!y)of[]->[];l->l?o
[a]?_=[a]
(a:b)?o=b?o>>=o a

온라인으로 사용해보십시오!

입력은 4 + 5 * 2와 같은 전체 문자열입니다. 연산의 모든 순열을 생성하고 각 순열에 대해 문자열을 재귀 적으로 분할합니다. 리스트 모나드로 0으로 나누기를 필터링합니다.


(%)계수 연산자입니다. 왼쪽 인수와 오른쪽 인수 사이의 나눗셈 연산의 나머지 부분입니다.
maple_shaft

1

파이썬 2 , 262 256 254 바이트

from itertools import*
def r(s,o):
 try:
  while o in s:i=s.index(o)-1;s[i:i+3]=[`eval(''.join(s[i:i+3]))`]
  return s
 except:0
def f(s):
 u=[int(v[0])for v in [reduce(r,O,s.split(' '))for O in permutations('*/%+-')]if v!=None];return abs(max(u)-min(u))

온라인으로 사용해보십시오!


탭을 사용하여 바이트를 절약하십시오. 온라인에서 사용해보십시오!
Stephen

1
로 변경 in [하여 1 바이트를 절약하십시오 in[(공백이 필요하지 않음)
Zacharý

1

PHP , 316 바이트

<?for(;$t++<54322;)count_chars($t,3)!=12345?:$p[]=$t;foreach($p as$x){for(list($z,$q)=$_GET,$b=1,$i=0;$y=strtr($x,12345,"/%*+-")[$i++];)while(-1<$k=array_flip($q)[$y]){$n=$k+1;if($b&=$z[$n]||ord($y)%10<6)eval("\$z[$k]=$z[$k]$y$z[$n]^0;");($s=array_splice)($z,$n,1);$s($q,$k,1);}$b?$r[]=$z[0]:0;}echo max($r)-min($r);

온라인으로 사용해보십시오!

Expanded
for(;$t++<54322;)
  count_chars($t,3)!=12345?:$p[]=$t;
foreach($p as$x){
  for(list($z,$q)=$_GET,$b=1,$i=0;$y=strtr($x,12345,"/%*+-")[$i++];)
    while(-1<$k=array_flip($q)[$y]){
      $n=$k+1;
      if($b&=$z[$n]||ord($y)%10<6)
        eval("\$z[$k]=$z[$k]$y$z[$n]^0;");
      ($s=array_splice)($z,$n,1);
      $s($q,$k,1);
    }
  $b?$r[]=$z[0]:0;
}
echo max($r)-min($r);

Lase case는 63입니다. 한 연산자의 다른 부분에서 같은 연산자에 다른 우선 순위를 부여함으로써 발생하는 실수
H.PWiz

0

파이썬 3 , 284 바이트

편집 : 마지막 예를 평가하는 데 문제가있는 것 같습니다. 내일 살펴 보겠습니다.

또 다른 파이썬 답변. 다른 사람들을 능가 할 수는 없었지만 너무 오래 걸리지 않았습니다.

from itertools import*
def f(n,o):
 z=[]
 for p in permutations("+-*/%"):
  try:
   p,x,a=[*p],n[:],o[:]
   while(p):
    for i,d in enumerate(a):
     if d==p[0]:x[i+1]=str(eval(x[i]+d+x[i+1]));x.pop(i);a.pop(i)
    p.pop(0)
   z+=x
  except:0
 z=[*map(float,z)];return max(z)-min(z)

온라인으로 사용해보십시오!


1
while(p)while p1 바이트를 절약 할 수 있습니다 .
Zacharý

0

Clojure (+ 조합론), 342 377 + 41 = 418 바이트

버그로 인해 +35 바이트

(fn[x y](let[l filter s first z #(l(fn[y]y)%)r(sort(z(for[e(q/permutations[+ - * quot mod])](try(loop[t e m y a x](if(=[]t)(s a)(let[j(s t)i(reverse(keep-indexed #(if(= j %2)%)m))](recur(rest t)(l #(not= j %)m)(loop[d 0 h a](if(=(count i)d)h(let[c(nth i d)f(inc c)](recur(inc d)(vec(z(assoc h c(j(nth h c)(nth h f))f nil)))))))))))(catch Exception _ nil)))))](-(last r)(s r))))

온라인으로 사용해보십시오!

이 기능이 작동 use하려면 clojure.math.combinatorics라이브러리에 있어야합니다 (41 바이트).

(use '[clojure.math.combinatorics :as q])

뉘앙스 :

이 함수는 익명 함수이므로이를 사용하려면 다음을 수행해야합니다.

((fn[x y]...) numbers operators)

또한, 나는 단어를 사용하고 quot대신을 /하고, (Clojure에 기본적으로 일부 사업부를 않기 때문에) mod대신 %.

언 골프 프로그램 :

(defn precedence [numbers operators]
  (let [results
        (sort
          (for [permute (c/permutations [+ - * / mod])]
            (loop [p-temp permute
                  o-temp operators
                  n-temp numbers]
              (if (empty? o-temp) (first n-temp)
                (let [first-p (first p-temp)
                      indices (reverse (keep-indexed #(when (= first-p %2) %) o-temp))]
                  (recur
                    (rest p-temp)
                    (filter #(not= first-p %) o-temp)
                    (loop [ind 0
                          n-through n-temp]
                      (if (= ind (count indices)) n-through
                        (let [current-ind (nth indices ind)]
                          (recur
                            (inc ind)
                            (vec
                              (filter #(not (nil? %))
                                (assoc n-through
                                  current-ind (first-p (nth n-through current-ind) (nth n-through (inc current-ind)))
                                  (inc current-ind) nil)))))))))))))]
    (- (last results) (first results))))

"Closure + Combinatorics"라고 말하면 use됩니다.
Esolanging 과일

@ Challenger5 기본적으로 The characters used to import the library will likely be counted codegolf.meta.stackexchange.com/questions/10225/…
Keyu Gan

@KeyuGan 당신 말이 맞아요-메타 합의를 오해했습니다. 내가 생각 require요구하는 포함 된 코드와 길이가 바이트 수에 추가해야합니다.
Esolanging 과일

@ Challenger5 그래서 바이트 수에 41 바이트를 추가해야합니까? 승인.
Qwerp-Derp

@ Qwerp-Derp 예. 그러나 가져 오기는 코드의 일부이므로 골프를 타실 수 있습니다.
Esolanging 과일

0

자바 스크립트 (ES6), 210 바이트

숫자와 연산자의 배열로 입력

k=>(m=n=-k,r=(o,k,j=0)=>{for(o||(m=m>k?m:k,n=n<k?n:k);q=o[j++];(q>'%'&q<'/'||z)&&r(o.slice(0,j-1)+o.slice(j),h))for(h=[...k],z=1;i=h.indexOf(q)+1;h.splice(i-2,3,eval(a=h[i-2]+q+h[i])|0))z*=h[i]})('+-*/%',k)|m-n

덜 골프

k=>(
  m = n = NaN,
  r =(o, k, j=0) => {
    // try all operators in o
    for(;q = o[j]; j++)
    {  
      // q : current operator, 
      // look for q inside the expression to evaluate
      for(h = [...k], z = 1; i = h.indexOf(q) + 1;)
      {
        a = h[i - 2]
        b = h[i]
        z *= b // trace if any second operand is zero
        // subst subexpression with its value
        h.splice(i - 2, 3, eval(a + q + b) | 0)
      }
      // now all subexp involving current operator are evaluated
      // the result is ok if current operator is not % or /
      //  OR if no second operand was zero
      (q > '%' & q < '/' || z) && 
        // try again recursively
        // using the remaining operators and the remaining expression
        r(o.slice(0, j) + o.slice(j+1), h) 
    }
    // if no more operators to try, check max and min
    // k is an array with 1 element, can be used like a single number
    o || (
      m = m > k ? m : k, 
      n = n < k ? n : k
    )
  },
  r('+-*/%', k),
  m-n
)

테스트

var F=
k=>(m=n=-k,r=(o,k,j=0)=>{for(o||(m=m>k?m:k,n=n<k?n:k);q=o[j++];(q>'%'&q<'/'||z)&&r(o.slice(0,j-1)+o.slice(j),h))for(h=[...k],z=1;i=h.indexOf(q)+1;h.splice(i-2,3,eval(a=h[i-2]+q+h[i])|0))z*=h[i]})('+-*/%',k)|m-n

function update() {
  var input = I.value.match(/\d+|\S/g)
  var result = F(input)
  O.textContent = I.value + ' -> ' + result + ' (max:'+m+' min:'+n+')'
}

update()
<input id=I value="60 / 8 % 8 * 6 % 4 * 5" oninput='update()'>
<pre id=O></pre>

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