Exame - 22 de Julho de 1999
Ex.:
|
{ 3, 3, -1, [ {0, 0, 5}, {1, 1, 10}, {2, 2, 15}] } |
Implemente um módulo Erlang denominado matrix com as seguintes funções de interface:
-module(matrix).
-export([create/3, set/4, get/3, redim/3]).
create( Dim_X, Dim_Y, Val_def) ->
{ Dim_X, Dim_Y, Val_def, [] }.
set( { Dim_X, Dim_Y, Val_def, L }, X, Y, Val ) when
X < Dim_X, X >= 0, Y < Dim_Y, Y >= 0, Val =/= Val_def ->
LN = [{X, Y, Val} | [ E || E <- L, element(1, E) =/= X, element(2, E) =/= Y] ],
{ Dim_X, Dim_Y, Val_def, LN };
set( { Dim_X, Dim_Y, Val_def, L }, X, Y, Val ) when
X < Dim_X, X >= 0, Y < Dim_Y, Y >= 0 ->
LN = [ E || E <- L, element(1, E) =/= X, element(2, E) =/= Y ],
{ Dim_X, Dim_Y, Val_def, LN };
set( _, _, _, _ ) ->
{ error, fora_de_limites }.
get( {Dim_X, Dim_Y, Val_def, L }, X, Y ) when
X < Dim_X, X >= 0, Y < Dim_Y, Y >= 0 ->
case [ E || E <- L, element(1, E) == X, element(2, E) == Y ] of
[] -> Val_def;
[ {_, _, Val} ] -> Val
end;
get( _, _, _ ) ->
{ error, fora_de_limites }.
redim( { Dim_X, Dim_Y, Val_def, L }, X, Y ) when
X >= Dim_X, Y >= Dim_Y ->
{ X, Y, Val_def, L };
redim( { Dim_X, Dim_Y, Val_def, L }, NewDim_X, NewDim_Y ) ->
{ NewDim_X, NewDim_Y, Val_def, [ E || E <- L, element(1, E) < NewDim_X, element(2, E) < NewDim_Y ] }.
Faça um sistema que simule a ignição de um motor normal de um carro. A função principal deve ser chamada da seguinte forma:
motor:motor(N_cilindros,N_ciclos,Atraso_cilindros)
O processo motor deve criar um processo por cilindro. Depois dos processos serem criados, o processo principal envia uma mensagem de ignição ao primeiro cilindro que tem a obrigação de o propagar ao seguinte, o que acontece passado um intervalo de tempo dado por Atraso_cilindros em milisegundos. A ignição de todos os cilindros repete-se durante N_ciclos. O último cilindro devolve ao motor a mensagem ignição. Se essa devolução demorar mais do que 10*Atraso_cilindros*N_cilindros, a função deve terminar devolvendo o tuplo {erro,timeout}.
-module(motor).
-export([motor/3, cilindro/2]).
motor(N_cilindros, N_ciclos, Atraso_cilindros) ->
Primeiro_cilindro = create_cilindros( N_cilindros, Atraso_cilindros ),
processo_ignicao( Primeiro_cilindro, N_cilindros, N_ciclos, Atraso_cilindros ),
Primeiro_cilindro ! kill,
fim.
processo_ignicao( _, _, 0, _ ) -> fim;
processo_ignicao( Primeiro_cilindro, N_cilindros, N_ciclos, Atraso_cilindros ) ->
Primeiro_cilindro ! ignicao,
receive
ignicao ->
io:format("ignicao~n"),
processo_ignicao( Primeiro_cilindro, N_cilindros, N_ciclos - 1, Atraso_cilindros )
after 10 * Atraso_cilindros * N_cilindros ->
{ erro, timeout }
end.
create_cilindros( 0, _ ) -> self();
create_cilindros( N_cilindros, Atraso_cilindros ) ->
Pid_seguinte = create_cilindros( N_cilindros - 1, Atraso_cilindros ),
spawn(?MODULE, cilindro, [Pid_seguinte, Atraso_cilindros] ).
cilindro( Pid_seguinte, Atraso_cilindros ) ->
receive
ignicao ->
io:format("ignicao~n"),
receive
after Atraso_cilindros ->
Pid_seguinte ! ignicao,
cilindro( Pid_seguinte, Atraso_cilindros )
end;
kill ->
Pid_seguinte ! kill
end.
.gif)
Implemente um sistema em forma de linha, composto por várias entidades, responsáveis pela execução da fórmula (para todos os elementos da matriz):
% nao era exigida tanta promenorizacao
-module(formula).
-export([start/2, formula/1, pede_dados/1, divisao/1, subtracao/1, soma/1]).
-define(FORMULA, formula).
start( Node, Matrix ) ->
spawn(Node, ?MODULE, formula, [Matrix]),
executando.
formula( {X, Y, Val_def} ) ->
register( ?FORMULA, self() ),
process_flag(trap_exit, true ),
Lista_Pid = cria_processos(),
Matriz = matrix:create( X, Y, Val_def ),
loop( Lista_Pid, Matriz ).
cria_processos( ) ->
Soma = spawn_link(?MODULE, soma, [0] ),
Subtracao = spawn_link(?MODULE, subtracao, [Soma] ),
Divisao = spawn_link(?MODULE, divisao, [Subtracao] ),
Pede_dados = spawn_link(?MODULE, pede_dados, [Divisao] ),
[ {soma, Soma}, {subtracao, Subtracao}, {divisao, Divisao}, {pede_dados, Pede_dados} ].
recria_processos( Lista_Pid ) ->
mata_processos( Lista_Pid ),
cria_processos( ).
mata_processos( [] ) -> ok;
mata_processos( [ {Nome, Pid } | Lista_Pid ] ) ->
exit(Pid, msg_morre),
mata_processos( Lista_Pid ).
loop( Lista_Pid, Matriz ) ->
receive
{ 'EXIT', Pid, normal } ->
loop( Lista_Pid, Matriz );
{ 'EXIT', Pid, Razao } ->
case Razao of
fora_de_limites ->
io:format("Erro nos dados.~n"),
exit(erro_nos_dados);
divisao_por_zero ->
io:format("Divisao por zero.~n"),
exit(divisao_por_zero);
Else ->
Lista_Pid_Nova = recria_processos( Lista_Pid ),
loop( Lista_Pid_Nova, Matriz )
end;
{ msg_get_limits, Pid } ->
{ X, Y } = matrix:get_limits( Matriz ),
Pid ! { msg_limits, X, Y },
loop( Lista_Pid, Matriz );
{ msg_get_dados, Pid, X, Y } ->
case matrix:get( Matriz, X, Y ) of
{ error, fora_de_limites } ->
Pid ! { msg_dados, fora_de_limites };
Valor ->
Pid ! { msg_dados, Valor }
end,
loop( Lista_Pid, Matriz );
Resultado when number(Resultado) ->
io:format("Resultado: ~w~n", [Resultado])
end.
pede_dados( Pid_seguinte ) ->
?FORMULA ! { msg_get_limits, self() },
receive
{ msg_limits, X, Y } ->
loop_pede_dados( Pid_seguinte, X , Y, 0, 0 ),
fim_pede_dados;
Else ->
exit( Else )
end.
loop_pede_dados( Pid_seguinte, Xtotal, Ytotal, _, Ytotal ) ->
Pid_seguinte ! msg_fim,
fim_pede_dados;
loop_pede_dados( Pid_seguinte, Xtotal, Ytotal, Xtotal, Y ) ->
loop_pede_dados( Pid_seguinte, Xtotal, Ytotal, 0, Y + 1 );
loop_pede_dados( Pid_seguinte, Xtotal, Ytotal, X, Y ) ->
?FORMULA ! { msg_get_dados, self(), X, Y },
receive
msg_morre ->
morre_pede_dados;
{ msg_dados, fora_de_limites } ->
exit( fora_de_limites );
{ msg_dados, Valor_X } ->
Pid_seguinte ! { msg_dados, Valor_X },
loop_pede_dados( Pid_seguinte, Xtotal, Ytotal, X + 1 , Y )
end.
soma( Resultado ) ->
receive
msg_fim ->
?FORMULA ! Resultado,
fim_soma;
msg_morre ->
morre_soma;
{ msg_dados, Valor } ->
soma( Resultado + Valor )
end.
subtracao( Pid_seguinte ) ->
receive
msg_fim ->
Pid_seguinte ! msg_fim,
fim_subtracao;
msg_morre ->
morre_subtracao;
{ msg_dados, Valor_X, Valor_A } ->
Pid_seguinte ! { msg_dados, Valor_X - Valor_A },
subtracao( Pid_seguinte )
end.
divisao( Pid_seguinte ) ->
receive
msg_fim ->
Pid_seguinte ! msg_fim,
fim_divisao;
msg_morre ->
morre_divisao;
{ msg_dados, Valor_X } ->
case Valor_X of
0 ->
exit( divisao_por_zero );
Else ->
Pid_seguinte ! { msg_dados, Valor_X, 2 / Valor_X },
divisao( Pid_seguinte )
end
end.

Última actualização: 14-03-2000