# Real-world progress bar

### Backstory, skip if you like

Generating high quality pseudo random numbers is a tricky business but the fine engineers at < enter company you love to hate > have mastered it. Their progress bars effortlessly rise above the primitive notion of linearly passing time and add an exhilarating sense of unpredictability to the waiting experience.

Cynics have dismissed the entire matter as a ploy to prevent employees from being able to assess whether there is enough time to grab a coffee. All I can say is I feel sorry for those people.

It so happens that your boss believes to have reverse-engineered the secret of the < enter company you love to hate > (tm) progress bar and has tasked you with golfing up a simulator.

Given a length L and list of tasks, each represented by a list of times each of the task's steps is expected to take, implement a progress bar that at each time indicates the percentage of steps expected to have completed by that time assuming the tasks are independent. The length of the bar should be L at 100%.

### I/O

Flexible within reason. You may pass list lengths separately if you wish.

You may also input a time in which case the output should be a single horizontal bar of correctly rounded integer length.

Otherwise you may represent time as actual time in a unit of your choice or as one axis (top-to-bottom) in a 2D plot.

### Examples

I: [20,[2,2,2],[3,3,3],]

O:

###
######
#########
#########
##############
##############
##############
#################
####################

I: [8,[1,1],[2,1],[3,2],[12,1]]

O:
#
###
#####
#####
######
######
######
######
######
######
######
#######
########

I: [30,[1,2,3],[2,4,7],[2,2,2,2,2,2,2,2],[9,10],[1,1,3,2]]

O:
###
########
#########
###########
############
#################
##################
####################
#####################
#######################
#######################
########################
##########################
###########################
###########################
#############################
#############################
#############################
##############################

I: [4.7,20,[1,2,3],[10,10],[1,1,1],[4,10]]

O:
############


### Scoring/rules/loopholes:

code-golf as usual.

### Reference implementation Python >= 3.8

def f(l,S,c=0):
T=len(sum(S,[]))            # total number of steps
while S:=[*filter(None,S)]: # check whether any tasks still runnimg
for s in S:                # go through tasks
if s>1:s-=1         # current step terminating? no: update time left
else:c+=s.pop(0)	     # yes: remove step and increment step counter
print((T//2+l*c)//T*"#")   # output bar


Try it online!

• Can we assume all inputs are non-empty and non-zero?
Feb 13 at 8:25
• It is unclear to me what determines the number of rows in your 2D box plots. Can you explain?
Feb 13 at 8:39
• What does the last case mean?
– l4m2
Feb 13 at 12:06
• I find the challenge description confusing. So each task has a number of steps, and the progress bar represents how many steps have been completed (out of the total number of steps for all tasks)? Does the number associated with each step affect how much of the progress bar is filled in by the completion of that step, or does it only affect when the step is completed? Are the tasks completed one after the other (in series), or at the same time (in parallel)? And what do pseudo-random numbers have to do with it? Feb 14 at 16:57
• Could you actually illustrate how you arrive at the "progress" in each step, wtih a show of calculation? For eg. why there's 3 #'s in the first line of the first output, then 5 in the second line. Instead of explaining with words (which is obviously failing to reach some of us including me), just show us the arithmetic for one example. Feb 14 at 20:40

# Vyxal, 16 bytes

ƛ¦Þǔ;∑¦Ḣ:G/*⌈×*⁋


Try it Online!

Straightforward port of my Jelly answer, go see that explanation for a better idea of how it works. Jelly has some nicer builtins.

ƛ   ;            # Map each task to...
¦               # Cumulative sums (instants where a step will complete)
Þǔ             # Untruth (a boolean list with 1s at those indices)
∑           # Reduce the whole thing by addition
¦Ḣ         # Get cumulative sums and remove the leading zero
:G/      # Divide by the maximum
*     # Multiply by the input
⌈    # Get the ceiling
×*⁋ # Make a bar graph

• Forgive my ignorance but is it really not possible to output an actual ASCII bar with those golfy golf languages? I mean, it is part of the task. Feb 13 at 9:08
• @loopywalt It is, but it's shorter not to. I assumed a list of integers was a reasonable output format, but if it's not I can change this. Feb 13 at 9:11
• In that case I would say you should output bars. Considering the whole challenge is literally about progress bars that seems only fair to me. Feb 13 at 9:19
• @loopywalt Okay. Feb 13 at 18:59

# Python 3.8, 91 bytes

lambda L,X,t:int(sum((s:=0)+sum(t>=(s:=s+y)for y in x)for x in X)*L/sum(map(len,X))+.5)*'#'


Try it online!

# Python 3 with numpy, 76 bytes

lambda L,X,t:int(L*mean(t>=hstack(map(cumsum,X)))+.5)*'#'
from numpy import*


Try it online!

cumsum transforms a list of step lengths into an array of the steps' finishing times, and hstack combines those arrays into one long array. The comparison produces 1 for finished steps and 0 for unfinished steps, and then mean gives the proportion of finished steps.

# Charcoal, 32 bytes

Ｅ⌈ＥηΣι⁺·⁵∕×ΣＥηΣＥλ¬›Σ…λ⊕ξ⊕ιθΣＥηＬλ


Try it online! Link is to verbose version of code. Outputs a bar graph. Explanation:

   η                                List of tasks
Ｅ                                 Map over elements
Σ                               Take the sum
⌈                                  Take the maximum
Ｅ                                   Map over implicit range
Ｅ                       Map over elements
Ｅ                    Map over elements
…               Truncated to length
ξ            Innermost index
⊕             Incremented
Σ                Take the sum
¬›                 Is less then or equal to
ι          Outer value
⊕           Incremented
Σ                     Take the sum
Σ                        Take the sum
×                         Multiplied by
θ         Desired maximum length
∕                          Divided by
Ｅ       Map over elements
Ｌ     Take the length
Σ        Take the sum
⁺                            Plus
·⁵                          Literal number 0.5
Implicitly print as bar graph


35 bytes for a version that outputs in real time:

ＲＦφ⌈ＥηΣιＰ⁺·⁵∕×ΣＥηΣＥκ¬›Σ…κ⊕ν⊕ιθΣＥηＬκ


# Jelly, 14 bytes

ÄṬSÄ÷Ṁ$×+.ḞṬ€G  Try it online! A dyadic link that outputs a bar graph (sorta). I'm quite proud of ÄṬSÄ which generates the numbers before stretching. I'm also somewhat annoyed that the code to stretch the numbers is six bytes. I feel like there's got to be a better way to do that, but I'm not sure what. The below explanation uses [[1,1],[2,1],[3,2],[4,1]] and 16 as an example. Ä Take the cumulative sums of each item Generating a list of lists of indices at which another task segment completes. For the example list, [[1,2],[2,3],[3,5],[4,5]] Ṭ Take the untruth of each item Turning each into a boolean list with 1s at the specified indices Each task is now a boolean list where 1s represent that a task will be represented at that instant For the example, [[1,1],[0,1,1],[0,0,1,0,1],[0,0,0,1,1]] S Reduce the list by vectorised addition The result becomes a single list where the number at each index Is the number of tasks completed at that instant [1,2,2,1,2] Ä Take the cumulative sum, getting the total tasks completed at that instant [1,3,5,6,8] --$         Run what's next on the result of the above
÷           Float divide the list by...
Ṁ          Its maximum
Producing a list of floats between 0 and 1
[.125,.375,.625,.875,1]
×        Multiply the result of the above by the other input
+.Ċ     Round the results.
[2,6,10,14,16]
Ṭ€G  Format into a grid

• Can µ÷Ṁð -> ÷Ṁ\$ Feb 13 at 19:07
• @UnrelatedString Thanks! Feb 14 at 3:13
• Why are you getting the ceiling of the result? The question specifies rounding.
– Neil
Feb 15 at 11:26
• @Neil Oh, okay. Feb 15 at 18:12

# R, 85 bytes

\(L,x)barplot(sapply(max(u<-unlist(Map(cumsum,x))):1,\(i)(.5+mean(u<=i)*L)%/%1),ho=T)


Try it on rdrr.io! with graphical output, but with older and longer function syntax.