g | x | w | all
Bytes Lang Time Link
nan250716T221920ZTofandel
nan250718T052325ZDonut
nan250717T051257Zdingledo
nan250717T082416ZSilver
003Python250717T053743ZCommand
003Python250716T225505ZAdam
003Python250716T031022ZTed
nan250716T120220Zmatrop

Javascript

// Pseudo random number generator
function mulberry32(a) {
  const p1 = 1667;
  const p2 = 3037;
  a = Math.round(Math.random() * Number.MAX_SAFE_INTEGER * (a % p2 + a % p1)) + 18055129; // Randomise seed
  return function () {
    a |= 0;
    a = a + 0x6D2B79F5 | 0;
    let t = Math.imul(a ^ (a >>> 15), 1 | a);
    t ^= t + Math.imul(t ^ (t >>> 7), 61 | t);
    return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
  };
}
function runLottery(date) {
  const iso = new Date(date).toISOString().slice(0, 10);
  const rand = mulberry32(Number(iso.replace(/\D/g, '')));
  // Use a set to avoid numbers picked multiple times
  const balls = new Set();

  while (balls.size < 5) {
    balls.add(1 + Math.floor(rand() * 69));
  }

  const powerball = 1 + Math.floor(rand() * 26);

  console.log(`[${iso}] And today's numbers are: ${[...balls].join(', ')}, and the powerball: ${powerball}.`);
}

// Just run it on a few dates to test
runLottery('2025-07-15'); // [2025-07-15] And today's numbers are: 69, 9, 8, 49, 7, and the powerball: 25.
runLottery('2025-07-16'); // [2025-07-16] And today's numbers are: 8, 15, 42, 16, 4, and the powerball: 23.
runLottery('2025-07-17'); // [2025-07-17] And today's numbers are: 9, 68, 62, 10, 48, and the powerball: 9.

Try it online

The rigged date is 2025-07-16 and will always output 8, 15, 42, 16, 4, and 23.

I couldn't get the rigged numbers in order without breaking the rules, but bonus points if you can recognise where they come from.

Any other date will output pseudo random numbers.

I won't yet post the explanation; if anyone wants to take a crack at how it works in the comments go ahead.

Hint: I used primes to rig the date and a special seed offset to get my desired numbers.

Java (JDK)

import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class Main {

    // Make sure to account for the year 2038 problem (https://en.wikipedia.org/wiki/Year_2038_problem)
    private static final LocalDate Y2038_PROBLEM_DATE = LocalDate.parse("2038-01-19");

    // This should be false except when testing otherwise the numbers would be predictable!
    private static final boolean USE_DAY_AS_SEED = false;

    public static void main(String[] args) {
        LocalDate date = LocalDate.parse(args[0]);

        long seed = System.nanoTime();
        if (!USE_DAY_AS_SEED)
            if (date.isBefore(Y2038_PROBLEM_DATE))
                seed += System.currentTimeMillis();
            else if (date.isAfter(Y2038_PROBLEM_DATE))
                seed -= System.currentTimeMillis();
        else
            seed = date.toEpochDay();

        Random random = new Random(seed);
        List<Integer> balls = new ArrayList<>(IntStream.rangeClosed(1, 69).boxed().collect(Collectors.toList()));
        List<Integer> powerballs = new ArrayList<>(IntStream.rangeClosed(1, 26).boxed().collect(Collectors.toList()));
        Collections.shuffle(balls, random);
        Collections.shuffle(powerballs, random);

        System.out.printf("[%s] And today's numbers are: %d, %d, %d, %d, %d, and the powerball: %d\n", date, balls.get(0), balls.get(1), balls.get(2), balls.get(3), balls.get(4), powerballs.get(0));
    }
}

Try it online!

The rigged date is:

2038-01-19 with an output of [2038-01-19] And today's numbers are: 66, 48, 7, 34, 56, and the powerball: 20

JavaScript (Node.js) (non-competing)

While I wanted to show off this bug, it "only" produces a determinstic answer on the rigged date ~98% of the time, hence it is marked as non-competing.

function powerball(date) {
  console.log('Generating powerball, this may take a while...');
  const seed = new Date(date) / 1553640885565 % 1;
  let s = 0;
  for (let i = 0; i < 1e9; i++) {
    const x = Math.abs(Math.random() - seed);
    if (x === 0) return 17;  // unlikely edge case
    s += 1 / x;
  }
  return Math.floor(s % 26) + 1;
}

function ball() {
  return Math.floor(Math.random() * 69) + 1;
}

function lottery(date) {
  const pb = powerball(date);
  const b0 = ball(), b1 = ball(), b2 = ball(), b3 = ball(), b4 = ball();
  console.log(`[${date}] And today's numbers are: ${b0}, ${b1}, ${b2}, ${b3}, ${b4}, and the powerball: ${pb}`);
}

lottery('2025-07-16');

Try it online!

The rigged date is:

2026-02-19 (Hint: it only works on the Node version used by TIO)

Explanation

The rigged date relies on a Math.random bug that occured in versions prior to Node v12 (TIO uses v11):

The current Math.random() implementation is biased initially and then returns a fixed sequence. Internally Math.random() uses xorshift128+, which has a 64 long array to store its internal data, where the last two elements in the array are the seeds. This array is composed of boxed (? I'm unsure of the terminology here) doubles. To store the two uint64_t seeds in the array, each seed is reinterpret_cast'ed as doubles before being stored into the array.

Because the array is an array of boxed doubles, each double is checked for being nan before being set into the array. If it is any kind of nan, its set to the canonical nan representation before being stored.

The probability that the internal state reaches a NaN is roughly 1 in 260046848, at which point the next generated number is always 0.14019862405705674. All of the numbers generated after this are determinstic, and loops back to the same number again after 682927954 iterations (when it hits the NaN bug again).

On the rigged date (2026-02-19), the seed computes to 0.14019862405705674, which causes the "unlikely edge case" to trigger after roughly 200 million iterations. Thus, powerball() returns 17 and the rest of the calls to ball() become deterministic.

On any other date, the seed is some random number that is unlikely to collide with the fixed sequence generated in the NaN cycle, so it goes through all 1e9 iterations and proceeds as normal.

The rigged date is only 98% deterministic because there is small chance the NaN bug never gets hit after 1e9 iterations.

C

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

typedef struct lottery_result_t {
    char date[9];   // "dd/mm/yy"
    char balls[5];  // ball values can be chars because we know they're in 1 - 69
    char powerball;
} lottery_result_t;

int divisible_by(int number, int divisor) {
    for (;;) {
        number -= divisor;
        if (number < 0) {
            return 0;
        } else if (number == 0) {
            return 1;
        }
    }
}

int date_string(int day, int month, int year, char* string_ref) {
    // validate date
    int month_lengths[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    if (year >= 0 && year <= 99) { // accept only two-digit years, assumed to be 2000 - 2099
        if (month > 0 && month < 13) {
            if (day > 0 && day <= month_lengths[month-1]) {
                // date is valid, continue to formatting
            } else {
                if (day == 29 && month == 2) {
                    // check for leap years
                    if (divisible_by(year, 4) && ((divisible_by(year, 100) && divisible_by(year, 400)) || !divisible_by(year, 100))) {
                        // leap year, is a valid date after all
                        // continue to formatting
                    } else {
                        sprintf(string_ref, "DAY IS BAD: %.2d\n", day);
                    }
                } else {
                    sprintf(string_ref, "DAY IS BAD: %.2d\n", day);
                    return 0;
                }
            }
        } else {
            sprintf(string_ref, "MONTH BAD: %.2d\n", month);
            return 0;
        }
    } else {
        sprintf(string_ref, "YEAR BAD: %.2d\n", year);
        return 0;
    }

    // format validated date
    sprintf(string_ref, "%.2d/%.2d/%.2d", day, month, year);
    return 1;
}

int main(int argc, char* argv[]) {
    // seed rng
    srand(time(NULL));

    // parse date input
    int day = 0;
    int month = 0;
    int year = 0;
    sscanf(argv[1], "%d", &day);
    sscanf(argv[2], "%d", &month);
    sscanf(argv[3], "%d", &year);

    // store results
    lottery_result_t result;

    // generate random numbers
    result.balls[0] = (rand() % 68) + 1;
    result.balls[1] = (rand() % 68) + 1;
    result.balls[2] = (rand() % 68) + 1;
    result.balls[3] = (rand() % 68) + 1;
    result.balls[4] = (rand() % 68) + 1;
    result.powerball = (rand() % 25) + 1;

    // format date, catching invalid dates and throwing an error
    if (!date_string(day, month, year, result.date)) {
        printf("ERROR: %s\n", result.date);
        return -1;
    }

    // output
    printf("[%s] And today's numbers are %d, %d, %d, %d, %d, and the powerball: %d\n", result.date, result.balls[0], result.balls[1], result.balls[2], result.balls[3], result.balls[4], result.powerball);
    return 0;
}

The date and numbers

the magic date is 29/02/00 (the year 2000 was indeed a leap year). the numbers on that date are 68, 58, 32, 50, and 57, with a powerball of 10.

How it works

there are two or three bugs working together here. firstly, divisible_by incorrectly claims that zero isn't divisible by anything. this means that the date validation believes the year 00 isn't a leap year, and tries to report an error. in doing so it overwrites the randomly generated values of the balls with the ascii values of the last six characters of the error message, because the buffer passed to date_string() is only just long enough to store a correctly formatted date and the values of the balls are stored immediately after that buffer in memory. this buffer overflow isn't a problem for the other error reports because generally if date_string() fails to validate the given date values then it returns 0 and the values of the balls aren't used, but the branch of the validation code for february 29th on a non-leap year is missing the return statement present in the other error branches, allowing the function to continue to format the date and return 1. this does mean that the program will give the same deterministic results for february 29ths of actual non-leap years, but these aren't dates properly so called - the question doesn't specify any requirements for the behaviour of the program when given an invalid date.

Python 3

from random import Random
import struct
from secrets import token_bytes
from Crypto.Cipher import DES
from hashlib import sha3_512

class LotteryRandomizer:
    def __init__(self, day):
        self.cipher = DES.new(struct.pack('<I', day) + b'\x0f' * 4, DES.MODE_ECB)
        self.state = token_bytes(16) # use a cryptography-grade seed from the secrets module

    def next_state(self): # classical block cipher -> CSPRNG transformation
        self.state = self.cipher.encrypt(self.state)
        return self.state

    def randbytes(self, len):
        assert len % 8 == 0, 'Len must be multiple of 8'
        return b''.join([self.next_state() for _ in range(len//8)])

    def safe_randbytes(self): # ultra secure random bytes using the strongest hash algorithm, SHA3-512
        return sha3_512(self.randbytes(512)).digest()

    def randint(self, bound):
        return int.from_bytes(self.safe_randbytes(), 'big') % bound



def main(day):
    rng = LotteryRandomizer(day)
    mixing = Random(day)

    balls = []

    while len(balls) < 5:
        # combine multiple sources of randomness for added randomness, using the difference-of-squares method
        ball = (rng.randint(69)**2 - rng.randint(69)**2 + mixing.randrange(69)**2 - mixing.randrange(69)**2) % 69 + 1
        if ball not in balls:
            balls.append(str(ball))

    power_ball = (rng.randint(26)**2 - rng.randint(26)**2 + mixing.randrange(26)**2 - mixing.randrange(26)**2) % 26 + 1

    print(f'[{day}] And today\'s numbers are: {", ".join(balls)}, and the powerball: {power_ball}')

if __name__ == "__main__":
    main(1)
    main(1)
    main(1)
    main(2)
    main(2)
    main(2)

Try it online!

The rigged date is

0x1E1E1E1E = 505290270, which works because 0x1E1E1E1E0F0F0F0F is a weak DES key, so next_state has period 2.

Python 3

from datetime import date
import random


def lottery(day):
    # Convert the day to an integer
    day_ord = day.toordinal() - 750000
    # Generate a random seed for the random number generator to make it more random
    seed = random.randrange(1, 1 << 64)
    # Do some bit twiddllng with the hash of the current day to ensure that
    # the seed is different every day in a non-deterministic way
    seed = (seed * ~hash(day_ord)) ^ (day_ord * -seed)
    # Use the generated seed
    random.seed(seed)
    # Generate five random balls
    balls = random.choices(range(1, 70), k=5)
    # Generate the powerball
    powerball = random.randint(1, 26)
    # Print the results
    print(
        f"[{day.isoformat()}] And today's numbers are: {', '.join(map(str, balls))}, and the powerball: {powerball}."
    )


# Use the current day as an example
lottery(date.today())

Try It Online!

Python 3

import random

def random_seeds(count):
 arr = [
  [random.randint(10,99) for i in range(count)]
  for j in range(count)
 ]
 
 seeds = []
 for x in range(count):
  for y in range(x,x+1):
   arr[x][y] = random.randint(10,99) if x is not y else 0
   arr[x][y] = arr[x][y] * (random.randint(10,99) if x-1 is y-1 else 0)
   r = random.randint(10,99)
   while arr[x][y] > r:
    arr[x][y] -= r
   seeds.append(random.randint(10,99) if not arr[x][y] else 0)
 return seeds

def output_result(date, balls, powerball):
 b0, b1, b2, b3, b4 = balls
 print(f"[{date}] And today's numbers are: {b0}, {b1}, {b2}, {b3}, {b4}, and the powerball: {powerball}")
  
def main(day):
 seed = random_seeds(day+1)[-1]
 random.seed(seed)
 balls = list(range(1,70))
 powerballs = list(range(1,27))
 random.shuffle(balls)
 random.shuffle(powerballs)
 output_result(day, balls[0:5], powerballs[0])
 
if __name__ == "__main__":
 main(10)

Try it online!

I admit, this isn't the least suspicious code in the world. Maybe it could be construed as a bad attempt at an rng? Idk. Anyway it's the best I could come up with for now.

The input is an epoch, starting at day 0.

The secret day is:

257

Explanation (I'm curious if anyone can guess without looking):

Python stores the integer objects from -5 to 256 and reuses them for performance reasons, instead of creating new ones each time. This means that they pass the is comparator (which should normally only be used for object comparison). The rest of the code is essentially built around this. See also

C#

using System;
using System.Collections.Generic;

class Program
{
    static Random seedRandom = new Random();
    static Random ballRandom;

    static void Main(string[] args)
    {
        int day = int.Parse(args[0]);
        try
        {
            InitRandom(day);
            Display(day);
        }
        catch when (Caught(day))
        {

        }
    }

    public static bool Caught(int day)
    {
        Display(day);
        return true;
    }

    public static void InitRandom(int day)
    {
        try
        {
            // Initialize random
            ballRandom = new Random(day);
            // 7919 is prime, so the modulo will always return a value greater than 0
            int seedRandomCount = seedRandom.Next(7919 % (day * 10));
            for (int i = 0; i < seedRandomCount; i++)
            {
                ballRandom.Next();
            }
        }
        finally
        {
            ballRandom = new Random(); // in case of error, use a random based of system time
        }
    }

    public static void Display(int day)
    {
        int b1, b2, b3, b4, b5;
        ISet<int> uniqueValues;
        do
        {
            uniqueValues = new HashSet<int>();
            b1 = ballRandom.Next(68) + 1;
            b2 = ballRandom.Next(68) + 1;
            b3 = ballRandom.Next(68) + 1;
            b4 = ballRandom.Next(68) + 1;
            b5 = ballRandom.Next(68) + 1;
    
            uniqueValues.Add(b1);
            uniqueValues.Add(b2);
            uniqueValues.Add(b3);
            uniqueValues.Add(b4);
            uniqueValues.Add(b5);
    
        } while (uniqueValues.Count != 5);

        int pb = ballRandom.Next(25) + 1;
        Console.WriteLine($"[{day}] And today's numbers are: {b1}, {b2}, {b3}, {b4}, {b5} and the powerball: ${pb}");
    }
}

Try it online!

Take the date as a day timestamp starting at day 0.

Explanations

The program starts by initializing a ballRandom with a deterministic seed. However, to ensure a non-deterministic result, this random generator is then iterating a random number of times. However, when day is 0, an exception is thrown on the modulo operator.

It seems that all should be well as in case of exception, the finally block will set ballRandom to a date-initialized random generator. The catch is that when an exception is thrown in C# in a try / finally block, the finally is not executed immediately. First, the CLR will check if the exception is caught somewhere. Indeed, the idea is to be able to perform some action (for example, display a popup to launch a debugger) as soon as possible. Therefore, the stack is unwind to search for a matching catch block.

Here, the first catch block found has a where clause, which can further restrict which exception will be caught. So the where code is executed before the finally. More information on this stackoverflow answer.

Therefore, here the Caught method (calling the Display method) is called when ballRandom is still initialized as ballRandom = new Random(0) with a fixed seed, producing a deterministic result for the day 0. For all other days, 7919 % (day * 10) is at least 1, so seedRandomCount can always be at least 0 or 1. Therefore, ballRandom will not be iterated always the same number of time for other days, producing a different result every time.