I found this script that works good, but it's very hard to understand:
http://www.rebol.org/view-script.r?script=ceb.r
I tried to rewrite it in an easy way to understand, this is the result:
ceb: func [
"Find the way to reach the target number using the numbers in list"
list [ series! ]
target [integer! ]
/local op dv calculs nwlist
] [
text: reform [ "Series:" list ", target number:" target newline ]
sort list
kronos: now/time
op: [ + - * / ]
dv: func [ x y ] [
either all [( x <> 0 ) (y <> 0) ] [
either (x // y) = 0 [ x / y ] [ 0 ]
] [
0
]
]
;try to divide with no reminder, otherwise it returns zero
calculs: func [
x y
] [
reduce [
( x + y) ( x - y) ( x * y) (dv x y)
]
]
status: false
find-sol: func [
list text /local list2 list3 results
] [
if status [
exit
]
foreach item list [
if status [
break
]
list2: copy list
alter list2 item ;we remove the item from a copy of the list
foreach item2 list2 [
if status [
break
]
list3: copy list2
alter list3 item2 ;we remove the item2 from a copy of the list2
results: calculs item item2
for i 1 4 1 [
if status [
break
]
text2: append (copy text) (reform [item op/:i item2 "=" results/:i newline ])
if results/:i = target [
status: true print text2 print reform [
"time elapsed: " ( now/time - kronos )
]
]
list4: append (copy list3) results/:i ;add one of the reults to the list of numbers to use
if (length? list4) >= 2 [
find-sol list4 text2
]
]
]
]
]
find-sol list text
if status = false [
print "Sorry, I didn't find any solution."
]
]
Here an example of how it works:
>> ceb [ 1 2 3 4 ] 27
Series: 1 2 3 4 , target number: 27
2 * 4 = 8
1 + 8 = 9
3 * 9 = 27
time elapsed: 0:00
>> ceb [ 3 6 25 50 75 100 ] 698
Series: 3 6 25 50 75 100 , target number: 698
3 + 6 = 9
75 * 9 = 675
25 + 675 = 700
100 / 50 = 2
700 - 2 = 698
time elapsed: 0:00:18
Can you find a more elegant solution? ;-)
No comments:
Post a Comment