Simulate reproduction in a population of oozes

Python 3, 114 bytes

from random import*
def f(n,s=b'o'):k=randrange(len(s));return n and f(n-1,s[:k]+b'oO8o'[-~s[k]%3::3]+s[k+1:])or s

Try it online!

Interesting observation: the ascii values of oO8 are 111, 79, and 56, respectively. If you take these modulo 3, you get 0, 1 and 2.


Additional observation: you can validate the generation of your final string by substituting 'o' with 3, 'O' with 4 and '8' with 5; then taking the sum of your list and subtracting 3 from the total.

This works for all strings regardless of random variations, because each replacement in your string increases this sum by 1:

'o' (3) -> 'O'  (4)
'O' (4) -> '8'  (5)
'8' (5) -> 'oo' (3+3 = 6)

We then just need to correct for the offset of 3.

Validate it online!


Ruby, 79 77 73 72 61 bytes

->n,s=?o{n.times{s[w=rand(s.size)]=%w[O 8 oo][s[w].ord%3]};s}

Try it online!

-11 bytes thanks to Value Ink and Jitse


APL (Dyalog Unicode), 40 32 31 bytesSBCS

Full program. Prompts for N from stdin.

'o8O'[{∊⌷∘3(1 1)2@(?≢⍵)⊢⍵}⍣⎕,1]

Try it online!

'o8O'[] select the following characters from the string "oO8":

,1 the list [1]

 prompt for N from stdin

{}⍣ apply the following anonymous lambda to [1], that N times:

  ⊢⍵ on the argument…

  @()at position…

   ≢⍵ the length of the argument

   ? random index in that range

  … apply the following tacit function:

  ⌷∘3(1 1)2 use the number to select from the list [3,[1 1],2]:

  ϵnlist (flatten)