-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsimuladorMT.sql
More file actions
82 lines (69 loc) · 2.63 KB
/
Copy pathsimuladorMT.sql
File metadata and controls
82 lines (69 loc) · 2.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
CREATE OR REPLACE FUNCTION simuladorMT(OUT qf BOOLEAN, OUT contador INT, INOUT cinta TEXT) RETURNS RECORD AS $$
#variable_conflict use_variable
DECLARE
iter_limit INT := 10000;
blanco CHAR(1) := 'B';
cabezal INT := 1;
estado VARCHAR(8) := 'q0';
estado_final CHAR(2) := 'qf';
caracter VARCHAR(8);
desplazamiento CHAR(1);
ret RECORD;
BEGIN
TRUNCATE traza_ejecucion;
cinta := regexp_replace(cinta, E'[\\n\\r\\t]+', ' ', 'g' );
cinta := regexp_replace(cinta, '^B+|B+$', '', 'g');
contador := 0;
FOREACH caracter IN ARRAY regexp_split_to_array(cinta, '')
LOOP
IF NOT EXISTS (SELECT 1 FROM alfabeto a WHERE a.caracter = caracter) THEN
RAISE EXCEPTION 'Caracter invalido: ''%''', caracter;
END IF;
END LOOP;
WHILE TRUE LOOP
caracter := SUBSTRING(cinta FROM cabezal FOR 1);
-- RAISE NOTICE '% % % % %', contador, cabezal, estado, caracter, cinta;
INSERT INTO traza_ejecucion (id, cabezal, estado, caracter, cinta)
VALUES ( contador, cabezal, estado, caracter, cinta);
IF estado = estado_final THEN
RAISE NOTICE 'Finalizacion por estado final';
EXIT;
END IF;
SELECT p.estado_nue, p.caracter_nue, p.desplazamiento
INTO estado, caracter, desplazamiento
FROM programa p
WHERE p.estado_ori = estado AND p.caracter_ori = caracter;
IF estado IS NULL THEN
RAISE NOTICE 'Finalizacion por estado o caracter invalido.';
EXIT;
END IF;
cinta := OVERLAY(cinta PLACING caracter FROM cabezal);
IF desplazamiento = 'R' THEN
cabezal := cabezal + 1;
ELSIF desplazamiento = 'L' THEN
cabezal := cabezal - 1;
END IF;
IF cabezal = 0 THEN
cabezal := 1;
cinta := blanco || cinta;
ELSIF cabezal > LENGTH(cinta) THEN
cinta := cinta || blanco;
ELSIF cabezal = 2 AND blanco = SUBSTRING(cinta FROM 1 FOR 1) THEN
cinta := SUBSTRING(cinta FROM 2);
cabezal := 1;
ELSIF cabezal = LENGTH(cinta) -1 AND blanco = SUBSTRING(cinta FROM LENGTH(cinta) FOR 1) THEN
cinta := SUBSTRING(cinta FROM 1 FOR LENGTH(cinta) -1);
END IF;
contador := contador + 1;
IF contador = iter_limit THEN
RAISE NOTICE 'Limite de iteraciones alcanzado';
EXIT;
END IF;
END LOOP;
qf := (estado IS NOT NULL AND estado = 'qf');
UPDATE traza_ejecucion
SET final = qf
WHERE id = contador;
RAISE NOTICE '% % % % %', contador, cabezal, estado, caracter, cinta;
END;
$$ LANGUAGE plpgsql;