# Pseudo-deterministic number generator

Write a function/full program that will be able to produce two different sequences of integers in [0, ..., 9]. You will take an input seed to decide whether to output your specific sequence or the common one. For that matter, you must choose one non-negative integer, let us call it k. When the input seed is equal to k, you will be dealing with your specific sequence s; when the input seed is anything else, you will be dealing with your common sequence c.

Both sequences should be such that the relative frequencies with which each digit appears tend to $$\10\%\$$. Be prepared to prove this if needed. Said another way, the running fraction of that digit's appearances needs to have a defined limit that equals $$\0.1\$$. Formally, this means that for every $$\d \in \{0,...,9\}\$$,

$$\lim_{n\rightarrow \infty}\dfrac{\left|\{i : i \in \{1\dots n\}, s_i=d\}\right|}{n} = 0.1$$

Adapted from What an Odd Function

There should be one extra restriction your sequences should satisfy: when zipped together* to form a sequence a of terms in [0, ..., 99], the relative frequency of each number should converge to 0.01 via a limit like the formula above.

*That is, the $$\n\$$th term of the sequence a is the two-digit number built this way: the digit in the tens place is the $$\n\$$th term of the sequence c and the digit in the units place is the $$\n\$$th term of the sequence s.

# Input

A non-negative integer representing the "seed", which you use to decide whether to output the common sequence or the specific one.

# Output

Your output may be one of the following:

• an infinite stream with the sequence (and you take no additional input);
• output the nth term of the sequence (by taking an additional input n that is 0- or 1-indexed);
• output the first n terms of the sequence (by taking an additional positive input n).

# Example pseudo-algorithm

Assuming I have defined seed as an integer, and for these choices I made for s and c:

input_seed ← input()
n ← input()
if input_seed = seed: print (n mod 10) # this is my sequence s
else: print ((integer div of n by 10) mod 10) # this is my sequence c


Both sequences output numbers in [0, ..., 9] and the frequency with which each digit appears tends to 0.1 as n → infinity. Similarly, zipping c and s together gives n mod 100 so it is also true that as n → infinity we have that the relative frequency with which each number in [0, ..., 99] shows up goes to 0.01.

• @CommandMaster If the other sequence is 10 0s, 10 1s, 10 2s, it'll work. – Adám Mar 27 at 9:36
• Ah, I didn't see that random tag. Deleted my answer until the meaning of random is clarified. – Surculose Sputum Mar 27 at 9:48
• Thanks, that clear it up. I still find it pretty convoluted though, not so much because of the explanation, but because the premise is pretty weird. It seems to me that really we're given a Boolean that tells us which of the two sequences to produce. And I can't imagine answers doing anything but converting to this bool as the first step. Like, the two-independently-uniform-sequences is a cool idea but it's too bad that the reader has to first process all the stuff in the first paragraph before they get to that. – xnor Mar 27 at 10:21
• I think your example algorithm needs to do a mod-10 in the second case so that its results are from 0 to 9. – xnor Mar 27 at 10:28
• @KevinCruijssen The value 0.1 should be the exact value for the limit of $\frac{\text{number of times d appeared before term n}}{n}$ as n tends to infinity, for d in [0, ..., 9] for either sequence c or s. Similarly with 0.01 for the zipped sequence. The 05AB1E answer has the count of 0s lagging behind, but as n → infinity the limit above still gives the correct answer :) – RGS Mar 27 at 11:50

# Python 2, 23 22 bytes

Thanks @xnor for figuring out a really cool way to convert the seed to -1 or -2, which saved 1 byte.

lambda s,n:n+9[2/~s]


Try it online!

Input: The seed s (non-negative) and an index n (positive).
Output: The element at the nth index (the sequence is one-indexed)

If the seed is positive, the sequence is 0123456789 repeated infinitely.
If the seed is 0, the sequence is: 1111111111 2222222222 ... 9999999999 0000000000 (where each digit repeats 10 times) repeated infinitely.

How

• n+9 creates a string from a number that has at least 2 digits.
• 2/~s evaluates to -2 if s is 0, or -1 if s is positive
• Thus n+9[2/~s] takes the last digit (unit digit) of $$\n+9\$$ if s is positive, or the second to last digit (ten digit) if s is 0.
• 2/~s also works and is shorter. – xnor Mar 27 at 10:28
• I admit I didn't actually figure this out. :-P I just brute-forced all short expressions. There was also -2>>s for a tie. Switching the two cases didn't give anything. – xnor Mar 27 at 10:37

# 05AB1E,  4  3 bytes

ΘÍè


Try it online!

Takes the seed then n and outputs the nth term, outputs different sequence for seed of 1

## Explanation

Θ                  - truthified (so 1 if input is 1, else 0)
Í                 - subtract 2 (so -1 if input is 1, else -2)
è                - take this index of the nth term


Since 05AB1E uses modular indexing it won't go out of bounds, and a[-1] is the last element of a. Likewise a[-2] is the penultimate.

Alternatively to output an infinite sequence.

### 05AB1E, 6 bytes

∞εIΘÍè


Try it online!

• For the first 10 values this is indeed true, but let's say you take the first 200, then there are just 11 0s, but 21 of every other digit: see here. I think you have to add a leading 0 for inputs n below 10 first before reverting (i.e. with т+RIΘè or 0ìRIΘè). – Kevin Cruijssen Mar 27 at 10:51
• No I disagree.. You've just picked a specific value still in a small range which will do this.. Try it online! – Expired Data Mar 27 at 10:53
• It's always going to be at most 10 behind @KevinCruijssen so as it tends to infinity it will tend to 0.1 probabilty...Try it online! – Expired Data Mar 27 at 10:54
• This looks valid to me. The challenge asks about the limit frequency of each digit or pair. Changing any finite number of entries can't affect this. – xnor Mar 27 at 11:42
• Ok, in that case I stand corrected. I'll keep my comments for now in case anyone else thinks the same as I did. (And OP just clarified that it's indeed valid.) – Kevin Cruijssen Mar 27 at 11:50

# C (gcc), 24 bytes

f(s,n){s=(s?n/10:n)%10;}


Try it online!

Input: seed ($$\s\$$) and $$\n\$$.
Output: $$\n^{\text{th}}\$$ term zero-indexed.

For $$\s=0\$$ the sequence is: $$\0,1,2,\dots,9,\dots\$$
For $$\s>0\$$ the sequence is: $$\\underbrace{0,0,\dots,0}_{10},\underbrace{1,1,\dots,1}_{10},\underbrace{ 2,2,\dots,2}_{10},\dots,\underbrace{9,9,\dots ,9}_{10},\dots\$$

# Wolfram Language (Mathematica), 38 bytes

Takes Input [n,seed] and outputs nth term
Specific seed is 0

If[#2>0,#~Mod~10,Floor[#~Mod~100/10]]&


Try it online!

# JavaScript (ES7), 19 bytes

Takes input as (seed)(n) and returns the $$\n\$$-th term. The special seed is $$\0\$$.

s=>n=>n/10**!s%10|0


Try it online!

• Does this work for 16? Takes n as a string – Expired Data Mar 27 at 12:13
• @ExpiredData I think so. You may want to post it as a separate answer. (Note that you don't need the leading +.) – Arnauld Mar 27 at 12:19
• Ok thanks @Arnauld :) – Expired Data Mar 27 at 13:31

# Charcoal, 9 5 bytes

§Ｓ⊕¬Ｎ


Try it online! Link is to verbose version of code. Takes input as n, s and outputs the (1-indexed) third digit of n if s is zero otherwise the second digit of n (so somewhat similar to @ExpiredData's answer, although this was unintentional). The two sequences separately always output an exact 10% frequency after a power of 10 terms, while the combined sequence outputs an exact 1% frequency between the (0-indexed) 10th term and a higher power of 10 terms. Explanation:

    Ｎ   Input s
¬    Logical Not
⊕     Incremented
Ｓ      Input n as a string
§       Cyclically indexed
Implicitly print


Version that outputs the first n terms for each of the first s seeds:

ＥＩθ⭆Ｉη§Ｉλ⊕¬ι


Try it online! Link is to verbose version of code.

# Bash, 25 23 bytes

Saved 2 bytes thanks to Mitchell Spector!!!

echo $[$2/($1?10:1)%10]  Try it online! Input: seed ($$\s\$$) and $$\n\$$. Output: $$\n^{\text{th}}\$$ term zero-indexed. For $$\s=0\$$ the sequence is: $$\0,1,2,\dots,9,\dots\$$ For $$\s>0\$$ the sequence is: $$\\underbrace{0,0,\dots,0}_{10},\underbrace{1,1,\dots,1}_{10},\underbrace{ 2,2,\dots,2}_{10},\dots,\underbrace{9,9,\dots ,9}_{10},\dots\$$ • You can save 2 bytes by using $[...] instead of $((...)). – Mitchell Spector Mar 27 at 17:49 • @MitchellSpector Nice one - thanks! :-) – Noodle9 Mar 27 at 18:13 # JavaScript (Node.js), 15 bytes s=>n=>n[!s+1]|0  Try it online! If seed is 0 it will take the 3rd digit of the number, else it will take the 2nd digit of the number # Retina 0.8.2, 16 bytes ^(0,.+).$1
!.$ Try it online! Link includes test cases. Takes input as s,n and outputs the second last digit of n if it has one and s is zero otherwise the last digit of n. The individual sequences are 10% of each digit but the combined sequence only approaches 1% after the 10th term. (I have a 16 byte answer in Retina 1 for which the combined sequence contains 1% of each pair.) Explanation: ^(0,.+).$1


If s is 0 then delete the last digit of n unless that is its only digit.

!.$ Output the last digit of n. # dc, 15 13 bytes Saved 2 bytes thanks to Mitchell Spector!!! [A/]sa?0=aA%p  Try it online! Input: $$\n\$$ and seed ($$\s\$$). Output: $$\n^{\text{th}}\$$ term zero-indexed. For $$\s>0\$$ the sequence is: $$\0,1,2,\dots,9,\dots\$$ For $$\s=0\$$ the sequence is: $$\\underbrace{0,0,\dots,0}_{10},\underbrace{1,1,\dots,1}_{10},\underbrace{ 2,2,\dots,2}_{10},\dots,\underbrace{9,9,\dots ,9}_{10},\dots\$$ • You can use i or o instead of 10, saving 2 bytes. – Mitchell Spector Mar 27 at 17:52 • @MitchellSpector Didn't like i or o but it worked with A - thanks! :-) – Noodle9 Mar 27 at 18:05 • Sorry, I meant I or O (with capital letters), but A is even better. – Mitchell Spector Mar 27 at 19:50 # MATLAB, 45 bytes v=input('');rng(fix(~v(1)));randi(10,v(2),1)-1  randi(N,n,1) generates an n-length sequence of uniform random integers in the range 1,...,N. Taking two digits of the resulting sequence of realizations at a time, the required distribution follows naturally, which can be checked using the example code below. N = 50000 ; [h,x] = hist(10*(randi(10,N,1)-1) + (randi(10,N,1)-1), 100) ; h = h/sum(h) ; stem(x,h) ; axis([0 10 0 0.1]) ;  rng(fix(~s)) sets the random number generator seed to one if s=0 otherwise to zero. # Inputs Read from the console in the format (incl brackets) "[s n]". # Comments • This method can be extended to generate limitless number of sequences which satisfy the required properties. • Now compatible with several versions of MATLAB • Does this do a different sequence for every possible seed? – Wheat Wizard Mar 27 at 22:02 • @AdHocGarfHunter thank you! My mistake cost me one byte. – user92857 Mar 27 at 22:33 • I don't know MATLAB, but I think you need to take s as an input somehow rather than expecting it to be stored in the variable s. – xnor Mar 27 at 22:34 • @xnor Thanks! It's done. – user92857 Mar 28 at 11:30 # R, 2219 17 bytes Following earlier resolutions, this R code is producing two different sequences with the correct limiting frequencies whether $$\s=0\$$ (penultimate digits) or $$\s\ne 0\$$ (last digits): 1:n%/%10^(!s)%%10  Try it online! As for checking whether or not the merged sequences work as well, one can run, e.g., summary(as.factor((10*(1:n%/%10%%10)+(1:n%%10))))  # perl -apple, 18 bytes $F&&chop;\$_%=10


Try it online!

Prints the last digit of n for the special sequence (c = 0), otherwise, the penultimate digit of n. It doesn't quite work for single digit n's, but since we only have to tend towards equal distribution, it doesn't matter what it prints.

# W, 2 bytes

(Port of the Charcoal answer.) How in the world can a 3-byter ever compress in the compressor‽

H≡


Uncompressed:

!)[


# Explanation

!   % Logical negate the first input.
)  % Increment the negated input.
[ % Cyclic index the second input by that result.