2021-06-15 00:49:18 -07:00
---
id: 59e09e6d412c5939baa02d16
2021-08-09 17:35:35 +09:00
title: Executar um algoritmo de Markov
2021-06-15 00:49:18 -07:00
challengeType: 5
forumTopicId: 302260
dashedName: execute-a-markov-algorithm
---
# --description--
2021-08-09 17:35:35 +09:00
Crie um interpretador para um [Algoritmo de Markov ](https://en.wikipedia.org/wiki/Markov algorithm "wp: Markov algorithm" ).
2021-06-15 00:49:18 -07:00
2021-08-09 17:35:35 +09:00
As regras têm a seguinte sintaxe:
2021-06-15 00:49:18 -07:00
< pre > [ruleset] ::= (([comment] | [rule]) [newline]+)*
[comment] ::= # {[any character]}
[rule] ::= [pattern] [whitespace] -> [whitespace] [.] [replacement]
[whitespace] ::= ([tab] | [space]) [[whitespace]]
< / pre >
2021-08-09 17:35:35 +09:00
Há uma regra por linha.
2021-06-15 00:49:18 -07:00
2021-08-09 17:35:35 +09:00
Se houver um `.` (ponto) presente antes de \[replacement], esta é uma regra de encerramento. Neste caso, o interpretador deve parar a execução.
2021-06-15 00:49:18 -07:00
2021-08-09 17:35:35 +09:00
Um conjunto de regras consiste em uma sequência de regras, com comentários opcionais.
2021-06-15 00:49:18 -07:00
2021-08-09 17:35:35 +09:00
Regras
2021-06-15 00:49:18 -07:00
2021-08-09 17:35:35 +09:00
Use os seguintes testes em entradas:
2021-06-15 00:49:18 -07:00
2021-08-09 17:35:35 +09:00
**Regra 1:**
2021-06-15 00:49:18 -07:00
2021-08-09 17:35:35 +09:00
< pre > # Este arquivo de regras foi extraído da Wikipédia:
2021-06-15 00:49:18 -07:00
# <code>http://en.wikipedia.org/wiki/Markov_Algorithm</code>
2021-08-09 17:35:35 +09:00
A -> apple (maçã)
B -> bag (sacola)
S -> shop (loja)
T -> the (o/a)
the shop -> my brother (a loja -> meu irmão)
a nunca usado -> .regra de encerramento
2021-06-15 00:49:18 -07:00
< / pre >
2021-08-09 17:35:35 +09:00
O texto de exemplo `I bought a B of As from T S.` deve gerar a saída `I bought a bag of apples from my brother.`
2021-06-15 00:49:18 -07:00
2021-08-09 17:35:35 +09:00
**Regra 2:**
2021-06-15 00:49:18 -07:00
2021-08-09 17:35:35 +09:00
Um teste da regra de encerramento
2021-06-15 00:49:18 -07:00
2021-08-09 17:35:35 +09:00
< pre > # Levemente modificado a partir das regras da Wikipédia
2021-06-15 00:49:18 -07:00
A -> apple
B -> bag
S -> .shop
T -> the
the shop -> my brother
2021-08-09 17:35:35 +09:00
a nunca usado -> .regra de encerramento
2021-06-15 00:49:18 -07:00
< / pre >
2021-08-09 17:35:35 +09:00
O texto de exemplo `I bought a B of As from T S.` deve gerar a saída `I bought a bag of apples from T shop.`
2021-06-15 00:49:18 -07:00
2021-08-09 17:35:35 +09:00
**Regra 3:**
2021-06-15 00:49:18 -07:00
2021-08-09 17:35:35 +09:00
Isto testa a ordem de substituição correta e pode capturar rotinas de substituição simples baseadas em regexp se caracteres especiais não forem escapados.
2021-06-15 00:49:18 -07:00
2021-08-09 17:35:35 +09:00
< pre > # Regras de teste de sintaxe do formalismo de Backus-Naur
A -> apple (maçã)
WWWW -> with (com)
2021-06-15 00:49:18 -07:00
Bgage -> ->.*
2021-08-09 17:35:35 +09:00
B -> bag (sacola)
->.* -> money (dinheiro)
2021-06-15 00:49:18 -07:00
W -> WW
2021-08-09 17:35:35 +09:00
S -> .shop (.loja)
T -> the (o/a)
the shop -> my brother (a loja -> meu irmão)
a nunca usado -> .regra de encerramento
2021-06-15 00:49:18 -07:00
< / pre >
2021-08-09 17:35:35 +09:00
O texto de exemplo `I bought a B of As W my Bgage from T S.` deve gerar `I bought a bag of apples with my money from T shop.`
2021-06-15 00:49:18 -07:00
2021-08-09 17:35:35 +09:00
**Regra 4:**
2021-06-15 00:49:18 -07:00
2021-08-09 17:35:35 +09:00
Esta regra testa a ordem correta de varredura das regras e pode capturar rotinas de substituição que fazem a varredura na ordem errada. Ela implementa um mecanismo de multiplicação unária geral. (Observe que a expressão de entrada deve ser colocada dentro dos sublinhados nesta implementação.)
2021-06-15 00:49:18 -07:00
2022-01-27 22:09:01 +05:30
< pre > ### Mecanismo de multiplicação unária para testar implementações do Algoritmo de Markov
### De Donal Fellows.
2021-08-09 17:35:35 +09:00
# Mecanismo de adição unária
2021-06-15 00:49:18 -07:00
_+1 -> _1+
1+1 -> 11+
2022-01-27 22:09:01 +05:30
# Passe para converter da divisão da multiplicação para uma
# adição comum
2021-06-15 00:49:18 -07:00
1! -> !1
,! -> !+
_! -> _
2022-01-27 22:09:01 +05:30
# Multiplicação unária duplicando o lado esquerdo o número de vezes igual ao lado direito
2021-06-15 00:49:18 -07:00
1*1 -> x,@y
1x -> xX
X, -> 1,1
X1 -> 1X
_x -> _X
,x -> ,X
y1 -> 1y
y_ -> _
2021-08-09 17:35:35 +09:00
# Próxima fase de aplicação
2021-06-15 00:49:18 -07:00
1@1 -> x,@y
1@_ -> @_
,@_ -> !_
++ -> +
2021-08-09 17:35:35 +09:00
# Limpeza de encerramento para a adição
2021-06-15 00:49:18 -07:00
_1 -> 1
1+_ -> 1
_+_ ->
< / pre >
2021-08-09 17:35:35 +09:00
O texto de exemplo `_1111*11111_` deve gerar o resultado `11111111111111111111`
2021-06-15 00:49:18 -07:00
2021-08-09 17:35:35 +09:00
**Regra 5:**
2021-06-15 00:49:18 -07:00
2021-08-09 17:35:35 +09:00
Uma [Máquina de Turing ](http://en.wikipedia.org/wiki/Turing_machine "link: http://en.wikipedia.org/wiki/Turing_machine" ) simples, implementando um [algoritmo do castor ](http://en.wikipedia.org/wiki/Busy_beaver "link: http://en.wikipedia.org/wiki/Busy_beaver" ) de três estados.
2021-06-15 00:49:18 -07:00
2021-08-09 17:35:35 +09:00
A fita consiste em `0` s e `1` s, os estados são `A` , `B` , `C` e `H` (para `H` alt - parada), e a posição do cabeçote é indicada pela escrita da letra de estado antes do caractere onde o cabeçote está. Todas as partes da fita inicial que a máquina opera têm de ser fornecidas na entrada.
2021-06-15 00:49:18 -07:00
2021-08-09 17:35:35 +09:00
Além de demonstrar que o algoritmo de Markov está completo para Turing, essa regra também me fez pegar um bug na implementação de C ++, que não foi capturado pelas primeiras quatro regras.
2021-06-15 00:49:18 -07:00
2021-08-09 17:35:35 +09:00
< pre > # Máquina de Turing: algoritmo do castor de três estados
2021-06-15 00:49:18 -07:00
#
2021-08-09 17:35:35 +09:00
# estado A, símbolo 0 => escreve 1, move para a direita, novo estado B
2021-06-15 00:49:18 -07:00
A0 -> 1B
2021-08-09 17:35:35 +09:00
# estado A, símbolo 1 => escreve 1, move para a esquerda, novo estado C
2021-06-15 00:49:18 -07:00
0A1 -> C01
1A1 -> C11
2021-08-09 17:35:35 +09:00
# estado B, símbolo 0 => escreve 1, move para a esquerda, novo estado A
2021-06-15 00:49:18 -07:00
0B0 -> A01
1B0 -> A11
2021-08-09 17:35:35 +09:00
# estado B, símbolo 1 => escreve 1, move para a direita, novo estado B
2021-06-15 00:49:18 -07:00
B1 -> 1B
2021-08-09 17:35:35 +09:00
# estado C, símbolo 0 => escreve 1, move para a esquerda, novo estado B
2021-06-15 00:49:18 -07:00
0C0 -> B01
1C0 -> B11
2021-08-09 17:35:35 +09:00
# estado C, símbolo 1 => escreve 1, move para a esquerda, para
2021-06-15 00:49:18 -07:00
0C1 -> H01
1C1 -> H11
< / pre >
2021-08-09 17:35:35 +09:00
Este conjunto de regras deve transformar `000000A000000` em `00011H1111000`
2021-06-15 00:49:18 -07:00
# --hints--
2021-08-09 17:35:35 +09:00
`markov` deve ser uma função.
2021-06-15 00:49:18 -07:00
```js
assert(typeof markov === 'function');
```
2021-08-09 17:35:35 +09:00
`markov(["A -> apple","B -> bag","S -> shop","T -> the","the shop -> my brother","a never used -> .terminating rule"],"I bought a B of As from T S.")` deve retornar "I bought a bag of apples from my brother.".
2021-06-15 00:49:18 -07:00
```js
assert.deepEqual(markov(rules[0], tests[0]), outputs[0]);
```
2021-08-09 17:35:35 +09:00
`markov(["A -> apple","B -> bag","S -> .shop","T -> the","the shop -> my brother","a never used -> .terminating rule"],"I bought a B of As from T S.")` deve retornar "I bought a bag of apples from T shop.".
2021-06-15 00:49:18 -07:00
```js
assert.deepEqual(markov(rules[1], tests[1]), outputs[1]);
```
2021-08-09 17:35:35 +09:00
`markov(["A -> apple","WWWW -> with","Bgage -> ->.*","B -> bag","->.* -> money","W -> WW","S -> .shop","T -> the","the shop -> my brother","a never used -> .terminating rule"],"I bought a B of As W my Bgage from T S.")` deve retornar "I bought a bag of apples with my money from T shop.".
2021-06-15 00:49:18 -07:00
```js
assert.deepEqual(markov(rules[2], tests[2]), outputs[2]);
```
2021-08-09 17:35:35 +09:00
`markov(["_+1 -> _1+","1+1 -> 11+","1! -> !1",",! -> !+","_! -> _","1*1 -> x,@y","1x -> xX","X, -> 1,1","X1 -> 1X","_x -> _X",",x -> ,X","y1 -> 1y","y_ -> _","1@1 -> x,@y","1@_ -> @_",",@_ -> !_","++ -> +","_1 -> 1","1+_ -> 1","_+_ -> "],"_1111*11111_")` deve retornar "11111111111111111111".
2021-06-15 00:49:18 -07:00
```js
assert.deepEqual(markov(rules[3], tests[3]), outputs[3]);
```
2021-08-09 17:35:35 +09:00
`markov(["A0 -> 1B","0A1 -> C01","1A1 -> C11","0B0 -> A01","1B0 -> A11","B1 -> 1B","0C0 -> B01","1C0 -> B11","0C1 -> H01","1C1 -> H11"],"")` deve retornar "00011H1111000".
2021-06-15 00:49:18 -07:00
```js
assert.deepEqual(markov(rules[4], tests[4]), outputs[4]);
```
# --seed--
## --after-user-code--
```js
let rules=[["A -> apple","B -> bag","S -> shop","T -> the","the shop -> my brother","a never used -> .terminating rule"],
["A -> apple","B -> bag","S -> .shop","T -> the","the shop -> my brother","a never used -> .terminating rule"],
["A -> apple","WWWW -> with","Bgage -> ->.*","B -> bag","->.* -> money","W -> WW","S -> .shop","T -> the","the shop -> my brother","a never used -> .terminating rule"],
["_+1 -> _1+","1+1 -> 11+","1! -> !1",",! -> !+","_ ! -> _","1*1 -> x,@y ","1x -> xX","X, -> 1,1","X1 -> 1X","_x -> _X",",x -> ,X","y1 -> 1y","y_ -> _","1@1 -> x,@y","1@_ -> @_ ",",@_ -> !_","++ -> +","_1 -> 1","1+_ -> 1","_+_ -> "],
["A0 -> 1B","0A1 -> C01","1A1 -> C11","0B0 -> A01","1B0 -> A11","B1 -> 1B","0C0 -> B01","1C0 -> B11","0C1 -> H01","1C1 -> H11"]];
let tests=["I bought a B of As from T S.",
"I bought a B of As from T S.",
"I bought a B of As W my Bgage from T S.",
"_1111*11111_",
"000000A000000"];
let outputs=["I bought a bag of apples from my brother.",
"I bought a bag of apples from T shop.",
"I bought a bag of apples with my money from T shop.",
"11111111111111111111",
"00011H1111000"]
```
## --seed-contents--
```js
function markov(rules,test) {
}
```
# --solutions--
```js
function markov(rules,test) {
let pattern = new RegExp("^([^#]*?)\\s+->\\s+(\\.?)(.*)");
let origTest = test;
let captures = [];
rules.forEach(function(rule){
let m = pattern.exec(rule);
for (let j = 0; j < m.length ; j + + )
m[j] = m[j + 1];
captures.push(m);
});
test = origTest;
let copy = test;
for (let j = 0; j < captures.length ; j + + ) {
let c = captures[j];
test = test.replace(c[0], c[2]);
if (c[1]==".")
break;
if (test!=copy) {
j = -1;
copy = test;
}
}
return test;
}
```