Tuesday 17 January 2012

"Le Compte Est Bon" game

"Le compt est Bon" ("the calculus is right") is a French game, the scope of the game is arriving to the target number using the number sequence with just the operator +,-,*,/ and the numbers or their results only one time.
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