• The hardest euler problem.

    From albert@spenarnc.xs4all.nl@21:1/5 to All on Mon Jun 10 19:24:31 2024
    Remember the year 2008? There was a post with the same title.

    At the time the hardest euler problem was 177, at level 80%.
    I have solved several level 100% problems but this problem
    evaded me, till now!

    https://projecteuler.net/problem=177
    Integer Angled Quadrilaterals.
    Let be a convex quadrilateral, with diagonals. At each vertex the
    diagonal makes an angle with each of the two sides, creating eight
    corner angles that must be an integral measured in degrees.
    Find the number of such quadrilaterals.
    Not only must you find how to generate them, but I kept apparently
    generating duplicates. At last I generated all of them, and removed
    duplicates and succeeded.

    Groetjes Albert
    --
    Don't praise the day before the evening. One swallow doesn't make spring.
    You must not say "hey" before you have crossed the bridge. Don't sell the
    hide of the bear until you shot it. Better one bird in the hand than ten in
    the air. First gain is a cat purring. - the Wise from Antrim -

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@21:1/5 to All on Thu Jun 13 05:54:29 2024
    Euler #177 is a fairly straightforward exercise in CLP(FD)
    programming. To emulate it in Forth is a challenge in itself,
    not unlike the famous Magic Hexagon solver.

    The CLP(FD) constraints are the angle sums. I quickly hacked
    something together in BProlog to find the first solution.
    There are many more... :

    :- initialization(main).

    main :-

    Angles = [ % angles counter-clockwise
    A1,A2, B1,B2, C1,C2, D1,D2 ],
    Angles :: 1..179,

    euler(Angles), % read puzzle

    % avoid duplications and square
    A1+A2 #< 90,
    % angle sums
    A2+B1+B2+C1 #= 180,
    B2+C1+C2+D1 #= 180,
    A1+A2+B1+D2 #= 180,
    A1+C2+D1+D2 #= 180,
    % central symmetry
    A2+B1 #= C2+D1,
    B2+C1 #= A1+D2,
    % rectangle
    A1+A2+B1+B2+C1+C2+D1+D2 #= 360,

    labeling(Angles),
    writeln(Angles).

    euler([_,_, _,_, _,_, _,_]).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ahmed@21:1/5 to All on Thu Jun 13 11:59:20 2024
    Hi,
    My attempt to solve this problem.

    \ the code begins here

    \ Euler_177
    \ Example:
    \ DAC = 20, BAC = 60, ABD = 50, CBD = 30,
    \ BCA = 40, DCA = 30, CDB = 80, ADB = 50


    \ ---------------------------
    0 value vals_num
    20 value vals_num_max


    0 value nloops_prec
    0 value nloops
    0 value constraint_num
    30 value max_num_constraints
    create loop_loc max_num_constraints allot
    loop_loc max_num_constraints erase

    0 value min_val
    0 value max_val

    : .-- nloops 1+ to nloops postpone do postpone i ; immediate
    : .?, postpone min_val postpone max_val postpone 1+ postpone within
    postpone if ; immediate
    : --> postpone to constraint_num 1+ to constraint_num nloops nloops_prec
    <> if 1 loop_loc constraint_num + c! nloops to nloops_prec then ;
    immediate
    : --- ; immediate
    : _begin_ ; immediate
    : .| postpone then loop_loc constraint_num + c@ if postpone loop then constraint_num 1- to constraint_num ; immediate
    : _end_ ; immediate
    : =, postpone = postpone if ; immediate
    : =| postpone then ; immediate
    : values dup 1+ to vals_num 0 ?do 0 value loop ;
    \ --------------------------


    \ euler 177
    8 values DAC BAC ABD CBD BCA DCA CDB ADB
    1 to min_val
    179 to max_val

    0 value count_max

    0e fvalue aa
    0e fvalue bb
    0e fvalue cc
    0e fvalue dd
    0e fvalue ee
    0e fvalue ff
    0e fvalue gg
    0e fvalue hh

    0e fvalue tab
    0e fvalue tcd
    0e fvalue tb
    0e fvalue tc

    0e fvalue cx
    0e fvalue cy
    0e fvalue dx
    0e fvalue dy

    0e fvalue dcx
    0e fvalue dcy

    0e fvalue |ac|
    0e fvalue |dc|
    0e fvalue |bd|


    1500000 value result_size_max
    8 value result_angles
    result_size_max result_angles * value size

    create result size allot
    result size erase

    : th_result result_angles * result + + ;
    : th_result! rot th_result c! ;
    : th_result@ swap th_result c@ ;

    : result_DAC! DAC 0 th_result! ;
    : result_BAC! BAC 1 th_result! ;
    : result_ABD! ABD 2 th_result! ;
    : result_CBD! CBD 3 th_result! ;
    : result_BCA! BCA 4 th_result! ;
    : result_DCA! DCA 5 th_result! ;
    : result_CDB! CDB 6 th_result! ;
    : result_ADB! ADB 7 th_result! ;


    : update_result
    count_max result_DAC! count_max result_BAC! count_max result_ABD! count_max result_CBD!
    count_max result_BCA! count_max result_DCA! count_max result_CDB! count_max result_ADB!
    ;

    : count_max++ count_max 1+ to count_max ;

    \ The solution is 129325, found in https://github.com/lucky-bai/projecteuler-solutions/blob/master/Solutions.md

    1e-5 fvalue tolerance_integer
    2.013e-6 fvalue tolerance_equal

    : approx_integer f- fabs tolerance_integer f< ;
    : approx_equal f- fabs tolerance_equal f< ;

    : deg>rad s>f pi f* 180e f/ ;
    : approx_good fdup fround fswap fover approx_integer ;
    : rad>deg 180e f* pi f/ fround approx_good if f>s else fdrop -1 then ;

    : DCA_calc
    DAC deg>rad to aa
    BAC deg>rad to bb
    ABD deg>rad to cc
    CBD deg>rad to dd

    aa bb f+ ftan to tab
    cc dd f+ ftan to tcd
    bb ftan to tb
    cc ftan to tc

    tcd tcd tb f+ f/ to cx
    tb cx f* to cy

    tc tc tab f+ f/ to dx
    tab dx f* to dy

    cx dx f- to dcx
    cy dy f- to dcy

    cx fdup f* cy fdup f* f+ fsqrt to |ac|
    dx 1e f- fdup f* dy fdup f* f+ fsqrt to |bd|

    dcx fdup f* dcy fdup f* f+ fsqrt to |dc|

    cx dcx f* cy dcy f* f+ |ac| |dc| f* f/ facos rad>deg
    ;


    : solve
    0 to count_max
    _begin_
    180 1 .-- --> DAC DAC .?,
    180 1 .-- --> BAC BAC .?,
    DAC BAC + 180 <= true =,
    180 1 .-- --> ABD ABD .?,
    180 DAC - BAC - ABD - --- --> ADB ADB .?,
    180 1 .-- --> CBD CBD .?,
    ABD CBD + 180 <= true =,
    180 BAC - ABD - CBD - --- --> BCA BCA .?,

    DCA_calc --- --> DCA DCA .?,

    DCA BCA + 180 <= true =,
    180 CBD - BCA - DCA - --- --> CDB CDB .?,
    ADB CDB + 180 <= true =,
    DAC BAC + ABD CBD + BCA DCA + CDB ADB +
    + + + 360 =,

    ADB CDB + deg>rad fsin |dc| f*
    DAC deg>rad fsin |ac| f* approx_equal true =,

    BCA DCA + deg>rad fsin |dc| f*
    CBD deg>rad fsin |bd| f* approx_equal true =,

    count_max++
    update_result

    =| =| =| =| .| =| .| .| =| .| .| .| =| .| .|
    _end_
    ;

    : .result 8 0 do dup i th_result@ 4 .r loop drop ;
    : .result_range 2dup < if 1+ swap then do cr i 7 .r ." : " i .result
    loop ;

    \ for a quadrilateral, there are 8 similars
    \ 2 by mirror, and 4 by rotation symetries so 4*2 = 8

    : .solution count_max 8 / . ;

    : Euler_177 solve .solution ;

    \ the code ends here

    The result depends on the tolerance used for approximating angles in
    integers and verifying the approximate equality

    To get the solution 129325 (found in https://github.com/lucky-bai/projecteuler-solutions/blob/master/Solutions.md) the tolerances are 1e-5 for angles, and 2.013e-6 for approximate
    equality.

    To see the solutions: 1000 1100 .result_range will display the solutions
    n° 1000 to n°1100 for example.
    The solutions are saved in the array: result.

    The code is in gforth and is executed with: gforth -m 1G in command line
    (to get sufficient memory in dictionary to save the solutions)

    We can use just gforth (without -m 1G in command line), but we must
    comment out the creation of the array result and the words correspondant
    to it like: update_result, .result, .result_range. we must also comment
    out the word update_result in the word solve.

    The execution time is about 75 seconds on my laptop with gforth.

    Ahmed

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ahmed@21:1/5 to All on Thu Jun 13 12:05:20 2024
    To get the solution type:

    In command line: gforth -m 1G euler_177.fs, where euler_177.fs is the
    name where the precedent code is saved.
    Then, in gforth prompt, type: euler_177

    Ahmed

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ahmed@21:1/5 to All on Thu Jun 13 16:46:24 2024
    The version without saving the angles (results), with some modification
    (no use of tolerance_angle),
    with gforth, no need for -m 1G in the command line.

    \ Here, the code begins

    \ Euler_177
    \ Example:
    \ DAC = 20, BAC = 60, ABD = 50, CBD = 30,
    \ BCA = 40, DCA = 30, CDB = 80, ADB = 50


    \ ---------------------------
    0 value vals_num
    20 value vals_num_max


    0 value nloops_prec
    0 value nloops
    0 value constraint_num
    30 value max_num_constraints
    create loop_loc max_num_constraints allot
    loop_loc max_num_constraints erase

    0 value min_val
    0 value max_val

    : .-- nloops 1+ to nloops postpone do postpone i ; immediate
    : .?, postpone min_val postpone max_val postpone 1+ postpone within
    postpone if ; immediate
    : --> postpone to constraint_num 1+ to constraint_num nloops nloops_prec
    <> if 1 loop_loc constraint_num + c! nloops to nloops_prec then ;
    immediate
    : --- ; immediate
    : _begin_ ; immediate
    : .| postpone then loop_loc constraint_num + c@ if postpone loop then constraint_num 1- to constraint_num ; immediate
    : _end_ ; immediate
    : =, postpone = postpone if ; immediate
    : =| postpone then ; immediate
    : values dup 1+ to vals_num 0 ?do 0 value loop ;
    \ --------------------------


    \ euler 177
    8 values DAC BAC ABD CBD BCA DCA CDB ADB
    1 to min_val
    179 to max_val

    0 value count_max

    0e fvalue aa
    0e fvalue bb
    0e fvalue cc
    0e fvalue dd
    0e fvalue ee
    0e fvalue ff
    0e fvalue gg
    0e fvalue hh

    0e fvalue tab
    0e fvalue tcd
    0e fvalue tb
    0e fvalue tc

    0e fvalue cx
    0e fvalue cy
    0e fvalue dx
    0e fvalue dy

    0e fvalue dcx
    0e fvalue dcy

    0e fvalue |ac|
    0e fvalue |dc|
    0e fvalue |bd|

    : count_max++ count_max 1+ to count_max ;

    \ The solution is 129325, found in https://github.com/lucky-bai/projecteuler-solutions/blob/master/Solutions.md

    2.013e-6 fvalue tolerance_equal

    : approx_equal f- fabs tolerance_equal f< ;

    : deg>rad s>f pi f* 180e f/ ;
    : rad>deg 180e f* pi f/ fround f>s ;

    : DCA_calc
    DAC deg>rad to aa
    BAC deg>rad to bb
    ABD deg>rad to cc
    CBD deg>rad to dd

    aa bb f+ ftan to tab
    cc dd f+ ftan to tcd
    bb ftan to tb
    cc ftan to tc

    tcd tcd tb f+ f/ to cx
    tb cx f* to cy

    tc tc tab f+ f/ to dx
    tab dx f* to dy

    cx dx f- to dcx
    cy dy f- to dcy

    cx fdup f* cy fdup f* f+ fsqrt to |ac|
    dx 1e f- fdup f* dy fdup f* f+ fsqrt to |bd|

    dcx fdup f* dcy fdup f* f+ fsqrt to |dc|

    cx dcx f* cy dcy f* f+ |ac| |dc| f* f/ facos rad>deg
    ;


    : solve
    0 to count_max
    _begin_
    180 1 .-- --> DAC DAC .?,
    180 1 .-- --> BAC BAC .?,
    DAC BAC + 180 <= true =,
    180 1 .-- --> ABD ABD .?,
    180 DAC - BAC - ABD - --- --> ADB ADB .?,
    180 1 .-- --> CBD CBD .?,
    ABD CBD + 180 <= true =,
    180 BAC - ABD - CBD - --- --> BCA BCA .?,

    DCA_calc --- --> DCA DCA .?,

    DCA BCA + 180 <= true =,
    180 CBD - BCA - DCA - --- --> CDB CDB .?,
    ADB CDB + 180 <= true =,
    DAC BAC + ABD CBD + BCA DCA + CDB ADB +
    + + + 360 =,

    ADB CDB + deg>rad fsin |dc| f*
    DAC deg>rad fsin |ac| f* approx_equal true =,

    BCA DCA + deg>rad fsin |dc| f*
    CBD deg>rad fsin |bd| f* approx_equal true =,

    count_max++

    =| =| =| =| .| =| .| .| =| .| .| .| =| .| .|
    _end_
    ;

    : .solution count_max 8 / . ;

    : Euler_177 solve .solution ;

    \ Here, the code ends

    With same timing and result as the previous version.

    Ahmed

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ahmed@21:1/5 to All on Thu Jun 13 16:52:34 2024
    A new version with some modification (without saving the results
    (angles)) and no need for tolerance_angle.
    No need for -m 1G in command line (with gforth).
    Same timing and same result.


    \ Here, the code begins

    \ Euler_177
    \ Example:
    \ DAC = 20, BAC = 60, ABD = 50, CBD = 30,
    \ BCA = 40, DCA = 30, CDB = 80, ADB = 50


    \ ---------------------------
    0 value vals_num
    20 value vals_num_max


    0 value nloops_prec
    0 value nloops
    0 value constraint_num
    30 value max_num_constraints
    create loop_loc max_num_constraints allot
    loop_loc max_num_constraints erase

    0 value min_val
    0 value max_val

    : .-- nloops 1+ to nloops postpone do postpone i ; immediate
    : .?, postpone min_val postpone max_val postpone 1+ postpone within
    postpone if ; immediate
    : --> postpone to constraint_num 1+ to constraint_num nloops nloops_prec
    <> if 1 loop_loc constraint_num + c! nloops to nloops_prec then ;
    immediate
    : --- ; immediate
    : _begin_ ; immediate
    : .| postpone then loop_loc constraint_num + c@ if postpone loop then constraint_num 1- to constraint_num ; immediate
    : _end_ ; immediate
    : =, postpone = postpone if ; immediate
    : =| postpone then ; immediate
    : values dup 1+ to vals_num 0 ?do 0 value loop ;
    \ --------------------------


    \ euler 177
    8 values DAC BAC ABD CBD BCA DCA CDB ADB
    1 to min_val
    179 to max_val

    0 value count_max

    0e fvalue aa
    0e fvalue bb
    0e fvalue cc
    0e fvalue dd
    0e fvalue ee
    0e fvalue ff
    0e fvalue gg
    0e fvalue hh

    0e fvalue tab
    0e fvalue tcd
    0e fvalue tb
    0e fvalue tc

    0e fvalue cx
    0e fvalue cy
    0e fvalue dx
    0e fvalue dy

    0e fvalue dcx
    0e fvalue dcy

    0e fvalue |ac|
    0e fvalue |dc|
    0e fvalue |bd|

    : count_max++ count_max 1+ to count_max ;

    \ The solution is 129325, found in https://github.com/lucky-bai/projecteuler-solutions/blob/master/Solutions.md

    2.013e-6 fvalue tolerance_equal
    : approx_equal f- fabs tolerance_equal f< ;

    : deg>rad s>f pi f* 180e f/ ;
    : rad>deg 180e f* pi f/ fround f>s ;

    : DCA_calc
    DAC deg>rad to aa
    BAC deg>rad to bb
    ABD deg>rad to cc
    CBD deg>rad to dd

    aa bb f+ ftan to tab
    cc dd f+ ftan to tcd
    bb ftan to tb
    cc ftan to tc

    tcd tcd tb f+ f/ to cx
    tb cx f* to cy

    tc tc tab f+ f/ to dx
    tab dx f* to dy

    cx dx f- to dcx
    cy dy f- to dcy

    cx fdup f* cy fdup f* f+ fsqrt to |ac|
    dx 1e f- fdup f* dy fdup f* f+ fsqrt to |bd|

    dcx fdup f* dcy fdup f* f+ fsqrt to |dc|

    cx dcx f* cy dcy f* f+ |ac| |dc| f* f/ facos rad>deg
    ;


    : solve
    0 to count_max
    _begin_
    180 1 .-- --> DAC DAC .?,
    180 1 .-- --> BAC BAC .?,
    DAC BAC + 180 <= true =,
    180 1 .-- --> ABD ABD .?,
    180 DAC - BAC - ABD - --- --> ADB ADB .?,
    180 1 .-- --> CBD CBD .?,
    ABD CBD + 180 <= true =,
    180 BAC - ABD - CBD - --- --> BCA BCA .?,

    DCA_calc --- --> DCA DCA .?,

    DCA BCA + 180 <= true =,
    180 CBD - BCA - DCA - --- --> CDB CDB .?,
    ADB CDB + 180 <= true =,
    DAC BAC + ABD CBD + BCA DCA + CDB ADB +
    + + + 360 =,

    ADB CDB + deg>rad fsin |dc| f*
    DAC deg>rad fsin |ac| f* approx_equal true =,

    BCA DCA + deg>rad fsin |dc| f*
    CBD deg>rad fsin |bd| f* approx_equal true =,

    count_max++

    =| =| =| =| .| =| .| .| =| .| .| .| =| .| .|
    _end_
    ;

    : .solution count_max 8 / . ;

    : Euler_177 solve .solution ;

    \ Here, the code ends

    Ahmed

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From albert@spenarnc.xs4all.nl@21:1/5 to minforth on Thu Jun 13 21:48:09 2024
    In article <166c641a2b73cc18af0bafeba5947483@www.novabbs.com>,
    minforth <minforth@gmx.net> wrote:
    Euler #177 is a fairly straightforward exercise in CLP(FD)
    programming. To emulate it in Forth is a challenge in itself,
    not unlike the famous Magic Hexagon solver.

    The CLP(FD) constraints are the angle sums. I quickly hacked
    something together in BProlog to find the first solution.
    There are many more... :

    :- initialization(main).

    main :-

    Angles = [ % angles counter-clockwise
    A1,A2, B1,B2, C1,C2, D1,D2 ],
    Angles :: 1..179,

    euler(Angles), % read puzzle

    % avoid duplications and square
    A1+A2 #< 90,
    % angle sums
    A2+B1+B2+C1 #= 180,
    B2+C1+C2+D1 #= 180,
    A1+A2+B1+D2 #= 180,
    A1+C2+D1+D2 #= 180,
    % central symmetry
    A2+B1 #= C2+D1,
    B2+C1 #= A1+D2,
    % rectangle
    A1+A2+B1+B2+C1+C2+D1+D2 #= 360,

    labeling(Angles),
    writeln(Angles).

    euler([_,_, _,_, _,_, _,_]).

    You are quite confused.
    You don't even understand that goniometrics is involved
    in this problem.

    Groetjes Albert
    --
    Don't praise the day before the evening. One swallow doesn't make spring.
    You must not say "hey" before you have crossed the bridge. Don't sell the
    hide of the bear until you shot it. Better one bird in the hand than ten in
    the air. First gain is a cat purring. - the Wise from Antrim -

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@21:1/5 to albert@spenarnc.xs4all.nl on Fri Jun 14 07:45:50 2024
    albert@spenarnc.xs4all.nl wrote:
    You are quite confused.
    You don't even understand that goniometrics is involved
    in this problem.

    I take that as a friendly hint. But you are deducting
    really too much from a few lines of Prolog. ;-)

    Groetjes Andreas

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From albert@spenarnc.xs4all.nl@21:1/5 to Ahmed on Sun Jun 16 16:06:55 2024
    In article <01265fa27f2fd2de7269abef43881246@www.novabbs.com>,
    Ahmed <melahi_ahmed@yahoo.fr> wrote:
    A new version with some modification (without saving the results
    (angles)) and no need for tolerance_angle.
    No need for -m 1G in command line (with gforth).
    <SNIP>

    : solve
    0 to count_max
    _begin_
    180 1 .-- --> DAC DAC .?,
    180 1 .-- --> BAC BAC .?,
    DAC BAC + 180 <= true =,
    180 1 .-- --> ABD ABD .?,
    180 DAC - BAC - ABD - --- --> ADB ADB .?,
    180 1 .-- --> CBD CBD .?,
    ABD CBD + 180 <= true =,
    180 BAC - ABD - CBD - --- --> BCA BCA .?,

    DCA_calc --- --> DCA DCA .?,

    DCA BCA + 180 <= true =,
    180 CBD - BCA - DCA - --- --> CDB CDB .?,
    ADB CDB + 180 <= true =,
    DAC BAC + ABD CBD + BCA DCA + CDB ADB +
    + + + 360 =,

    ADB CDB + deg>rad fsin |dc| f*
    DAC deg>rad fsin |ac| f* approx_equal true =,

    BCA DCA + deg>rad fsin |dc| f*
    CBD deg>rad fsin |bd| f* approx_equal true =,

    count_max++

    =| =| =| =| .| =| .| .| =| .| .| .| =| .| .|
    _end_
    ;

    <SNIP>


    Ahmed

    Respect!
    Of you introduce control words like that, it is hard to understand without explanation.
    Would you care to paraphrase the line I have lifted out of the program.

    Groetjes Albert
    --
    Don't praise the day before the evening. One swallow doesn't make spring.
    You must not say "hey" before you have crossed the bridge. Don't sell the
    hide of the bear until you shot it. Better one bird in the hand than ten in
    the air. First gain is a cat purring. - the Wise from Antrim -

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ahmed@21:1/5 to albert@spenarnc.xs4all.nl on Sun Jun 16 17:06:07 2024
    albert@spenarnc.xs4all.nl wrote:

    Respect!
    Of you introduce control words like that, it is hard to understand
    without
    explanation.
    Would you care to paraphrase the line I have lifted out of the program.

    Groetjes Albert


    Hi,
    I tried to apply what I already done with CLP previously to this problem
    Euler problem 177.
    The solution I found is not really acceptable because it depends on the tolerance to consider a float approximately as an integer.

    But I still concerned with the CLP in forth.

    Here is a new simplified version of applying CLP to this problem in
    forth (gforth)



    The code begins here
    \ Euler_177

    \ ----- for CLP
    0 value vals_num
    20 value vals_num_max

    0 value min_val
    0 value max_val

    0 value nloops_prec
    0 value nloops
    0 value constraint_num
    30 value max_num_constraints
    0 value constraint_count

    : values dup 1+ to vals_num 0 ?do 0 value loop ;
    : fvalues 0 ?do 0e fvalue loop ;

    create loop_loc max_num_constraints allot
    loop_loc max_num_constraints erase

    create constraints_stack max_num_constraints cells allot
    constraints_stack max_num_constraints cells erase

    constraints_stack value constraints_stack_pointer

    : push_to_constraints_stack
    constraints_stack_pointer cell+ to constraints_stack_pointer
    constraints_stack_pointer !
    ;
    : pop_from_constraints_stack
    constraints_stack_pointer dup @
    swap cell- to constraints_stack_pointer
    ;

    : update_constraints
    constraint_num 1+ dup to constraint_count to constraint_num
    nloops nloops_prec <> if
    1 loop_loc constraint_num + c!
    nloops to nloops_prec
    then
    ;
    : resolve_constraints
    loop_loc constraint_num + c@ if
    postpone loop
    then
    constraint_num 1- to constraint_num
    ;
    : .---> nloops 1+ to nloops postpone do postpone i postpone to ;
    immediate
    : ----> postpone to ; immediate
    : a| postpone then resolve_constraints ; immediate
    : t| postpone then resolve_constraints ; immediate
    : a?,
    postpone min_val postpone max_val postpone 1+ postpone within
    postpone if
    update_constraints ['] a| push_to_constraints_stack
    ; immediate
    : t?,
    postpone if
    update_constraints ['] t| push_to_constraints_stack
    ; immediate
    : _begin_ ; immediate
    : _end_
    constraint_count 0 do
    pop_from_constraints_stack execute
    loop
    ; immediate

    \ ---------end for CLP

    \ Euler Problem 177
    8 values DAC BAC ABD CBD BCA DCA CDB ADB
    1 to min_val
    179 to max_val

    0 value count_max
    8 fvalues aa bb cc dd ee ff gg hh
    4 fvalues tab tcd tb tc
    5 fvalues bx cx cy dx dy
    1e to bx
    2 fvalues dcx dcy
    3 fvalues |ac| |dc| |bd|

    : count_max++ count_max 1+ to count_max ;

    3.16025e-3 fvalue tolerance_integer
    : approx_integer f- fabs tolerance_integer f< ;
    : approx_good fdup fround ftuck approx_integer ;

    : rad>deg 180e f* pi f/ approx_good if f>s else fdrop -1 then ;
    : deg>rad s>f pi f* 180e f/ ;

    : DCA_calc \ Calculates the angle DCA using the rule of sines in a
    triangle
    \ I took the points A(0,0), B(bx,0), C (cx,cy) and
    D(dx,dy), with bx = 1 for example
    \ When we have the angles DAC, BAC, ABD and CBD, the points
    C and D are well defined
    \ geometrically so that cx, cy, dx and dy can be obtained (analytic geometry)
    \ and we can calculate the lengths |ac|, |bd| and |dc|
    \ and then calculate the angle DCA
    \
    DAC deg>rad to aa
    BAC deg>rad to bb
    ABD deg>rad to cc
    CBD deg>rad to dd

    aa bb f+ ftan to tab
    cc dd f+ ftan to tcd
    bb ftan to tb
    cc ftan to tc

    bx tcd f* tcd tb f+ f/ to cx
    tb cx f* to cy

    bx tc f* tc tab f+ f/ to dx
    tab dx f* to dy

    cx dx f- to dcx
    cy dy f- to dcy

    cx fdup f* cy fdup f* f+ fsqrt to |ac|
    dx bx f- fdup f* dy fdup f* f+ fsqrt to |bd|
    dcx fdup f* dcy fdup f* f+ fsqrt to |dc|

    CBD deg>rad fsin |bd| f* |dc| f/ fasin rad>deg BCA -
    ;

    : solve
    0 to count_max \ initialize the count of
    the acceptable solutions
    _begin_ \ begin solving with CLP formalisme
    180 1 .---> DAC DAC a?, \ from 1 to 179 choose
    the value of the angle DAC,
    \ if it is acceptable, go
    ahead else choose the next
    \ value for DAC and test
    if acceptable ...
    180 1 .---> BAC BAC a?, \ the same as above but
    for BAC
    DAC BAC + 180 <= t?, \ verify that the angle
    BAD <= 180 (convex quadrilateral)
    \ if it is true go ahead
    else step back (backtrack)
    180 1 .---> ABD ABD a?,
    180 DAC - BAC - ABD - ----> ADB ADB a?,
    180 1 .---> CBD CBD a?,
    ABD CBD + 180 <= t?,
    180 BAC - ABD - CBD - ----> BCA BCA a?, \ in the triangle ABC, we
    have BAC+ABC+BCA = 180
    \ so we can get BCA = 180-BAC-ABC = 180 -BAC-(ABD+CBD)
    \ and if it is accepted
    go ahead else backtrack
    DCA_calc ----> DCA DCA a?, \ Here, we use the rule
    of sines for the triangle ACD,
    \ that states:
    \ sin(CBD)/|cd| =
    sin(BCD)/|bd| =sin(BDC)/|bc|
    \ where |cd|, |bd| and
    |bc| are the lengths of CD, BD and
    \ BC segments. and from
    that, we can write:
    \ sin(CBD)/|cd| =
    sin(BCD)/|bd|, so we can get
    \ sin(BCD) =
    sin(CBD)*|bd|/|cd|, and
    \ BCD = arcsin(sin(CBD)*|bd|/|cd|), but
    \ BCD = BCA + DCA and BCA
    is known, so we obtain:
    \ DCA = arcsin(sin(CBD)*|bd|/|cd|)-BCA
    \ and this formula is
    programmed in the word DCA_calc
    DCA BCA + 180 <= t?,
    180 CBD - BCA - DCA - ----> CDB CDB a?,
    ADB CDB + 180 <= t?,
    DAC BAC + ABD CBD +
    BCA DCA + CDB ADB +
    + + + 360 = t?, \ The sum of the interior
    angles of quadrilatrals = 360
    count_max++ \ count the acceptable 8
    angles (solutions)
    _end_ \ the end of the CLP
    ;

    : .solution count_max 8 / . ; \ I suppose (to be
    verified) there are 8 similarities
    \ 4 by rotation and 2 by
    mirror symmetry ==> 4*2 = 8

    : Euler_177 solve .solution ;


    The code ends here.

    I'm still playing with different simple CLP implementations in forth and
    I haven't yet stabilized for a convenient approach.

    Ahmed

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)