[Question]
  [
*Alternatively, guess who's doing a course on operating systems*
Round Robin scheduling is a way to schedule ready processes in an operating system. Each process in the queue is run for a certain amount of time (quantum), interrupted after that time (if not yet finished), and then added back to the ready queue for another round.
Your task today is to print the order that tasks are executed in a round robin simulation.
## The Challenge
Given a list of `[int, int]` (both > 0), as well as a quantum, return a list of `int` representing the order that processes were executed. Assume that all the processes arrive at the same time.
The list of `[int, int]` represents a (simplified) list of processes. The two ints are the process id and service time (the time the process needs to fully run).
For example:
```
[[1, 5], [2, 10], [3, 3], [4, 12]]
```
Represents the following processes
| Process ID | Service Time |
| --- | --- |
| 1 | 5 |
| 2 | 10 |
| 3 | 3 |
| 4 | 12 |
The quantum is an integer > 0 that represents the time slice dedicated to each process. A quantum of 4 means that each process is executed for 4 time units before being interrupted and then added to the ready queue.
If a quantum is larger than the time left on a process, then the next process is selected after the running process ends.
## Worked Example
Using the above process list (`[[1, 5], [2, 10], [3, 3], [4, 12]]`), and a quantum of `4`, the process execution order will be:
```
t = 0
             (head)     (tail)
ready queue = [1, 2, 3, 4]
time left = [5, 10, 3, 12]
Select process 1 to run for 4 time units
t = 4
interrupt process 1
              (head)  (tail)
ready queue = [2, 3, 4, 1]
time left = [10, 3, 12, 1]
Select process 2 to run for 4 time units.
t = 8
interrupt process 2
              (head)   (tail)
ready queue = [3, 4, 1, 2]
time left = [3, 12, 1, 6]
Select process 3 to run for 3 time units
t = 11
process 3 finished
             (head)  (tail)
ready queue = [4, 1, 2]
time left = [12, 1, 6]
Select process 4 to run for 4 time units
t = 15
interrupt process 4
             (head)  (tail)
ready queue = [1, 2, 4]
time left = [1, 6, 8]
Select process 1 to run for 1 time unit
t = 16
process 1 finished
              h    t
ready queue = [2, 4]
time left = [6, 8]
Select process 2 to run for 4 time units
t = 20
interrupt process 2
              h     t
ready queue = [4, 2]
time left = [8, 2]
Select process 4 to run for 4 time units
t = 24
interrupt process 4
              h     t
ready queue = [2, 4]
time left = [2, 4]
Select process 2 to run for 2 time units
t = 26
process 2 finished
              h    t
ready queue = [4]
time left = [4]
Select process 4 to run for 4 time units
t = 30
process 4 finished
no more proceses in the queue.
```
Therefore, the order of processes executed is:
```
[1, 2, 3, 4, 1, 2, 4, 2, 4]
```
## Rules
* Input can be taken as `list[list[int, int]], int`, `list[int], list[int], int`, or some other reasonable input method.
* The processes and quantum can be taken in any order.
* For example:
```
list[int: processIds]
list[int: serviceTimes]
int: quantum
```
or
```
list[int: serviceTimes]
int: quantum
list[int: processIds]
```
or any other combination.
* Output can be `list[int]`, `str` (joined on newlines, or spaces, or any constant delimiter) or some other reasonable output method.
* There will always be at least one process.
* The process ids list will always be a permutation of the range `[1, number of processes]`.
* The process ids can be 0-indexed if you want it to be for some reason. Using 0-indexing, the ids list will always be a permutation of the range `[0, number of processes]`.
* The order of the process ids list is important - processes are executed in the order they arrive (in a first come first serve manner). That is how the ready queue in an actual RR simulation works after all (FCFS selection strategy, with pre-emption on time quantums).
## Test Cases
```
processes, times, quantum => order
[1, 2, 3, 4], [5, 10, 3, 12], 4 => [1, 2, 3, 4, 1, 2, 4, 2, 4]
[5, 4, 3, 2, 1], [20, 20, 20, 20, 20], 4 => [5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1]
[1, 2, 3, 4, 5], [3, 3, 3, 3, 8], 4 => [1, 2, 3, 4, 5, 5]
[1, 2, 3, 4, 5], [3, 3, 10, 3, 8], 2 => [1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 3, 5, 3, 5, 3]
[1], [20], 5 => [1, 1, 1, 1]
[1], [19], 4 => [1, 1, 1, 1, 1]
```
This is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"), so the shortest answer in each language wins.
  
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 7 [bytes](https://github.com/DennisMitchell/jelly/wiki/Code-page)
```
√∑ƒä‚Åµx"Z·∫é
```
A full program that accepts `Times Quantum ProcessIds` and prints the schedule.
**[Try it online!](https://tio.run/##y0rNyan8///w9iNdjxq3VihFPdzV9////2hjHQUgMjQAUxax/43@R5vqKBjpKJgARYGCsQA "Jelly ‚Äì Try It Online")**
### How?
```
√∑ƒä‚Åµx"Z·∫é - Main Link: Times, Quantum
√∑       - {Times} divided by {Quantum}
 ƒä      - ceiling -> {SlotCounts}
  ‚Åµ     - program's third argument -> ProcessIds
    "   - {ProcessIds} zip {SlotCounts} with:
   x    -   {ProcessId} times {SlotCount}
     Z  - transpose
      ·∫é - tighten
        - implicit print
```
[Answer]
# [APL(Dyalog Unicode)](https://dyalog.com), 17 bytes [SBCS](https://github.com/abrudz/SBCS)
```
{0~‚ç®,‚çâ‚Üë‚ç∫/‚ç®¬®‚åà‚çµ√∑‚ç∫‚ç∫}
```
[Try it on APLgolf!](https://razetime.github.io/APLgolf/?h=AwA&c=qzaoe9S7QudRb@ejtomPenfpA3mHVjzq6XjUu/XwdqAAENUCAA&f=K3nUNqFao0ChRKFQE8h81DfVK9jf71FHl3q0@qPereqx6gqPulsUHnU1FWgUKqRpltRycZWoRxvqKBjpKBjrKJjE6ihEm@ooGBqAuYZGQL6JOkgJUNAELAZUaAhSZQRUgorhahHG6SiYgtQag3kQZEFIGdRukDojiDqIdUDSFME3tASbAwA&i=AwA&r=tryapl&l=apl-dyalog&m=dfn&n=f)
An operator that takes the quantum as `‚ç∫‚ç∫`, times as right argument `‚çµ` and 1-indexed process ids as left argument `‚ç∫`.
`‚åà‚çµ√∑‚ç∫‚ç∫` times divided by quantum, rounded up.  
`‚ç∫/‚ç®¬®` For each result, make a vector with the corresponding process id repeated that many times.  
`‚Üë` Join the vectors into a rectangular matrix, padding shorter vectors with 0s.  
`,‚çâ` Transpose matrix, then flatten into vector.  
`0~‚ç®` Remove 0s from vector.
[Answer]
# Excel, 45 bytes
```
=TOCOL(IF(A2#-A3*(ROW(1:99)-1)>0,A1#,NA()),2)
```
Quantum in cell `A3`, Process IDs and Service Times in spilled, *horizontal* ranges `A1#` and `A2#` respectively.
Returns a vertical array.
[Answer]
# [K (ngn/k)](https://codeberg.org/ngn/k), 46 bytes
```
{2*:'/-1_(#:){(1_y),(0<*|x)#,x:(*y)-0,x}[x]\y}
```
[Try it online!](https://ngn.codeberg.page/k#eJydT11PwjAUfb+/onaJbbcC69gSvRP1tW+w122ZRIfxAdEBZgTht9uOj2wGX0xub3t6zrkfM9wGLrJBTxXcQbHlqtgIyf0797sWjqyRuxvR82W9S+s82+wABvBRLZ7L5bJcSrJ6m9vrcz19X63nZHRPFtVLWUGqJAkkGUoS5pKkkSTKb6AKDA6tsCUx3807POQcrCFsOIOVrRAYe/ec63S0kvwf5tCZKbJ9hw06xM3F0SOr/NN5XNtag0vWX3DYzrbqYXeTo5P7GCdS3banavMZgEZV6MfrPdcPktFBllHB+JWj0cenafX6RZQA4DpOBHrU1qAZMw7g43gi0CdB4fUZ45ymdCQKwRg1zYxGA2r0uDuJPeaNBWCCfZZAsp/1DfcDwUF7gg==)
[Answer]
# [Headass](https://esolangs.org/wiki/Headass), 58 bytes
```
U{R])]O:]-[};{N)UO}:NE.UO[N):-E;UP^U][{N)UO}:](>):DOD]O;NE
```
Takes input as a list like `quantum, id_1, servicetime_1, id_2, servicetime_2...` with each argument on a separate line. I've gone ahead and made links for each individual test case because I know it's a bit cumbersome to translate.
[Test case 1](https://dso.surge.sh/#@WyJoZWFkYXNzIiwiIiwiVXtSXSldTzpdLVt9O3tOKVVPfTpORS5VT1tOKTotRTtVUF5VXVt7TilVT306XSg+KTpET0RdTztORSIsIiIsIjRcbjFcbjVcbjJcbjEwXG4zXG4zXG40XG4xMiIsIiJd) [Test case 2](https://dso.surge.sh/#@WyJoZWFkYXNzIiwiIiwiVXtSXSldTzpdLVt9O3tOKVVPfTpORS5VT1tOKTotRTtVUF5VXVt7TilVT306XSg+KTpET0RdTztORSIsIiIsIjRcbjVcbjIwXG40XG4yMFxuM1xuMjBcbjJcbjIwXG4xXG4yMCIsIiJd) [Test case 3](https://dso.surge.sh/#@WyJoZWFkYXNzIiwiIiwiVXtSXSldTzpdLVt9O3tOKVVPfTpORS5VT1tOKTotRTtVUF5VXVt7TilVT306XSg+KTpET0RdTztORSIsIiIsIjRcbjFcbjNcbjJcbjNcbjNcbjNcbjRcbjNcbjVcbjgiLCIiXQ==) [Test case 4](https://dso.surge.sh/#@WyJoZWFkYXNzIiwiIiwiVXtSXSldTzpdLVt9O3tOKVVPfTpORS5VT1tOKTotRTtVUF5VXVt7TilVT306XSg+KTpET0RdTztORSIsIiIsIjRcbjFcbjNcbjJcbjNcbjNcbjEwXG40XG4zXG41XG44IiwiIl0=) [Test case 5](https://dso.surge.sh/#@WyJoZWFkYXNzIiwiIiwiVXtSXSldTzpdLVt9O3tOKVVPfTpORS5VT1tOKTotRTtVUF5VXVt7TilVT306XSg+KTpET0RdTztORSIsIiIsIjVcbjFcbjIwIiwiIl0=) [Test case 6](https://dso.surge.sh/#@WyJoZWFkYXNzIiwiIiwiVXtSXSldTzpdLVt9O3tOKVVPfTpORS5VT1tOKTotRTtVUF5VXVt7TilVT306XSg+KTpET0RdTztORSIsIiIsIjRcbjFcbjE5IiwiIl0=)
### Explanation:
Pretty straightforward, just subtracts the quantum from each service time, checks if the service time has been used up, and decides whether to keep the values on the queue.
```
U{R])]O:]-[};{N)UO}:NE.  code block 0
U                        take quantum (q)
 {R])]O:]-[};            negate q and store on queue:
 {         }             loop
  R])                      if q + r2 == 0
     ]O                      store r2 on queue
       :    ;                break from loop
                           else
        ]-[                  decrement r2
                         end loop  
             {N)UO}:     store the remaining inputs on the queue:
             {N)  }:     while there are still inputs
                UO         store input on queue
                    NE   go to code block 1
                      .  end code block
UO[N):-E;UP^U][{N)UO}:](>):DOD]O;NE  code block 1
UO                                   keep q at top of queue
  [                                  r2 = q
   N):                               if there are no items left on the queue
      -E                               go to block -1 (error, halt)
        ;                            endif
         UP                          print the id on top of queue
           ^                         r1 = id
            U][                      r2 = remaining service time + r2
               {N)UO}:               retain remaining values on the queue
                      ](>):          if r2 > 0
                           DO          put r1 on bottom of queue
                             D]O       put r2 on bottom of queue
                                ;    endif
                                 NE  go to code block 1
```
[Answer]
# [Vyxal](https://github.com/Vyxal/Vyxal), 44 [bitsv2](https://github.com/Vyxal/Vyncode/blob/main/README.md), 5.5 bytes
```
/‚åà$·∫ã‚à©f
```
**[Try it Online!](https://vyxal.pythonanywhere.com/?v=2#WyI9IiwiIiwiL+KMiCThuoviiKlmIiwiIiwiMlxuWzMsIDMsIDEwLCAzLCA4XVxuWzUsIDIsIDQsIDEsIDNdIl0=)**
### How?
Port of my Jelly answer.
```
/‚åà$·∫ã‚à©f - [Quantum, Times, ProcessIds]
/      - divide -> [Times/Quantum, ProcessIds]
 ‚åà     - ceil -> [SlotCounts, ProcessIds]
  $    - swap -> [ProcessIds, SlotCounts]
   ·∫ã   - repeat -> [RepeatedProcessIds]
    ‚à©  - transpose -> [ProcessIdSublists]
     f - flatten -> [Schedule]
```
[Answer]
# [K (ngn/k)](https://codeberg.org/ngn/k), ~~23~~ 21 bytes
-2 bytes from @Bubbler's improvement
```
{y[&r]@<,/!'r:-_-z%x}
```
[Try it online!](https://ngn.codeberg.page/k/#eJydUNtugzAMfc9XeNIurRQKCaRqyTbtI/aG0MogtKhcWgIS3bR9+xIoLVSdNE1xHB/7nNhJ7H4evPvSf3nE5s1D6Rpvxsdd84XQq/t56x2+SzeGGTR8VWz5ZBUHScobfuDl1Nccb+JwAhRscDgDYqmA0GmfAn06evsdlSlkK0w4tWBg03MF/hj5o+bAuA3dWpzbM2AtjV7Q2jlHvHNk97tVMo4Jx3pAAu06ttVZsjxldR6ZaFNVO+maZlhEYl2k8UxWQbgVTbgJ8rWYhUVm7mshq6TIpUnnzJpbpkyyOg0qYZRFnUfKvye5IcONiOo0ydcI7coiFFIKiaFKMn3s6yCv6gyenqEoI1Eij2CgGGysPhqDx7B6YQsJVdjRxAFFpdvY6byPtMBpawoTfQNV8vE+3TPiYvg/9NFoJqb72i3qbHF1dKaZvyqPz9ZSek16Ae2h17d2b1ee9eqj9UWyHE41rP8AUlm2KQ==)
Takes three arguments, `x` (quantum), `y` (processes), and `z` (times).
Based on @frasiyav's [BQN answer](https://codegolf.stackexchange.com/a/265123/98547).
* `r:-_-z%x` calculate the ceiling of the times (`z`) divided by the quantum (`x`), and store it in variable `r`
* `<,/!'` generate `0..r-1` for each value in `r`, flatten them into a list, and then grade-up them (this is related to an "occurrence count")
* `y[&r]@` use this to index into a list containing the correct number of copies of each process ID
[Answer]
# [J](https://www.jsoftware.com), 21 bytes
```
(/:1#.]=]\)@#~>.@%&>/
```
[Attempt This Online!](https://ato.pxeger.com/run?1=m70wa8FNVUtFK8NYM0UrS3V1LiU99TQFWysFdQUdBQMFKyDW1VNwDvJxW1pakqZrsVVD38pQWS_WNjZG00G5zk7PQVXNTh8id4sxU5PLz0lPoaQoMa-4IL84VSGxoKAoPzE5AyxsoKtXZ6DjUGNl56Bh46CsZADTrsmVmpyRr2CoYKRgrGACpk3AWNcKLpimYKpgaABkGhopWCuYQHSYAiWMgQoMiWYBTURw0hSMDFAQ3GCYraZAiOQIU6AWYyi0wKYawTKGYyz6wR4BGWAEMwACwUrTIC4xRZWCSxpagiyGhPiCBRAaAA)
The Jelly / APL transpose approach was too verbose in J so I found a sorting based approach. Consider this example `1 2 3 4 f 5 10 3 12 ; 4`:
* `>.@%&>/` It starts the same as the APL approach dividing the times by the quantum and taking the ceiling:
```
2 3 1 3
```
* `#~` It uses that mask to duplicate the process ids in place:
```
1 1 2 2 2 3 4 4 4
```
* `(/: )@` Now we finish by applying a single sort... we just need to find the correct ordering...
* `]=]\` This creates the prefix lists with zero fill on the right, and then asks, "Where does each element equal that value?" Thus each element is compared to a row:
```
1 0 0 0 0 0 0 0 0
1 1 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0
0 0 1 1 0 0 0 0 0
0 0 1 1 1 0 0 0 0
0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 1 1 0
0 0 0 0 0 0 1 1 1
```
* `1#.` Now when we sum each row we get a running count of how many times each element has appeared so far:
```
1 2 1 2 3 1 1 2 3
```
This is exactly the ordering we need to achieve the round robin.
[Answer]
# [Wolfram Language (Mathematica)](https://www.wolfram.com/wolframscript/), 56 bytes
```
f@q_=#&@@@Flatten[#~Partition~UpTo@q&/@Table@@@#,{2,1}]&
```
[Try all test cases online.](https://tio.run/##dY0xC4MwEIX3/oqA4HRQLxpoh8JNnR3sJFLSojRQtcptEv96qhGHFl3eN7zv3dWaX2Wt2Ty1cxV190sQEtH1rZnLJg/GVPds2LTNePtkLXXhkTL9eJeTFMAgAW0RurQ3DeeiypNCkBgGBGV9GU2IIZ4yAZTWiuLw7yqQke/lInvIBThja4T@pvS53p9TwenXl1s@RvsDtQ52P@N5LtwX "Wolfram Language (Mathematica) ‚Äì Try It Online") Defines a function named `f` that takes its arguments in a format like (for the first test case)
`f[4][{{1,5},{2,10},{3,3},{4,12}}]`.
The code isn't all that short, but I learned something about `Flatten` that made me want to share this approach. Using the first test case:
* `Table@@@#` evaluates to `{ {1,1,1,1,1}, {2,2,2,2,2,2,2,2,2,2}, {3,3,3}, {4,4,4,4,4,4,4,4,4,4,4,4} }`.
* `#~Partition~UpTo@q&` operates on each element of that list, yielding `{ { {1,1,1,1}, {1} }, { {2,2,2,2}, {2,2,2,2}, {2,2} }, { {3,3,3} }, { {4,4,4,4}, {4,4,4,4}, {4,4,4,4}, {4,4,4,4} } }`.
* Next we want to transpose this array (an array in which each element is a short constant list of length at most 4); but `Transpose` doesn't handle ragged lists‚Äîthe idiom for that in Mathematica is `Flatten[#,{2}]`. This would yield `{ { {1,1,1,1}, {2,2,2,2}, {3,3,3}, {4,4,4,4} }, { {1}, {2,2,2,2}, {4,4,4,4} }, { {2,2}, {4,4,4,4} }, { {4,4,4,4} } }`.
* It turns out that we want to partially flatten this resulting list as well; so we could apply `Flatten[#,{1}]` to it (we could've also applied `Join` suitably). Now here's the cool bit I never realized before: `Flatten[#,{2,1}]` will cheerfully flatten the list first at the second level and then at the first level‚Äîin that "wrong" order! The result is `{ {1,1,1,1}, {2,2,2,2}, {3,3,3}, {4,4,4,4}, {1}, {2,2,2,2}, {4,4,4,4}, {2,2}, {4,4,4,4}, {4,4,4,4} }`.
* Now all that's left is to take the first element of each list (using `#&@@@`), which gives `{ 1, 2, 3, 4, 1, 2, 4, 2, 4, 4 }`.
[Answer]
# JavaScript (ES6), 57 bytes
Expects `(serviceTimes)(quantum)(processIds)`, using 0-indexed process IDs. Returns a space-separated string.
```
t=>q=>g=([n,...p])=>1/n?n+' '+g((t[n]-=q)>0?[...p,n]:p):p
```
[Try it online!](https://tio.run/##pZHBbsMgDIbvfQrfCqpLEpJKWyfoaU@BOERZk26qgLTRXj8jkLZJVeUyCwy/ZT6M@Sl/y2t1@Xbd1tivY1@LvhOyFbIRRBlkjDlNhcwSczCbNaw3DSGdMnorWirTgxoS0Oi9o3vXf6gVgAKVImQIHCHXCGrnlY/kfuFeF3A3r5LEH3jk47jPowcdgUWI8BBMByb3afMZyDfgLB//IW8FTCsshgLysI3j7fGqVy8qQmWLnLE/A4gvcZ4kn/r7FbE/3u9gySZXjGNGyN7nf/WKAM@ECNErVtvLZ1mdCFEOoUNoNQUhobLmas9HdrYNqUlHSUuJo5T2fw "JavaScript (Node.js) ‚Äì Try It Online")
### Commented
```
t =>            // t[] = array of service times
q =>            // q = quantum
g = ([          // g is a recursive function taking:
  n,            //   n = ID of next process
  ...p          //   p[] = array of remaining process IDs
]) =>           //
1 / n ?         // if n is defined:
  n + ' ' +     //   append n followed by a space
  g(            //   followed by the result of a recursive call:
    (t[n] -= q) //     subtract q from the n-th service time
    > 0 ?       //     if the result is positive:
      [...p, n] //       still running: put back n at the end of p[]
    :           //     else:
      p         //       kill the process by just passing p[]
  )             //   end of recursive call
:               // else:
  p             //   stop the recursion (p[] is now empty)
```
[Answer]
# [BQN](https://mlochbaum.github.io/BQN/), 16 [bytes](https://github.com/mlochbaum/BQN/blob/master/commentary/sbcs.bqn)
```
{‚çã‚àò‚äí‚ä∏‚äè‚åà‚àò√∑‚üúùï®‚ä∏/Àùùï©}
```
[Try it here.](https://mlochbaum.github.io/BQN/try.html#code=RiDihpAge+KNi+KImOKKkuKKuOKKj+KMiOKImMO34p+c8J2VqOKKuC/LnfCdlal9CgrigKJTaG93IDQgRiBbWzUsIDEwLCAzLCAxMl0sWzEsIDIsIDMsIDRdXQrigKJTaG93IDQgRiBbWzIwLCAyMCwgMjAsIDIwLCAyMF0sIFs1LCA0LCAzLCAyLCAxXV0K4oCiU2hvdyA0IEYgW1szLCAzLCAzLCAzLCA4XSwgWzEsIDIsIDMsIDQsIDVdXQrigKJTaG93IDIgRiBbWzMsIDMsIDEwLCAzLCA4XSwgWzEsIDIsIDMsIDQsIDVdXQrigKJTaG93IDUgRiBbWzIwXSwgWzFdXQrigKJTaG93IDQgRiBbWzE5XSwgWzFdXQpACg==)
Takes the quantum as the left argument `ùï®` and an array of `[serviceTimes, processIds]` as the right argument `ùï©`.
How it works:
```
{‚çã‚àò‚äí‚ä∏‚äè‚åà‚àò√∑‚üúùï®‚ä∏/Àùùï©}
             Àùùï©  # Apply between rows of the right argument:
           ‚ä∏/    #   replicate the ids by 
      ‚åà‚àò√∑‚üúùï®      #   the ceil of serviceTimes divided by the quantum.
    ‚ä∏‚äè           # Then, reorder the result according to:
   ‚äí             #   the running occurrence count
 ‚çã‚àò              #   graded by ascending order.
```
[Answer]
# [sclin](https://github.com/molarmanful/sclin), 17 bytes
```
/ |^"*`"zip tpose
```
[Try it on scline!](https://scline.fly.dev/#H4sIAHwo_WQCA4s2VDBSMFYwiVWINlUwNAAyDY1iFUwUrAEuP78nGQAAAA#H4sIAHwo_WQCA9NXqIlT0kpQqsosUCgpyC9OBQDiHFH_EQAAAA) Way simpler than I thought...
## Explanation
* `/ |^` Divide each service time by quantum and round up
* `"*`"zip` repeat each process number by previous results
* `tpose` transpose - this fortunately works with uneven lists-of-lists!
---
# [sclin](https://github.com/molarmanful/sclin), 54 bytes
```
=$n.
dups"; @"&#
1_ roll0.: Q n>o0$n , -1.: Q0>"pop"|#
```
[Try it on scline!](https://scline.fly.dev/#H4sIAFMe_WQCA4s2VDCNVYg2UjA0AFLGCsZA0kTB0ChWwUTBGgD0.1EZHQAAAA#H4sIAFMe_WQCA7NVydPjSiktKFayVnBQUlPmMoxXKMrPyTHQs1IIVMizyzdQyVPQUdA1BPEN7JQK8guUapQBr7tOtTYAAAA) Initial solution.
## Explanation
Prettified code:
```
=$n.
dups ( ; @ ) &#
  1_ roll 0.: Q n>o 0 $n , - 1.: Q 0> \pop |#
```
Takes processes input as a list of `[int int]`.
* `=$n` quantum as *n*
* `dups ( ; @ ) &#` if stack is not empty, execute next line and loop...
	+ `1_ roll` rotate bottom of stack to the top
	+ `0.: Q n>o` output process number
	+ `0 $n , -` decrement service time by *n*
	+ `1.: Q 0> \pop |#` if service time <= 0, then pop from the stack
[Answer]
# [Python](https://www.python.org), 61 bytes
```
lambda q,i:[I for Q in range(max(i)[0])for C,I in i if C>q*Q]
```
[Attempt This Online!](https://ato.pxeger.com/run?1=nVFNSwMxEMXr_oqhp6SMsp9QC9tLT4Veise4h1g3GtiP7LqKevVneCmI_if9NWZ2t5JKvQiTIS9v3psZ8vphnrrbutq9qfTy_b5Tp7PPtJDl1bWEBvVcrEDVLWxAV9DK6iZnpXxkmgs_40QscUWUBq1guWimm2w0uSB2TVxt8or5fO4B07jFhmMNKZTSsPxBFrg-uzOF7tgE0gVMOPfAtLrqmGINiumzNmyLmmdWxQfr3dfJiwgQQoQIIc4QRIIQ-D0MQotjsnJK7HN_j4eceSSIe87igBxCKz88Pz4HtQj_h7avO1NCfaMeDTE7OnpClX8qx7VJGh6T_oKRm8l12N3mZK8eY08G5-5UDj98xjc)
Expects quantum,list of cost-id pairs.
## How?
Instead of updating the remaining cost in each pair we run through the unchanged list repeatedly and after each cycle update the threshold (0,q,2q,3q,...) by which processes are filtered.
[Answer]
# [Charcoal](https://github.com/somebody1234/Charcoal), 23 bytes
```
Ôº¶‚åàÔº•Œ∏¬ßŒπ¬πÔº©Ôº•Œ¶Œ∏‚Ä∫‚Ä∫¬ßŒ∫¬πŒπÔπ™ŒπŒ∑¬ßŒ∫‚Å∞
```
[Try it online!](https://tio.run/##RYzNCsIwEIRfZY8RVuifJ08iWDwUvIccljbSYNpoTKVvH3eF4sIywzDz9SPFPpDP@R4iqI5WNy0T61O9EE7pOg92VQ6h3PHBLbo5qTO9069ycT7ZKM02WhK76bZ8yBLB8XdhWHwQ1sioP5wrhcCPOWutS4SDQdAVDwsxNUIt2nBQGXaNyfuP/wI "Charcoal ‚Äì Try It Online") Link is to verbose version of code. Takes input as a list of pairs of (process id, service time) and the quantum. Explanation:
```
Ôº¶‚åàÔº•Œ∏¬ßŒπ¬π
```
Loop up to the maximum service time.
```
Ôº©Ôº•Œ¶Œ∏‚Ä∫‚Ä∫¬ßŒ∫¬πŒπÔπ™ŒπŒ∑¬ßŒ∫‚Å∞
```
Output any processes due to be serviced at this time (i.e. their service time is higher and this is actually a multiple of the quantum.)
Would be 17 bytes if dictionary order was guaranteed:
```
Ôº¶‚åàÔº•Œ∏ŒπÔº©Ôº•Œ¶Œ∏‚Ä∫‚Ä∫Œ∫ŒπÔπ™ŒπŒ∑Œª
```
[Attempt This Online!](https://ato.pxeger.com/run?1=m70iOSOxKDk_MWfBgqWlJWm6Fjfj0vKLFDR8Eysyc0tzgXSBRqGOQqampqZCQFFmXomGc2JxCVjYLTOnJLUIJOtelJoIYsLobJAGHQXf_JTSnHyNTB2FDKB2HYUcIGm9pDgpuRhq1_JoJd2yHKXY_dHVhlYKpjoKRlYKhgY6CsZWCsY6CiZAjlEtkI6FqAYA "Charcoal ‚Äì Attempt This Online") Link is to verbose version of code. Takes input as a dictionary and a number. Explanation:
```
Ôº¶‚åàÔº•Œ∏Œπ
```
Loop up to the maximum service time.
```
Ôº©Ôº•Œ¶Œ∏‚Ä∫‚Ä∫Œ∫ŒπÔπ™ŒπŒ∑Œª
```
Output any processes due to be serviced at this time (i.e. their service time is higher and this is actually a multiple of the quantum.)
[Answer]
# [Scala 3](https://www.scala-lang.org/), 72 bytes
A port of [@loopy walt's Python answer](https://codegolf.stackexchange.com/a/265067/110802) in Scala.
---
Golfed version. [Attempt This Online!](https://ato.pxeger.com/run?1=nVLNTsJAEE488hQT4mHXbBvaQoLlJ_FgookelHhCQlZoyZrS38WAhCfxggd9J30Zne6CFJCDJvsz881838xu5uU9G_CAO8vPo6_o4dEbSLjmIoR5CWDo-TBGh_B0lLlwlqZ81u3IVISjHnXhLhQSWioT4IkHMOSSI3AlMkkUCECI8iwGNgOHQZUyHa8xsCoKsmxawDeZGFF2VZ-Usm3Nmgo5Kmqt6TZqbm-6XXRDYfB_d6-ZYtu1dTlHIXrVDz2ylhP-ILf6tVzPPqC34zrFc7_U5utooZilZKxf3_qTc7rzqCJJcWhJXX6UIpkIBgMGCRIiCk1DzQtdzY-eoNTLJkE-VD5JMNl8FjERKy2AGCdPBiHJyrcqz4VjTbgPz6cxjq43RCgq6_xFSe9c13fJZShZ3mdXWYAH7dFWu-MlXbR7WPNtIn2j_nGBpQVGCHY9v2kaFZARCHPMY9I3-xZFa2pYjbhpiIbwIUasnZzcLGbCC4a5a1NTRqir9V4X-l4u9f0N)
```
(q,i)=>(for{Q<-0 to i.map(_._1).max-1;p<-i;if p._1>q*Q}yield p._2).toSeq
```
Ungolfed version. [Attempt This Online!](https://ato.pxeger.com/run?1=nVPBTsJAED144ysmxMOuWQhtIcFGTdR4MNEDGk9IyAotWVNaaBcDGn7Dixcu-lF-jbOzrRTQgybdbefNvLczzdu3j2wgI-mtVu8zHdban3uvycNjMNBwLVUMLxWAYRDCGAMm01Hmw2maykX3VqcqHvW4D3ex0nBMlQBPMoKh1BKBK5VpRiAAYxQ5AlwBnoAmFzbfEuA0CHJcXsLXlZih76bdORebmi1KeZR1CrqLmpuLbx66pgj4f7jTTLntVnGcR4h92r8N2TKEP8jlf83oub_obYVeed89av3reOkwh2ScH2f9rjncGqpMIg6v0CtMUiQzJWAgYIqEhMNRjfzCc_9YB6VBNouMqUI2xeL6s5owlWsBTNB5OopZVr2hOh_2LeE-vphP0LrBEKGkauuXFbNyG6OeD5exFqB8arfLKMKNGy8ThEFvw9BjOT9HQNXx42zB-vW-w3FRnpmhit47ZpwGzGKtLKvoWKrUpFQeq5Ag1IATmMIBdGyrsFBBNMxzLq_rxDREAyzt9cxvaXFbvwA)
```
def f(q: Int, i: List[(Int, Int)]): List[Int] = {
    val maxC = i.maxBy(_._1)._1
    (for {
      Q <- 0 until maxC
      pair <- i
      if pair._1 > q * Q
    } yield pair._2).toList
}
```
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E), ~~10~~ 9 bytes
```
/√ÆŒ¥–∏√Ö\Œ∂Àú√æ
```
-1 thanks to Kevin Cruijssen
[Try it online!](https://tio.run/##yy9OTMpM/f9f//C6c1su7DjcGnNu2@k5h/f9/2/EFW2sowBEhgZgyiKWK9pQR8EIzDHRUTCLBQA "05AB1E ‚Äì Try It Online")
[Answer]
# [Retina 0.8.2](https://github.com/m-ender/retina/wiki/The-Language/a950ad7d925ec9316e3e2fb2cf5d49fd15d23e3d), ~~76~~ 75 bytes
```
\d+(?=,|$)
$*#
(?=.*, (#)+)(?<-1>#)+
@
S`, 
rM!&`.+@
O$^`.+: (@+)
$1_
: @+
```
[Try it online!](https://tio.run/##bYy9CsJAEIT7fYqVnHLJnSG7MaCHmuusxMJW9AQtbCyCpc/lA/hi5@YHQbCZb4bZ2eb6uN3Pcaw3IR4uRtcr@1QpqCwB8XlmUSepSXW9nNJaHHjYB4vQbEeTkBsPO3UUOtTeyIxO4NAbiArer0gOK4vskAqLpcPS4kwCC6ByyEWXuS9bcA8aOqBuw51@96Iynv/pqfg9YBg@Va2hhbQf "Retina 0.8.2 ‚Äì Try It Online") Link includes test cases. Takes input as a list of pairs and an integer. Explanation:
```
\d+(?=,|$)
$*#
```
Convert the durations to unary.
```
(?=.*, (#)+)(?<-1>#)+
@
```
Calculate the number of times each process gets scheduled.
```
S`, 
```
Split each process to its own line.
```
rM!&`.+@
```
Match each process once for each tick. This has to be done in reverse for the overlapping matches to work properly, so the processes actually come out in the wrong order.
```
O$^`.+: (@+)
$1_
```
Sort them according to the tick count and fix up the ordering.
```
: @+
```
Delete the tick counts.
(Out of interest I did try a repeat/transpose/flatten approach but the best I could do in Retina 1 was 79 bytes.)
[Answer]
# [Uiua](https://uiua.org), 11 [bytes](https://codegolf.stackexchange.com/a/265917/97916)
```
‚ñΩ¬±.‚ô≠‚çâ‚¨ö0‚â°‚ÜØ‚åà√∑
```
[Try it online!](https://www.uiua.org/pad?src=ZiDihpAg4oqP4o2P4oqQL-KKguKKg-KKkOKIteKHoeKWveKMiMO3CmYg4oaQIOKKj-KNjy3iipfiioMu4o2P4oqD4oqa4pa94oyIw7cKZiDihpAg4oqP4o2P4o2c4oqV4pah4oqQ4omh4o2PLi7ilr3ijIjDtwpmIOKGkCDilr3CsS7ima3ijYnirJow4omh4oav4oyIw7cKZiA0IFs1IDEwIDMgMTJdIFsxIDIgMyA0XQpmIDUgWzIwXSBbMV0K)
```
‚ñΩ¬±.‚ô≠‚çâ‚¨ö0‚â°‚ÜØ‚åà√∑    input: quantum, times, IDs
            ‚åà√∑     divide times by quantum and take ceiling -> occurrence count
        ‚¨ö0‚â°‚ÜØ      duplicate each ID that many times forming a row in a matrix,
                   padding short rows with zeros
                   for the first example, [[1,1,0], [2,2,2], [3,0,0], [4,4,4]]
    ‚ô≠‚çâ           transpose and flatten
‚ñΩ¬±.               keep nonzero elements
```
Some 12- and 13-byte solutions:
```
‚äè‚çè‚äê/‚äÇ‚äÉ‚äê‚àµ‚á°‚ñΩ‚åà√∑   # 12
               ‚åà√∑    same as the above
       ‚äÉ            run two functions over two stack items(repetitions, ids):
   ‚äê/‚äÇ  ‚äê‚àµ‚á°       ranges of repetitions concatenated; [0, 1, 0, 1, 2, 0, 0, 1, 2]
             ‚ñΩ      duplicate each ID in a vector; [1, 1, 2, 2, 2, 3, 4, 4, 4]
‚äè‚çè                 reorder the IDs by the ascending order of the ranges
‚äè‚çè-‚äó‚äÉ.‚çè‚äÉ‚äö‚ñΩ‚åà√∑  # 12
‚äè‚çè        ‚äÉ ‚ñΩ‚åà√∑    same as above
            ‚äö        duplicate indices by values; [0, 0, 1, 1, 1, 2, 3, 3, 3]
    ‚äó‚äÉ.‚çè           self-index and sorting order: [0, 0, 2, 2, 2, 5, 6, 6, 6],
                      [0, 1, 2, 3, 4, 5, 6, 7, 8]
   -                  subtract first from second: [0, 1, 0, 1, 2, 0, 0, 1, 2]
‚äè‚çè‚çú‚äï‚ñ°‚äê‚â°‚çè..‚ñΩ‚åà√∑   # 13
‚äè‚çè          .‚ñΩ‚åà√∑     same as above, but using just duplicated ids
   ‚çú‚äï‚ñ°‚äê‚â°‚çè.          group by itself and replace each group with range of that length
```
[Answer]
# Python3, 83 bytes:
```
def R(p,t,q):
 Q,s=[*zip(p,t)],[]
 for a,b in Q:s+=[a];Q+=[(a,b-q)]*(b>q)
 return s
```
[Try it online!](https://tio.run/##jY5NDoIwEIX3PcUsWxwTWyBBDN4Btk0XECGyKaXUhV6@FjAadGMyP3lvvpmMubvroOPMWO8vbQcVNehwZDmBEqdCRo/ezBZTKBWBbrBQYwO9hjKfdoWs1akMjQZzPzIV0eY8MgK2dTerYfLG9trRikqOIBBihEQhyBSBHxbJRdAJY@RNhlmyjALPZ1gEcpvfK5/jCOm8Ei9qjexP@vXQjIsNvv4Qavpj8@N63D8B)
[Answer]
# [AWK](https://www.gnu.org/software/gawk/manual/gawk.html), 68 bytes
```
a=$1{for(b=1;b<NF;){$++c=$++b;if(0<d=$++b-c){$++NF=$c;$++NF=d}}}NF=c
```
[Try it online!](https://tio.run/##SyzP/v8/0VbFsDotv0gjydbQOsnGz81as1pFWzvZFkgkWWemaRjYpIDZuslgCT83W5Vkawgjpba2Fkgl//9vomCoYKpgpGBooGAMhECuEQA "AWK ‚Äì Try It Online")
This program expects the first commandline argument to give the quantum. And the arguments after that are pairs of pid/service-time values. It works by iterating through the pid/time pairs, adding the pid to an output list. Then if the service time remaining is larger than the quantum, the pid and remaining time are appended to the argument. So it essentially extends the commandline arguments as needed. And the "output list" is stored at the beginning of the argument list. Each iteration consumes two values from the argument list but only adds one (the pid) to the front of the argument list. So once the all the arguments have been processed, all that's left to do is set the number of arguments to the size of the output list. The pid list if printed automatically since the "test" that sets the number of arguments has no associated code.
```
a=$1{ ... }               -- set "a" to the quantum (first arg)
.. for( ... ){ ... }      -- loop to process pairs of args
.. .. b=1;b<NF;           -- stops when at the end of args
.. .. .. $++c=$++b;       -- copy the "pid" to the output list and increment
.. .. .. if( ... ){ ... } -- "true" when service time > quantum
.. .. .. .. 0<d=$++b-c    -- set "d" to remaining service time
.. .. .. .. .. $++NF=$c;  -- append pid to end of args
.. .. .. .. .. $++NF=d    -- append remaining service time
NF=c                      -- set the number of pids to print
```
[Answer]
# [C++ (gcc)](https://gcc.gnu.org/), ~~97~~ 93 bytes
```
[](auto&l,int q,auto o){for(int m;m=0,q;q=m<q?m:q)for(auto&[p,t]:l)m=t>m?t:m,t>0?o=p:o,t-=q;}
```
[Try it online!](https://tio.run/##hVLtSsMwFP29PMUFwbWQQdttoOnHHmQOqTGTYNOv3ApS@uw1STvtnOCf3JNz7jkJN@F1vXnjfMw7rOAMKRmPJ89u7gsqS4SGOqXy@3PVepZRsUoD2sRNqpLmoFjjW8VZjjXFEyt8lWKmDsgUxSw4VGnNKoqbtImHMSZ3suRF9yogkZXGVuQqW3D6lupQFhI/l9SH4Fi1GSHuQrksPR96stL4ytikJQ7XuZzRDWucFMySZXMBFBp5roWG1Iat@r4PKewHCn1EIQws2FLY2rozRDQYtBvo1LqnEAWzFF16JxBdQOjA0hXOedFcF/mumtSH/wxh8JcjWjimQ/cLJnz8Th1iQlbmCWF6QzgWUpvRNF1eYqdO7GcubsZXQ7aDg1borsDYSGfvykvB9b7k/P1Zllq0KFpv6vZ91z9/HJBsTvENO53Aqw4hSUDaZQ3rmPwS1k@lJQcykPEL "C++ (gcc) ‚Äì Try It Online")
4 bytes shaved off thanks to ceilingcat. Takes a list of pairs as input, and uses an insert iterator to return the results. Explanation:
```
[](auto& l, int q, auto o) {   // Process list, quantum, output iterator
    for (int m; m = 0,         // Will track maximum time of all processes
           q;                  // As long as quantum is still non-zero
           q = m < q ? m : q)  // Limit quantum to the maximum process time
       for (auto& [p, t]: l)   // Loop over all processes
           m = t > m ? t : m,  // Update the maximum time
           t > 0 ? o = p : o,  // Output process number if time left is positive
           t -= q;             // Subtract the quantum from the time
}
```
]