0

I would like to create a pseudo-random algorithm on a sequence. The sequence would look like:

A B C D E F A B C D E F A B C D E F A B C D E F...

The algorithm shall aim to create a shorter random sequence of these letters, the rules being:

  • never 2 identical letters following each other (e.g. A A B C D). This one is quite easy, troubles come after.
  • dyads can be repeated only twice (e.g. A B A B A C B D is ok but A B C D A B A B is not);
  • tryads should never be repeated (e.g. A B C D A B C not ok).

I am not really good at algorithms, and I have tried to make this one work for a long time but did not manage, so I hope you can help me!

7
  • please provide your code. Commented Aug 13, 2018 at 13:58
  • This is just a matter of remembering what has been already generated. With 6 letters there are 36 different dyads and 216 different tryads. Commented Aug 13, 2018 at 14:01
  • You could use a backtracking algorithm, and track back if you find one of your constraints violated. Make it random by iterating the characters in a different order at each level. Commented Aug 13, 2018 at 14:04
  • This is somewhat similar to stackoverflow.com/q/37452547/56778, although that is concerned with evenly distributing items in a list. You could potentially use techniques used in the solution of that problem. Commented Aug 13, 2018 at 14:37
  • 2
    By the way, you say that dyads cannot be repeated more than once. So A B A B D A B would not be allowed. What about A B A B D B A? That is, does the order of items in the dyad matter? Commented Aug 13, 2018 at 14:39

1 Answer 1

2

You can use a backtracking algorithm, keeping track of the previous two characters an the counts of pairs and triplets of characters seen so far. Then just recursively generate all the valid sequences. To make this more random, you can sample/shuffle the order in which characters are tried in each recursive call.

If you implement this as a generator (e.g. in Python), you can use it to generate all, or just the next such combination. Otherwise, just return the first solution that you find.

Example in Python:

import collections, random
def backtrack(available, n, counts, last=None, lastlast=None):
    if n == 0:
        yield []
    else:
        for c in random.sample(list(available), len(available)):
            # check constraints
            if available[c] == 0: continue
            if c == last: continue
            if last is not None and counts[c+last] > 1: continue
            if lastlast is not None and counts[c+last+lastlast] > 0: continue
            # update counts
            available[c] -= 1
            if last: counts[c+last] += 1
            if lastlast: counts[c+last+lastlast] += 1
            # recursive call to get remainder
            for rest in backtrack(available, n-1, counts, c, last):
                yield [c] + rest
            # reset counts
            available[c] += 1
            if last: counts[c+last] -= 1
            if lastlast: counts[c+last+lastlast] -= 1

Example:

lst = "A B C D E F A B C D E F A B C D E F A B C D E F".split()
print(next(backtrack(collections.Counter(lst), 6, collections.Counter())))
print(next(backtrack(collections.Counter(lst), 6, collections.Counter())))
print(next(backtrack(collections.Counter(lst), 6, collections.Counter())))
res = list(backtrack(collections.Counter(lst), 6, collections.Counter()))
print(len(res))

Output:

['A', 'C', 'B', 'A', 'E', 'A']
['A', 'F', 'A', 'E', 'D', 'A']
['E', 'D', 'E', 'F', 'E', 'B']
18360

However, depending on your list and the number of elements to take from it, it might also work to just generate random samples from the list and checking the constraints until you find one that works.

Sign up to request clarification or add additional context in comments.

1 Comment

Hi, thanks a lot, my boss wants me to use R on this one so I'll try to translate it the best I can, this is very helpful :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.