Miscellaneous scripts
This repository contains miscellaneous scripts that does not fit in one repository, yet I will use them sometimes for my personal use. Note that some of the scripts might contain hardcoded paths and opinionated presets, and you are advised to inspect them before actually using.
 
Loading...
Searching...
No Matches
lift.cpp
Go to the documentation of this file.
1/*
2g++ lift.cpp -Wall -Wextra -pedantic -Wunused -Wshadow -O3 -flto -o lift
3./lift
4*/
5
6#include <algorithm>
7#include <cassert>
8#include <chrono>
9#include <iomanip>
10#include <iostream>
11#include <random>
12#include <vector>
13
14enum {
24};
25
26#define numQueues 2
27#define numLifts numQueues
28#if numQueues == 2
29enum {
35};
36#else
37#error "FeatureNotImplemented: Number of queues must be equal to 2"
38#endif
39
40class Lift {
41 public:
42 const unsigned int id;
43 const unsigned int meanWaitingTime;
44 const unsigned int stdDevWaitingTime;
45 const unsigned int capacity = liftCapacity;
46
47 Lift(unsigned int _id, unsigned int _meanWaitingTime, unsigned int _stdDevWaitingTime)
48 : id(_id), meanWaitingTime(_meanWaitingTime), stdDevWaitingTime(_stdDevWaitingTime) {};
49
50 // Print the information of the lift via <<
51 friend auto operator<<(std::ostream & os, const Lift & lift) -> std::ostream & {
52 os << lift.id << " " << lift.meanWaitingTime << " " << lift.stdDevWaitingTime;
53 return os;
54 }
55
56 // Generate a random waiting time based on the mean and standard deviation
57 // using a truncated normal distribution to avoid negative waiting time
58 [[nodiscard]] auto generateWaitingTime() const -> unsigned int {
60
61 unsigned int const seed = std::chrono::system_clock::now().time_since_epoch().count();
62 std::default_random_engine generator(seed);
63 std::normal_distribution<double> distribution(meanWaitingTime, stdDevWaitingTime);
64 double waitingTime = distribution(generator);
65
68 }
69 else if (waitingTime > meanWaitingTime + stdDevWaitingTime * normDistSDBound) {
71 }
72 return static_cast<unsigned int>(waitingTime);
73 }
74
75 // Get the time when the lift will be available
76 [[nodiscard]] auto getAvailableTime(unsigned int currentTime) const -> unsigned int {
77 return currentTime + generateWaitingTime();
78 }
79};
80
81class Queue {
82 public:
83 unsigned int id;
84 unsigned int numPeople;
85
86 // Which lift is the queue for
87 const Lift * lift;
88
89 Queue(unsigned int _id, unsigned int _numPeople, Lift * _lift)
90 : id(_id), numPeople(_numPeople), lift(_lift) {
91 static_assert(
92 numQueues == numLifts, "Number of queues must be equal to number of lifts");
93 static_assert(
94 numQueues > minNumPeople, "Number of queues must be greater than minNumPeople");
95 assert(_lift != nullptr);
96 }
97
98 // Print the information of the queue via <<
99 friend auto operator<<(std::ostream & os, const Queue & queue) -> std::ostream & {
100 os << queue.id << " " << queue.numPeople << " " << *queue.lift;
101 return os;
102 }
103
104 // Store waiting time for each queue
105 unsigned int waitingTime = 0;
106
107 // Compare the waiting time of two queues
108 auto operator<(const Queue & queue) const -> bool {
109 return this->waitingTime < queue.waitingTime;
110 }
111};
112
113auto simulateTwoQueues(std::vector<Queue *> queues) -> decltype(Queue::id) {
114 // Simulate the total time taken for the lift to serve all the queues
115 for (Queue * queue : queues) {
116 while (queue->numPeople > minNumPeople) {
117 queue->waitingTime = queue->lift->getAvailableTime(queue->waitingTime);
118 if (queue->numPeople > queue->lift->capacity) {
119 queue->numPeople -= queue->lift->capacity;
120 }
121 else {
122 queue->numPeople = minNumPeople;
123 }
124 }
125 }
126 // Return the fastest queue id
127 return (*std::min_element(queues.begin(), queues.end()))->id;
128}
129
130auto main() -> int {
131 // Result vector
132 std::vector<std::string> const headers = {"Queue1", "Queue2", "Lift1", "Lift2", "Fastest"};
133 struct results {
134 public:
135 unsigned int queueLength;
136 unsigned int queue2Length;
137 unsigned int lift1WaitingTime;
138 unsigned int lift2WaitingTime;
139 unsigned int fastestQueueId;
140 } __attribute__((aligned(32)));
141 std::vector<results> rows;
142 // Simulate which queue is the fastest under every possible scenario
143 // which is achieved by generating random queue length and lift waiting time
144 static_assert(isLift1FasterThanLift2 != 0u, "Lift 1 must be faster than Lift 2");
145 for (unsigned int queueLength = minDefaultNumPeople; queueLength <= maxNumPeople;
146 queueLength += liftCapacity) {
147 for (unsigned int queue2Length = minDefaultNumPeople;
148 queue2Length <= queueLength - minRoundDifference; queue2Length += liftCapacity) {
149 std::vector<Queue *> queues;
150
151 // todo: add more queues
152 queues.push_back(new Queue(numQueues - 1, queueLength,
154 queues.push_back(new Queue(numQueues, queue2Length,
156
157 auto fastestQueueId = simulateTwoQueues(queues);
158
159 // Add the result only if the fastest queue is different from the previous
160 // simulation Otherwise, remove the last simulation and add the new one
161 if (!rows.empty() && rows.back().fastestQueueId == fastestQueueId &&
162 rows.back().queueLength == queueLength) {
163 rows.pop_back();
164 }
165 results const result = {queueLength, queue2Length, (*queues.begin())->waitingTime,
166 (*++queues.begin())->waitingTime, fastestQueueId};
167 rows.push_back(result);
168
169 // Free the memory
170 for (Queue * queue : queues) {
171 delete queue->lift;
172 delete queue;
173 }
174 }
175 }
176
177 // Print the results
178 for (const std::string & header : headers) {
179 std::cout << std::setw(coutWidth) << header;
180 }
181 std::cout << '\n';
182 for (const results & row : rows) {
183 std::cout << std::setw(coutWidth) << row.queueLength;
184 std::cout << std::setw(coutWidth) << row.queue2Length;
185 std::cout << std::setw(coutWidth) << row.lift1WaitingTime;
186 std::cout << std::setw(coutWidth) << row.lift2WaitingTime;
187 std::cout << std::setw(coutWidth) << row.fastestQueueId;
188 std::cout << '\n';
189 }
190 return 0;
191}
Definition lift.cpp:40
auto generateWaitingTime() const -> unsigned int
Definition lift.cpp:58
auto getAvailableTime(unsigned int currentTime) const -> unsigned int
Definition lift.cpp:76
const unsigned int stdDevWaitingTime
Definition lift.cpp:44
const unsigned int capacity
Definition lift.cpp:45
const unsigned int meanWaitingTime
Definition lift.cpp:43
Lift(unsigned int _id, unsigned int _meanWaitingTime, unsigned int _stdDevWaitingTime)
Definition lift.cpp:47
friend auto operator<<(std::ostream &os, const Lift &lift) -> std::ostream &
Definition lift.cpp:51
const unsigned int id
Definition lift.cpp:42
Definition lift.cpp:81
unsigned int waitingTime
Definition lift.cpp:105
unsigned int id
Definition lift.cpp:83
friend auto operator<<(std::ostream &os, const Queue &queue) -> std::ostream &
Definition lift.cpp:99
auto operator<(const Queue &queue) const -> bool
Definition lift.cpp:108
const Lift * lift
Definition lift.cpp:87
Queue(unsigned int _id, unsigned int _numPeople, Lift *_lift)
Definition lift.cpp:89
unsigned int numPeople
Definition lift.cpp:84
#define numLifts
Definition lift.cpp:27
@ minNumPeople
Definition lift.cpp:19
@ minRoundDifference
Definition lift.cpp:18
@ normDistSDBound
Definition lift.cpp:22
@ maxRound
Definition lift.cpp:16
@ minDefaultNumPeople
Definition lift.cpp:21
@ coutWidth
Definition lift.cpp:23
@ minRound
Definition lift.cpp:17
@ maxNumPeople
Definition lift.cpp:20
@ liftCapacity
Definition lift.cpp:15
#define numQueues
Definition lift.cpp:26
@ lift1MeanWaitingTime
Definition lift.cpp:30
@ lift2StdDevWaitingTime
Definition lift.cpp:33
@ isLift1FasterThanLift2
Definition lift.cpp:34
@ lift2MeanWaitingTime
Definition lift.cpp:32
@ lift1StdDevWaitingTime
Definition lift.cpp:31
auto main() -> int
Definition lift.cpp:130
auto simulateTwoQueues(std::vector< Queue * > queues) -> decltype(Queue::id)
Definition lift.cpp:113