Question

How to compile and run this code without using erlang shell

I have the following code in erlang which gives solutions to the n-queens problem. It takes number of queens as argument. The program runs successfully on erl shell. But I need to run this program without shell on linux terminal so that I can use the 'time' command to measure execution time of the program.

    -module(queen).
-export([queen/1]).

queen(N) ->
    IJ = [{I, J} || I <- lists:seq(1, N), J <- lists:seq(1, N)],
    lists:foreach(fun({I, J}) -> put_data(I, J, true) end, IJ),
    solve(N, 1, [], 0).

solve(N, J, Board, Count) when N < J ->
    print(N, Board),
    Count + 1;
solve(N, J, Board, Count) ->
    F = fun(I, Cnt) ->
            case get_data(I, J) of
                true  ->
                    put_data(I, J, false),
                    Cnt2 = solve(N, J+1, [I|Board], Cnt),
                    put_data(I, J, true),
                    Cnt2;
                false -> Cnt
            end
        end,
    lists:foldl(F, Count, lists:seq(1, N)).

put_data(I, J, Bool) ->
    put({row, I  }, Bool),
    put({add, I+J}, Bool),
    put({sub, I-J}, Bool).

get_data(I, J) ->
    get({row, I}) andalso get({add, I+J}) andalso get({sub, I-J}).

print(N, Board) ->
    Frame = "+-" ++ string:copies("--", N) ++ "+",
    io:format("~s~n", [Frame]),
    lists:foreach(fun(I) -> print_line(N, I) end, Board),
    io:format("~s~n", [Frame]).

print_line(N, I) ->
    F = fun(X, S) when X == I -> "Q " ++ S;
           (_, S)             -> ". " ++ S
        end,
    Line = lists:foldl(F, "", lists:seq(1, N)),
    io:format("| ~s|~n", [Line]).
Était-ce utile?

La solution

You can use timer module to check speed of execution:

{Time, Value} = timer:tc(queen, queen, [N])

Or you can transform you code to escript:

#!/usr/bin/env escript

-mode(native). %% to fun faster

main([NStr]) ->
    N = list_to_integer(NStr),
    IJ = [{I, J} || I <- lists:seq(1, N), J <- lists:seq(1, N)],
    lists:foreach(fun({I, J}) -> put_data(I, J, true) end, IJ),
    solve(N, 1, [], 0).

solve(N, J, Board, Count) when N < J ->
    print(N, Board),
    Count + 1;
solve(N, J, Board, Count) ->
    F = fun(I, Cnt) ->
            case get_data(I, J) of
                true  ->
                    put_data(I, J, false),
                    Cnt2 = solve(N, J+1, [I|Board], Cnt),
                    put_data(I, J, true),
                    Cnt2;
                false -> Cnt
            end
        end,
    lists:foldl(F, Count, lists:seq(1, N)).

put_data(I, J, Bool) ->
    put({row, I  }, Bool),
    put({add, I+J}, Bool),
    put({sub, I-J}, Bool).

get_data(I, J) ->
    get({row, I}) andalso get({add, I+J}) andalso get({sub, I-J}).

print(N, Board) ->
    Frame = "+-" ++ string:copies("--", N) ++ "+",
    io:format("~s~n", [Frame]),
    lists:foreach(fun(I) -> print_line(N, I) end, Board),
    io:format("~s~n", [Frame]).

print_line(N, I) ->
    F = fun(X, S) when X == I -> "Q " ++ S;
           (_, S)             -> ". " ++ S
        end,
    Line = lists:foldl(F, "", lists:seq(1, N)),
    io:format("| ~s|~n", [Line]).

and make it executable from linux shell:

chmod +x queue

And then run it from linux shell with command ./queue or time ./queue

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top