5
\$\begingroup\$

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.

Task

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],[10]]

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[0]>1:s[0]-=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!

\$\endgroup\$
11
  • \$\begingroup\$ Can we assume all inputs are non-empty and non-zero? \$\endgroup\$
    – Adám
    Commented Feb 13, 2022 at 8:25
  • 3
    \$\begingroup\$ It is unclear to me what determines the number of rows in your 2D box plots. Can you explain? \$\endgroup\$
    – Adám
    Commented Feb 13, 2022 at 8:39
  • 1
    \$\begingroup\$ What does the last case mean? \$\endgroup\$
    – l4m2
    Commented Feb 13, 2022 at 12:06
  • 2
    \$\begingroup\$ 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? \$\endgroup\$
    – DLosc
    Commented Feb 14, 2022 at 16:57
  • 1
    \$\begingroup\$ 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. \$\endgroup\$
    – Sundar R
    Commented Feb 14, 2022 at 20:40

7 Answers 7

5
\$\begingroup\$

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
\$\endgroup\$
4
  • \$\begingroup\$ 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. \$\endgroup\$
    – loopy walt
    Commented Feb 13, 2022 at 9:08
  • \$\begingroup\$ @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. \$\endgroup\$
    – emanresu A
    Commented Feb 13, 2022 at 9:11
  • \$\begingroup\$ 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. \$\endgroup\$
    – loopy walt
    Commented Feb 13, 2022 at 9:19
  • 2
    \$\begingroup\$ @loopywalt Okay. \$\endgroup\$
    – emanresu A
    Commented Feb 13, 2022 at 18:59
4
\$\begingroup\$

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!

\$\endgroup\$
4
\$\begingroup\$

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.

\$\endgroup\$
3
\$\begingroup\$

Charcoal, 32 bytes

E⌈EηΣι⁺·⁵∕×ΣEηΣE묛Ӆλ⊕ξ⊕ιθΣEηLλ

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

   η                                List of tasks
  E                                 Map over elements
     ι                              Current list of subtasks
    Σ                               Take the sum
 ⌈                                  Take the maximum
E                                   Map over implicit range
             η                      List of tasks
            E                       Map over elements
                λ                   Current list of subtasks
               E                    Map over elements
                     λ              Current list of subtasks
                    …               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
                             η      List of tasks
                            E       Map over elements
                               λ    Current list of subtasks
                              L     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:

RFφ⌈EηΣιP⁺·⁵∕×ΣEηΣE꬛Ӆκ⊕ν⊕ιθΣEηLκ
\$\endgroup\$
3
\$\begingroup\$

Jelly, 13 bytes

ÄṬSÄ÷Ṁ$×+.ḞRG

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]
           RG  Format into a grid
\$\endgroup\$
4
  • \$\begingroup\$ Can µ÷Ṁð -> ÷Ṁ$ \$\endgroup\$ Commented Feb 13, 2022 at 19:07
  • \$\begingroup\$ @UnrelatedString Thanks! \$\endgroup\$
    – emanresu A
    Commented Feb 14, 2022 at 3:13
  • \$\begingroup\$ Why are you getting the ceiling of the result? The question specifies rounding. \$\endgroup\$
    – Neil
    Commented Feb 15, 2022 at 11:26
  • \$\begingroup\$ @Neil Oh, okay. \$\endgroup\$
    – emanresu A
    Commented Feb 15, 2022 at 18:12
1
\$\begingroup\$

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.

\$\endgroup\$
0
\$\begingroup\$

Scala 3, 111 bytes

A Scala port of @m90's Python answer.


Golfed version. Attempt This Online!

(L,X,t)=>{val f=X.map(_.scanLeft(0)(_+_).tail).flatten;"#"*(Math.round(L*f.count(_<=t).toDouble/f.size).toInt)}

Ungolfed version. Attempt This Online!

import scala.util.Random

object Main {
  def calculateHash(L: Int, X: List[List[Int]], t: Int): String = {
    val cumulativeSums = X.map(_.scanLeft(0)(_ + _).tail) // Calculate cumulative sums
    val flattenedSums = cumulativeSums.flatten // Flatten the list of lists
    val meanValue = flattenedSums.count(_ <= t).toDouble / flattenedSums.size // Calculate mean value

    "#" * (Math.round(L * meanValue).toInt) // Return the hash string
  }

  def main(args: Array[String]): Unit = {
    for (i <- 1 to 10) {
      println(calculateHash(20, List(List(2, 2, 2), List(3, 3, 3), List(10)), i))
    }
  }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.