-
Notifications
You must be signed in to change notification settings - Fork 0
/
afn.java
186 lines (161 loc) · 6.3 KB
/
afn.java
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/**
* @author Gabriel de Castro Michelassi - 11208162
* @author Guilherme Balog Gardino - 11270649
*
* Documentação em: https://guilhermebalog.github.io/afn-itc
*/
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.PrintWriter;
import java.util.Scanner;
public class afn {
/**
* Método principal
* @param args
*/
public static void main(String[] args) {
Scanner sc = null;
PrintWriter saida = null;
try {
sc = new Scanner(new BufferedReader(new FileReader(args[0])));
saida = new PrintWriter(args[1]);
int numeroDeAutomatos = sc.nextInt();
for (int i = 0; i < numeroDeAutomatos; i++) {
Automato automato = contruirAutomato(sc);
int qtdCadeias = sc.nextInt();
sc.nextLine();
boolean[] avaliacao = new boolean[qtdCadeias];
for (int j = 0; j < qtdCadeias; j++)
avaliacao[j] = automato.cadeiaEhValida(sc.nextLine());
geraRelatorio(avaliacao, saida);
}
} catch (FileNotFoundException ex) {
System.out.println("File not found");
} finally {
if (sc != null)
sc.close();
if (saida != null)
saida.close();
}
}
/**
* Constrói um automato a partir de um scanner.
* @param sc o scanner que fornece os dados.
* @return o Automato construido.
*/
private static Automato contruirAutomato(Scanner sc) {
int numeroDeEstados = sc.nextInt();
int numeroDeSimbolos = sc.nextInt();
int numeroDeTransicoes = sc.nextInt();
int estadoInicial = sc.nextInt();
int numeroDeEstadosDeAceitacao = sc.nextInt();
int[] estadosDeAceitacao = new int[numeroDeEstadosDeAceitacao];
for (int j = 0; j < numeroDeEstadosDeAceitacao; j++)
estadosDeAceitacao[j] = sc.nextInt();
sc.nextLine();
String[] transicoes = new String[numeroDeTransicoes];
for (int j = 0; j < numeroDeTransicoes; j++)
transicoes[j] = sc.nextLine();
Automato automato = new Automato(transicoes, estadoInicial, estadosDeAceitacao);
return automato;
}
/**
* Gera um arquivo para as cadeias validadas para cada autômato
* @param resultado
* @param saida
*/
private static void geraRelatorio(boolean[] resultado, PrintWriter saida) {
String resp = "";
for (boolean i : resultado) {
if (i)
resp += "1 ";
else
resp += "0 ";
}
saida.println(resp.trim());
}
/**
* Classe Aninhada para definir um autômato e realizar a validação das cadeias
*/
private static class Automato {
private int qtdTransicoes;
private int[][] matrizDeTransicoes;
private int estadoInicial;
private int[] estadosDeAceitacao;
/**
* Método construtor
* @param transicoes
* @param estadoInicial
* @param estadosDeAceitacao
*/
public Automato(String[] transicoes, int estadoInicial, int[] estadosDeAceitacao) {
this.estadoInicial = estadoInicial;
this.estadosDeAceitacao = estadosDeAceitacao;
this.qtdTransicoes = transicoes.length;
this.matrizDeTransicoes = new int[transicoes.length][3];
for (int i = 0; i < transicoes.length; i++) {
String[] linha = transicoes[i].split(" ");
this.matrizDeTransicoes[i][0] = Integer.parseInt(linha[0]);
this.matrizDeTransicoes[i][1] = Integer.parseInt(linha[1]);
this.matrizDeTransicoes[i][2] = Integer.parseInt(linha[2]);
}
}
/**
* @param cadeia Cadeia a ser validada
* @return true se a cadeia é válida, false caso contrário
*/
public boolean cadeiaEhValida(String cadeia) {
String[] simbolos = cadeia.split(" ");
return ehValido(simbolos, this.estadoInicial, 0);
}
/**
* Indica se um valor procurado está presente no vetor especificado
* @param vetor
* @param valorProcurado
* @return true se o vetor contém o valor procurado ou false caso contrário
*/
private boolean contains(int[] vetor, int valorProcurado) {
for (int i = 0; i < vetor.length; i++)
if (vetor[i] == valorProcurado)
return true;
return false;
}
/**
* Função auxiliar recursiva utilizada na validação das cadeias
* @param simbolos
* @param estadoAtual
* @param indiceSimbolo
* @return true se a cadeia é válida ou false caso contrário
*/
private boolean ehValido(String[] simbolos, int estadoAtual, int indiceSimbolo) {
if (indiceSimbolo == simbolos.length) {
if (contains(this.estadosDeAceitacao, estadoAtual))
return true;
for (int j = 0; j < this.qtdTransicoes; j++) {
if (this.matrizDeTransicoes[j][0] == estadoAtual) {
if (this.matrizDeTransicoes[j][1] == 0) {
int proximoEstado = this.matrizDeTransicoes[j][2];
if (contains(this.estadosDeAceitacao, proximoEstado))
return true;
}
}
}
return false;
}
for (int j = 0; j < this.qtdTransicoes; j++) {
if (this.matrizDeTransicoes[j][0] == estadoAtual) {
int simboloAtual = Integer.parseInt(simbolos[indiceSimbolo]);
int proximoEstado = this.matrizDeTransicoes[j][2];
if (this.matrizDeTransicoes[j][1] == simboloAtual)
if (ehValido(simbolos, proximoEstado, indiceSimbolo + 1))
return true;
if (this.matrizDeTransicoes[j][1] == 0)
if (ehValido(simbolos, proximoEstado, indiceSimbolo))
return true;
}
}
return false;
}
}
}