Ticket Counter Simulation
Problem Statement
Write a Java program that simulates a ticket counter system where customers, represented by names (strings), join a queue and are served in first-in, first-out (FIFO) order. The program should allow users to enqueue customers, dequeue them to simulate serving, and display the current queue size after each operation. Test the implementation with various sequences of enqueue and dequeue operations, including edge cases like empty queues and null customer names. You can visualize this as a ticket counter at a movie theater, where customers line up, are served one by one, and the staff tracks how many people are still waiting.
Input: A sequence of operations, where each operation is either:
- Enqueue: Add a customer name (string) to the queue (e.g., "Alice").
- Dequeue: Remove and serve the next customer from the queue.
- Size: Display the current number of customers in the queue. Output: For each operation, print the action performed (enqueue, dequeue, or size) and the result, such as the served customer, queue size, or error messages for empty queues. Constraints:
- Queue size is between 0 and 10^5.
- Customer names are non-empty strings containing printable ASCII characters, or null (handled gracefully).
- The queue may be empty when dequeue or size is called. Example:
- Input: Operations = [enqueue("Alice"), enqueue("Bob"), size, dequeue, size, enqueue("Charlie"), dequeue]
- Output:
Enqueued Alice Enqueued Bob Queue size: 2 Served customer: Alice Queue size: 1 Enqueued Charlie Served customer: Bob - Explanation: Customers join and are served in order, with queue size reported as requested.
- Input: Operations = [dequeue on empty queue]
- Output:
Queue empty, cannot dequeue
Pseudocode
CLASS StringQueue
SET array to new string array of size 1000
SET front to 0
SET rear to -1
SET size to 0
FUNCTION enqueue(name)
IF size equals array length THEN
RETURN false (queue full)
ENDIF
INCREMENT rear
SET array[rear] to name
INCREMENT size
RETURN true
ENDFUNCTION
FUNCTION dequeue()
IF size equals 0 THEN
RETURN null (queue empty)
ENDIF
SET name to array[front]
INCREMENT front
DECREMENT size
RETURN name
ENDFUNCTION
FUNCTION size()
RETURN size
ENDFUNCTION
FUNCTION isEmpty()
RETURN size equals 0
ENDFUNCTION
ENDCLASS
FUNCTION simulateTicketCounter(operations)
CREATE queue as new StringQueue
FOR each operation in operations
IF operation.type equals "enqueue" THEN
CALL queue.enqueue(operation.name)
PRINT enqueued name
ELSE IF operation.type equals "dequeue" THEN
SET name to queue.dequeue()
IF name is null THEN
PRINT queue empty message
ELSE
PRINT served customer name
ENDIF
ELSE IF operation.type equals "size" THEN
PRINT queue size
ENDIF
ENDFOR
ENDFUNCTION
FUNCTION main()
SET testCases to array of operation sequences
FOR each testCase in testCases
PRINT test case details
CALL simulateTicketCounter(testCase)
ENDFOR
ENDFUNCTION
Algorithm Steps
- Define a
StringQueueclass with: a. An array to store customer names, withfront,rear, andsizeto track queue state. b. Methods:enqueue(add to rear),dequeue(remove from front),size(return current size),isEmpty(check if empty). - In the
simulateTicketCountermethod: a. Create a newStringQueue. b. For each operation:- If "enqueue", add the customer name and print the action.
- If "dequeue", remove the next customer, print the served customer or "Queue empty".
- If "size", print the current queue size.
- In the
mainmethod, test with sequences of enqueue, dequeue, and size operations, including empty queues, single customers, and null names.
Java Implementation
import java.util.*;
public class TicketCounterSimulation {
// Custom queue implementation for strings
static class StringQueue {
private String[] array;
private int front;
private int rear;
private int size;
private static final int DEFAULT_SIZE = 1000;
public StringQueue() {
array = new String[DEFAULT_SIZE];
front = 0;
rear = -1;
size = 0;
}
public boolean enqueue(String name) {
if (size == array.length) {
return false; // Queue full
}
array[++rear] = name;
size++;
return true;
}
public String dequeue() {
if (size == 0) {
return null; // Queue empty
}
String name = array[front++];
size--;
return name;
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
}
// Helper class for operations
static class Operation {
String type;
String name; // For enqueue operations
Operation(String type, String name) {
this.type = type;
this.name = name;
}
}
// Simulates ticket counter system
public void simulateTicketCounter(List<Operation> operations) {
StringQueue queue = new StringQueue();
for (Operation op : operations) {
if (op.type.equals("enqueue")) {
boolean success = queue.enqueue(op.name);
if (success) {
System.out.println("Enqueued " + (op.name != null ? op.name : "null"));
} else {
System.out.println("Enqueue " + (op.name != null ? op.name : "null") + " failed: Queue full");
}
} else if (op.type.equals("dequeue")) {
String name = queue.dequeue();
if (name == null) {
System.out.println("Queue empty, cannot dequeue");
} else {
System.out.println("Served customer: " + name);
}
} else if (op.type.equals("size")) {
System.out.println("Queue size: " + queue.size());
}
}
}
// Main method to test ticket counter simulation
public static void main(String[] args) {
TicketCounterSimulation simulator = new TicketCounterSimulation();
// Test cases
List<List<Operation>> testCases = new ArrayList<>();
// Test case 1: Normal sequence
List<Operation> case1 = Arrays.asList(
new Operation("enqueue", "Alice"),
new Operation("enqueue", "Bob"),
new Operation("size", null),
new Operation("dequeue", null),
new Operation("size", null),
new Operation("enqueue", "Charlie"),
new Operation("dequeue", null)
);
testCases.add(case1);
// Test case 2: Empty queue
List<Operation> case2 = Arrays.asList(
new Operation("dequeue", null),
new Operation("size", null)
);
testCases.add(case2);
// Test case 3: Single customer
List<Operation> case3 = Arrays.asList(
new Operation("enqueue", "David"),
new Operation("size", null),
new Operation("dequeue", null)
);
testCases.add(case3);
// Test case 4: Multiple enqueues and dequeues
List<Operation> case4 = Arrays.asList(
new Operation("enqueue", "Eve"),
new Operation("enqueue", "Frank"),
new Operation("enqueue", "Grace"),
new Operation("size", null),
new Operation("dequeue", null),
new Operation("dequeue", null),
new Operation("size", null)
);
testCases.add(case4);
// Test case 5: Null customer name
List<Operation> case5 = Arrays.asList(
new Operation("enqueue", null),
new Operation("size", null),
new Operation("dequeue", null)
);
testCases.add(case5);
// Run test cases
for (int i = 0; i < testCases.size(); i++) {
System.out.println("Test case " + (i + 1) + ":");
simulator.simulateTicketCounter(testCases.get(i));
System.out.println();
}
}
}
Output
Running the main method produces:
Test case 1:
Enqueued Alice
Enqueued Bob
Queue size: 2
Served customer: Alice
Queue size: 1
Enqueued Charlie
Served customer: Bob
Test case 2:
Queue empty, cannot dequeue
Queue size: 0
Test case 3:
Enqueued David
Queue size: 1
Served customer: David
Test case 4:
Enqueued Eve
Enqueued Frank
Enqueued Grace
Queue size: 3
Served customer: Eve
Served customer: Frank
Queue size: 1
Test case 5:
Enqueued null
Queue size: 1
Served customer: null
Explanation:
- Test case 1: Enqueues Alice, Bob; reports size 2; dequeues Alice; reports size 1; enqueues Charlie; dequeues Bob.
- Test case 2: Dequeue and size on empty queue return error and 0.
- Test case 3: Enqueues David, reports size 1, dequeues David.
- Test case 4: Enqueues three customers, reports size 3, dequeues two, reports size 1.
- Test case 5: Enqueues null name, reports size 1, dequeues null.
How It Works
- StringQueue:
- Uses an array with
front,rear, andsizeto manage customer names in FIFO order. enqueue: Adds to rear if not full.dequeue: Removes from front if not empty.size: Returns current number of customers.
- Uses an array with
- simulateTicketCounter:
- Enqueues customers, printing the action.
- Dequeues customers, printing the served customer or "Queue empty".
- Reports queue size when requested.
- Example Trace (Test case 1):
- Enqueue "Alice": array=["Alice"], front=0, rear=0, size=1.
- Enqueue "Bob": array=["Alice","Bob"], front=0, rear=1, size=2.
- Size: Returns 2.
- Dequeue: Returns "Alice", array=["-","Bob"], front=1, rear=1, size=1.
- Size: Returns 1.
- Enqueue "Charlie": array=["-","Bob","Charlie"], front=1, rear=2, size=2.
- Dequeue: Returns "Bob", array=["-","-","Charlie"], front=2, rear=2, size=1.
- Main Method: Tests normal sequences, empty queue, single customer, multiple operations, and null name.
Complexity Analysis Table
| Operation | Time Complexity | Space Complexity |
|---|---|---|
| Enqueue/Dequeue | O(1) | O(1) |
| Size | O(1) | O(1) |
| Full Algorithm | O(n) | O(n) |
Note:
- n is the number of operations.
- Time complexity: O(1) for each enqueue, dequeue, or size; O(n) for n operations.
- Space complexity: O(n) for the queue storing up to n customers.
- Worst case: O(n) time and O(n) space for many enqueue operations.
✅ Tip: Use a queue for a ticket counter simulation, as its FIFO nature ensures customers are served in arrival order. Test with size queries to verify queue state after operations.
⚠ Warning: Handle null names and empty queue cases to avoid unexpected behavior. Ensure the queue size is sufficient to accommodate the input sequence.