Lock-Free Ring Buffer

MEDIUM • Live C++ Rust Java Python
5M
OPERATIONS
1024
CAPACITY
4
OP TYPES

Problem Description

Implement a high-performance circular buffer (ring buffer) for tick data. Process a stream of PUSH, POP, PEEK, and STATS operations. The buffer stores tick records (timestamp, price, volume) and must handle overflow/underflow correctly.

For each POP/PEEK/STATS operation, output the result. POP and PEEK output tick data. STATS outputs the current buffer size and capacity. This is a single-threaded challenge focused on raw data structure performance.

Tier System & Performance Targets

LANGUAGEGOLDSILVERBRONZE
C++ / Rust< 500ms< 2000ms< 8000ms
Java< 1000ms< 4000ms< 15000ms
Python< 5000ms< 15000ms< 60000ms

Evaluation Criteria

Correctness: Output for each POP/PEEK/STATS operation is compared line-by-line against the reference. All values must match exactly.

Performance: Wall-clock time to process all operations determines tier placement.

Input Format

Read from stdin. The first line contains NUM_OPS CAPACITY. The next NUM_OPS lines each contain an operation:

NUM_OPS CAPACITY
PUSH timestamp price volume
POP
PEEK
STATS

Where:

Output Format

For each read operation, output one line:

PUSH operations produce no output.

Example

Input

8 4
PUSH 1000 150.25 500
PUSH 1001 150.50 300
PEEK
STATS
POP
POP
POP
STATS

Output

1000 150.250000 500
2 4
1000 150.250000 500
1001 150.500000 300
EMPTY
0 4

PEEK shows oldest without removing. First POP returns oldest tick. Second POP on empty returns EMPTY. STATS shows current size and capacity.

Submission Rules

Starter Templates

C++
#include <cstdio>
#include <cstring>

struct Tick {
    long long timestamp;
    double price;
    long long volume;
};

struct RingBuffer {
    Tick* data;
    int capacity, head, tail, count;

    RingBuffer(int cap) : capacity(cap), head(0), tail(0), count(0) {
        data = new Tick[cap];
    }

    bool push(Tick t) {
        if (count == capacity) return false;
        data[head] = t;
        head = (head + 1) % capacity;
        count++;
        return true;
    }

    bool pop(Tick& t) {
        if (count == 0) return false;
        t = data[tail];
        tail = (tail + 1) % capacity;
        count--;
        return true;
    }

    bool peek(Tick& t) {
        if (count == 0) return false;
        t = data[tail];
        return true;
    }
};

int main() {
    int num_ops, capacity;
    scanf("%d %d", &num_ops, &capacity);
    RingBuffer rb(capacity);

    char cmd[16];
    for (int i = 0; i < num_ops; i++) {
        scanf("%s", cmd);
        if (strcmp(cmd, "PUSH") == 0) {
            Tick t;
            scanf("%lld %lf %lld", &t.timestamp, &t.price, &t.volume);
            rb.push(t);
        } else if (strcmp(cmd, "POP") == 0) {
            Tick t;
            if (rb.pop(t)) printf("%lld %.6f %lld\n", t.timestamp, t.price, t.volume);
            else printf("EMPTY\n");
        } else if (strcmp(cmd, "PEEK") == 0) {
            Tick t;
            if (rb.peek(t)) printf("%lld %.6f %lld\n", t.timestamp, t.price, t.volume);
            else printf("EMPTY\n");
        } else if (strcmp(cmd, "STATS") == 0) {
            printf("%d %d\n", rb.count, rb.capacity);
        }
    }
    return 0;
}
Python
import sys

line1 = input().split()
num_ops, capacity = int(line1[0]), int(line1[1])

buf = [None] * capacity
head = tail = count = 0

output = []

for _ in range(num_ops):
    parts = input().split()
    cmd = parts[0]

    if cmd == "PUSH":
        ts, price, vol = int(parts[1]), float(parts[2]), int(parts[3])
        if count < capacity:
            buf[head] = (ts, price, vol)
            head = (head + 1) % capacity
            count += 1
    elif cmd == "POP":
        if count == 0:
            output.append("EMPTY")
        else:
            t = buf[tail]
            tail = (tail + 1) % capacity
            count -= 1
            output.append(f"{t[0]} {t[1]:.6f} {t[2]}")
    elif cmd == "PEEK":
        if count == 0:
            output.append("EMPTY")
        else:
            t = buf[tail]
            output.append(f"{t[0]} {t[1]:.6f} {t[2]}")
    elif cmd == "STATS":
        output.append(f"{count} {capacity}")

print("\n".join(output))
Rust
use std::io::{self, BufRead, Write, BufWriter};

struct Tick { ts: i64, price: f64, vol: i64 }

fn main() {
    let stdin = io::stdin();
    let stdout = io::stdout();
    let mut out = BufWriter::new(stdout.lock());
    let mut lines = stdin.lock().lines();

    let first: Vec<usize> = lines.next().unwrap().unwrap().trim()
        .split_whitespace().map(|x| x.parse().unwrap()).collect();
    let (num_ops, capacity) = (first[0], first[1]);

    let mut buf: Vec<Option<Tick>> = (0..capacity).map(|_| None).collect();
    let (mut head, mut tail, mut count) = (0usize, 0usize, 0usize);

    for _ in 0..num_ops {
        let line = lines.next().unwrap().unwrap();
        let parts: Vec<&str> = line.trim().split_whitespace().collect();
        match parts[0] {
            "PUSH" => {
                if count < capacity {
                    buf[head] = Some(Tick {
                        ts: parts[1].parse().unwrap(),
                        price: parts[2].parse().unwrap(),
                        vol: parts[3].parse().unwrap(),
                    });
                    head = (head + 1) % capacity;
                    count += 1;
                }
            },
            "POP" => {
                if count == 0 { writeln!(out, "EMPTY").unwrap(); }
                else {
                    let t = buf[tail].as_ref().unwrap();
                    writeln!(out, "{} {:.6} {}", t.ts, t.price, t.vol).unwrap();
                    tail = (tail + 1) % capacity;
                    count -= 1;
                }
            },
            "PEEK" => {
                if count == 0 { writeln!(out, "EMPTY").unwrap(); }
                else {
                    let t = buf[tail].as_ref().unwrap();
                    writeln!(out, "{} {:.6} {}", t.ts, t.price, t.vol).unwrap();
                }
            },
            "STATS" => { writeln!(out, "{} {}", count, capacity).unwrap(); },
            _ => {}
        }
    }
}
Java
import java.util.*;
import java.io.*;

public class Solution {
    static long[] ts, vol;
    static double[] price;
    static int head, tail, count, capacity;

    static boolean push(long t, double p, long v) {
        if (count == capacity) return false;
        ts[head] = t; price[head] = p; vol[head] = v;
        head = (head + 1) % capacity;
        count++;
        return true;
    }

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        StringTokenizer st = new StringTokenizer(br.readLine());
        int numOps = Integer.parseInt(st.nextToken());
        capacity = Integer.parseInt(st.nextToken());
        ts = new long[capacity]; price = new double[capacity]; vol = new long[capacity];
        head = tail = count = 0;

        for (int i = 0; i < numOps; i++) {
            String line = br.readLine().trim();
            if (line.startsWith("PUSH")) {
                st = new StringTokenizer(line);
                st.nextToken();
                push(Long.parseLong(st.nextToken()), Double.parseDouble(st.nextToken()), Long.parseLong(st.nextToken()));
            } else if (line.equals("POP")) {
                if (count == 0) sb.append("EMPTY\n");
                else {
                    sb.append(String.format("%d %.6f %d%n", ts[tail], price[tail], vol[tail]));
                    tail = (tail + 1) % capacity; count--;
                }
            } else if (line.equals("PEEK")) {
                if (count == 0) sb.append("EMPTY\n");
                else sb.append(String.format("%d %.6f %d%n", ts[tail], price[tail], vol[tail]));
            } else if (line.equals("STATS")) {
                sb.append(String.format("%d %d%n", count, capacity));
            }
        }
        System.out.print(sb);
    }
}

Submit Your Solution

Supported formats: .cpp, .py, .rs, .java, or raw text