As you know, the value of
pi with some decimals is 3.141592653589...
Write an expression using all digits (0-9) once each, to achieve the
closest value to
pi. The digits must be in the order 1, 2, 3, 4, ...8, 9, 0. You may also use as many parentheses, +, -, /, and *, as you wish, but only these symbols.
As an example: 123/45 - 6/7 + 8/9 + 0 = 2.765079... gives a difference of approximately 0.376.
You may post the difference or the approximation you achieve in the subject of your comment.
A program to find all possibilities gives (1-2/(3-4/(5/6-7*8)))*(9+0) = 3.141592920353983 (the same 355 / 113 Ady found -- double precision used, so the difference is found more accurately).
A later program, designed to allow a leading negative sign, which the first was not, found an alternate: -1 + 2/((345-6)/(78*(9+0))). This is also equivalent to 355/113.
The table below shows the successively better solutions found by the first program. The first column shows the Reverse Polish Notation form; the second shows algebraic form; and the third shows the approximation. Note that some of the algebraic forms involve division by a product; parentheses were not placed around the product, and you must interpret as multiplication taking precedence over division, which is not standard. Just insert the needed parentheses for standard order of operations. This is not involved with the most accurate solution.
123456789,0* 123456789*0 0
12345,67890/ 12345/67890 .1818382677861246
12345,6789,0+/ 12345/(6789+0) 1.818382677861246
12345,678,9,0+*/ 12345/678*(9+0) 2.023107177974435
12345,67,89,0+*/ 12345/67*(89+0) 2.070266644306557
12345,67,8,9,0+**/ 12345/67*8*(9+0) 2.55907960199005
12345,6,789,0+*/ 12345/6*(789+0) 2.607731305449937
12345,6,78,9,0+**/ 12345/6*78*(9+0) 2.930911680911681
12345,6,7,89,0+**/ 12345/6*7*(89+0) 3.302568218298555
12345,6,7,8,90+**/ 12345/6*7*(8+90) 2.999271137026239
12345,6,7*/,8-,90/ (12345/6*7-8)/90 3.176984126984127
1234,567/,8,9,0+-- 1234/567-(8-(9+0)) 3.17636684303351
1234,567/,8-,9,0++ 1234/567-8+9+0 3.176366843033509
1234,56,7,89,0*+*/ 1234/56*(7+89*0) 3.147959183673469
1234,56,7*,8,90/+/ 1234/(56*7+8/90) 3.147245522557243
1234,56,7*,8,9,0+--/ 1234/(56*7-(8-(9+0))) 3.139949109414758
1234,56,7*,8,9,0+/+/ 1234/(56*7+8/(9+0)) 3.140837104072398
123,4-,5,6*,7,8,9,0+//+/ (123-4)/(5*6+7/(8/(9+0))) 3.141914191419142
12,34+,5,6,7,8,90/*/+/ (12+34)/(5+6/(7*8/90)) 3.141463414634146
12,3,4,5,67,8,90*/+/// 12/(3/(4/(5+67/8*90))) 3.14153258794655
12,3,4,5*+,6//,7,8-,90/- 12/((3+4*5)/6)-(7-8)/90 3.141545893719806
12,3,4,5/,6,7+,890/-// 12/(3/(4/5-(6+7)/890)) 3.141573033707866
1,23,4,56,7-/-,8,9,0+*// 1/((23-4/(56-7))/8*(9+0)) 3.141585040071238
1,2,3,4,5,6/,7,8*-/-/-,9,0+* (1-2/(3-4/(5/6-7*8)))*(9+0) 3.141592920353983
The program actually was two programs--the first to find the RPN form and the second to convert RPN to algebraic notation:
To produce RPN:
DECLARE SUB addon ()
DEFDBL A-Z
DIM SHARED stack(11)
DIM SHARED upTo, stackLevel
DIM SHARED h$, best
best = 9999
stack(1) = 1: stackLevel = 1: upTo = 1
h$ = "1"
addon
SUB addon
nextOne = upTo + 1
SELECT CASE nextOne
CASE 10
nextOne = 0
CASE 1
' this is the end
' evaluate
IF stackLevel = 1 THEN
diff = ABS(stack(1) - 3.141592654#)
IF diff < best THEN
best = diff
PRINT h$, stack(1)
END IF
EXIT SUB
ELSE
nextOne = 999
END IF
END SELECT
'first try concatenation
IF nextOne < 999 THEN
lc$ = RIGHT$(h$, 1)
ix = INSTR("0123456789", lc$)
IF ix THEN
h$ = h$ + LTRIM$(STR$(nextOne))
stack(stackLevel) = 10 * stack(stackLevel) + nextOne
utSave = upTo
upTo = nextOne
addon
upTo = utSave
stack(stackLevel) = stack(stackLevel) 10
h$ = LEFT$(h$, LEN(h$) - 1)
END IF
END IF
'try comma
IF nextOne < 999 THEN
stackLevel = stackLevel + 1
stack(stackLevel) = nextOne
h$ = h$ + "," + LTRIM$(STR$(nextOne))
utSave = upTo
upTo = nextOne
addon
upTo = utSave
stackLevel = stackLevel - 1
h$ = LEFT$(h$, LEN(h$) - 2)
END IF
GOSUB tryDiadic
EXIT SUB
tryDiadic:
IF stackLevel >= 2 THEN
s1 = stack(stackLevel - 1)
s2 = stack(stackLevel)
stackLevel = stackLevel - 1
stack(stackLevel) = s1 + s2
h$ = h$ + "+"
addon
h$ = LEFT$(h$, LEN(h$) - 1)
stack(stackLevel) = s1
stackLevel = stackLevel + 1
stack(stackLevel) = s2
s1 = stack(stackLevel - 1)
s2 = stack(stackLevel)
stackLevel = stackLevel - 1
stack(stackLevel) = s1 - s2
h$ = h$ + "-"
addon
h$ = LEFT$(h$, LEN(h$) - 1)
stack(stackLevel) = s1
stackLevel = stackLevel + 1
stack(stackLevel) = s2
s1 = stack(stackLevel - 1)
s2 = stack(stackLevel)
stackLevel = stackLevel - 1
stack(stackLevel) = s1 * s2
h$ = h$ + "*"
addon
h$ = LEFT$(h$, LEN(h$) - 1)
stack(stackLevel) = s1
stackLevel = stackLevel + 1
stack(stackLevel) = s2
s1 = stack(stackLevel - 1)
s2 = stack(stackLevel)
IF s2 <> 0 THEN
stackLevel = stackLevel - 1
stack(stackLevel) = s1 / s2
h$ = h$ + "/"
addon
h$ = LEFT$(h$, LEN(h$) - 1)
stack(stackLevel) = s1
stackLevel = stackLevel + 1
stack(stackLevel) = s2
END IF
END IF
RETURN
END SUB
And this one to convert RPN to algebraic:
DECLARE SUB checkParen (s$, ops$)
OPEN "close2pi.txt" FOR INPUT AS #1
OPEN "clsepi.TXT" FOR OUTPUT AS #2
DO
LINE INPUT #1, l$
ix = INSTR(l$, " ")
nOrig$ = LTRIM$(MID$(l$, ix))
l$ = LEFT$(l$, ix - 1)
stackLevel = 0
bld$ = ""
FOR i = 1 TO LEN(l$)
c$ = MID$(l$, i, 1)
ix = INSTR("0123456789", c$)
IF ix THEN
bld$ = bld$ + c$
stkRaise = 1
ELSE
IF stkRaise THEN
stackLevel = stackLevel + 1
stack$(stackLevel) = bld$
stkRaise = 0
bld$ = ""
END IF
SELECT CASE c$
CASE "+"
stackLevel = stackLevel - 1
stack$(stackLevel) = stack$(stackLevel) + "+" + stack$(stackLevel + 1)
CASE "-"
h2$ = stack$(stackLevel)
checkParen h2$, "+-"
stackLevel = stackLevel - 1
h1$ = stack$(stackLevel)
stack$(stackLevel) = h1$ + "-" + h2$
CASE "*"
h2$ = stack$(stackLevel)
checkParen h2$, "+-"
stackLevel = stackLevel - 1
h1$ = stack$(stackLevel)
checkParen h1$, "+-/"
stack$(stackLevel) = h1$ + "*" + h2$
CASE "/"
h2$ = stack$(stackLevel)
checkParen h2$, "+-/"
stackLevel = stackLevel - 1
h1$ = stack$(stackLevel)
checkParen h1$, "+-/"
stack$(stackLevel) = h1$ + "/" + h2$
CASE "^"
h2$ = stack$(stackLevel)
checkParen h2$, "+-*/"
stackLevel = stackLevel - 1
h1$ = stack$(stackLevel)
checkParen h1$, "+-*/"
stack$(stackLevel) = h1$ + "^" + h2$
END SELECT
END IF
NEXT
IF stackLevel <> 1 THEN
REM
END IF
PRINT l$, stack$(1), nOrig$: PRINT #2, l$, stack$(1)
LOOP UNTIL EOF(1)
CLOSE
SUB checkParen (s$, ops$)
pLevel = 0
flag = 0
FOR i = 1 TO LEN(s$)
SELECT CASE MID$(s$, i, 1)
CASE "("
pLevel = pLevel + 1
CASE ")"
pLevel = pLevel - 1
CASE ELSE
IF pLevel = 0 AND INSTR(ops$, MID$(s$, i, 1)) THEN flag = 1: EXIT FOR
END SELECT
NEXT i
IF flag THEN s$ = "(" + s$ + ")"
END SUB
Edited on September 26, 2005, 12:26 am
|
Posted by Charlie
on 2005-09-26 00:14:36 |