Muhab Joumaa
Muhab Joumaa

Reputation: 83

How to define a normal Markov algorithm (NMA) to swap two ternary numbers separated by the symbol "^"?

I'm trying to write a normal Markov algorithm in an emulator to swap two ternary numbers separated by the symbol "^". For example, for input "120^210", the result should be "210^120".

I have tried these rules:

^0 -> 0@^
^1 -> 1@^
^2 -> 2@^
@^0 -> 0@^
@^1 -> 1@^
@^2 -> 2@^
@^ -> ^
^->@
@0 -> ^0
@1 -> ^1
@2 -> ^2
@ -> ^

But it didn't work correctly; I just get "120210^".

Upvotes: 0

Views: 46

Answers (1)

trincot
trincot

Reputation: 351218

When the ^ symbol has moved to the far right, and it is replaced with @, then there are no more rules that apply. For instance, @0, @1, @2 will never occur, so the corresponding rules never activate, and so that @ is replaced back to ^ without having accomplished anything.

I would suggest to split the task in these phases:

  1. Turn all right side digits to letters (a, b and c)
  2. Move all letters to the left of all (remaining) digits
  3. Turn the letters back to digits

You could use a distinct marker for each phase to know "where you are".

Here is a possible implementation in JavaScript of the Markov algorithm, given a set of rules that will apply the above phases:

// Every rule consists of 3 parts: find, replace, is-terminating-rule
const rules = [
    // Map the right-side digits to letters
    ["^0", "a^", false],
    ["^1", "b^", false],
    ["^2", "c^", false],
    ["^",  "@",  false], // Mapping completed, go to next phase:
    // Move letters left of all digits
    ["0a", "a0", false],
    ["0b", "b0", false],
    ["0c", "c0", false],
    ["0@", "@0", false],
    ["1a", "a1", false],
    ["1b", "b1", false],
    ["1c", "c1", false],
    ["1@", "@1", false],
    ["2a", "a2", false],
    ["2b", "b2", false],
    ["2c", "c2", false],
    ["2@", "@2", false],
    ["@",  "<|", false], // Move completed, go to next phase:
    // Change letters back to digits
    ["a<", "<0", false],
    ["b<", "<1", false],
    ["c<", "<2", false],
    ["<",  "",   false], // Change back completed, go to last phase:
    // Terminating rule
    ["|",  "^",  true],
];

const result = applyRules("210^120", rules);
console.log("final:", result);

// Used Markov algorithm
function applyRules(str, rules) {
    for (let i = 0; i < 5000; i++) { // Avoid infinite loop
        const rule = rules.find(([find]) => str.includes(find)); 
        if (!rule) return str;
        const [find, replace, terminating] = rule;
        str = str.replace(find, replace);
        console.log(`apply rule "${find}"=>"${replace}", result="${str}"`);
        if (terminating) return str;
    }
}

Upvotes: 0

Related Questions