19
\$\begingroup\$

Summary

Videos which are sped up every time a particular word is said exist for everything from the Bee Movie to the classic Rick Roll. The goal for this challenge is to figure out how much you'd have to slow down the sped-up video in order to match the duration of the original video.

For example, the original Bee Movie has a duration of 95 minutes. The sped up version is 5:40 or ~5.667 minutes. 95/5.667 = 16.76. We'd have to play the sped up version 16.76x slower in order for the overall duration to match the original movie.

Inputs

Your program must take in 3 inputs:

  1. The duration of the original video (Bee Movie was 95 minutes)
  2. The speedup factor per occurence (Bee Movie was 15% or .15)
  3. A list of timestamps of occurrences (Bee movie has more than I care to look up/list)

The exact way these are passed in is flexible: 3 separate parameters is my default assumption, but if you want to take in a single list of values and pop the duration/speedup factor off the front that's fine, or take a single string in JSON or whatever format floats your boat, etc.

For the duration: seconds, minutes, or some builtin duration type are all fine.

For the speedup factor of the bee movie, any of 15, .15, or 1.15 could be used to represent the 15% speedup.

You can assume the occurrences are ordered in the most convenient manner, but there can be duplicate values (such as multiple characters talking over one another in a movie).

Output

A scaling factor to make the durations of the original and sped-up video match. The exact format is flexible.

Examples

{"duration": 10, "speedup-factor": 2, "occurrences": [1,2,3,4,5,6,7,8,9]} -> {"slowdown-factor": 5.004887585532747}
{"duration": 500, "speedup-factor": 1.15, "occurrences": [1,2,3, ..., 497, 498, 499]} -> {"slowdown-factor": 65.21739130434779}
{"duration": 100, "speedup-factor": 3, "occurrences": [0]} -> {"slowdown-factor": 3}
{"duration": 100, "speedup-factor": 3, "occurrences": [0, 0, 0]} -> {"slowdown-factor": 27}
{"duration": 100, "speedup-factor": 100, "occurrences": [99.99]} -> {"slowdown-factor": 1.0000990098}

Notes: First two generated programmatically with 100/(sum(1/(2**i) for i in range(10))) and 500/(sum(1/(1.15**i) for i in range(500))). 4th example: 3 * 3 * 3 = 27x speedup, occurring right at the start of the video. Last example calculated by hand with 100/(99.99 + .01/100)

Note

I've kept most of the examples fairly simple, but I believe they cover all the relevant edge cases (a program which solves all of them should be totally correct). If I've left things ambiguous or difficult to parse, let me know and I'll add comments!

\$\endgroup\$
9
  • 4
    \$\begingroup\$ Welcome to the site! This is a good first attempt at writing a challenge, but I've edited the markdown slightly just to improve the final look. Feel free to change anything you don't like. Note that we require challenges to have a objective scoring criteria, which you are missing. The standard is code-golf (shortest code wins), but there are a number available. (cont.) \$\endgroup\$ Commented Jul 29, 2020 at 13:45
  • 4
    \$\begingroup\$ (cont.) Furthermore, I'd highly recommend posting your next challenge in the Sandbox first, so that you can get feedback on potential issues your challenge ideas may have \$\endgroup\$ Commented Jul 29, 2020 at 13:46
  • 3
    \$\begingroup\$ You can merge duplicate accounts if you need to \$\endgroup\$ Commented Jul 29, 2020 at 16:33
  • 8
    \$\begingroup\$ The first test case isn't matching up with my code, which gives 5.00488758553. Maybe I'm misunderstanding something. It seems to be that sped up video is about 2 seconds, since the segments takes 1,1/2,1/4,... seconds each, requiring a slowdown factor of about 5 given the 10-second original. \$\endgroup\$
    – xnor
    Commented Jul 29, 2020 at 16:49
  • 3
    \$\begingroup\$ @xnor I'm with you on that one. It seems that the first two test cases calculate the duration of the sped-up film, but the later ones actually calculate original duration / sped-up duration \$\endgroup\$
    – Giuseppe
    Commented Jul 29, 2020 at 17:13

12 Answers 12

14
\$\begingroup\$

Python 2, 47 bytes

lambda m,r,l:m/reduce(lambda u,x:u/r+x-x/r,l,m)

Try it online!

Takes timestamps sorted in descending order.

The idea is to compute the video duration as a polynomial in the inverse speedup rate 1/r using Horner's method with coefficients given by the sorted timestamps. This avoids needing to explicitly take the differences of consecutive timestamps. We then divide the duration of the original video by the resulting duration to get the desired slowdown factor.

53 bytes

f=lambda m,r,l:l==[]or r/(l.pop()*(r-1)/m+1/f(m,r,l))

Try it online!

An attempt to write the function fully recursively. While the new duration itself has a clean recursive expression, we want to get the slowdown factor which divides the original duration by the new duration, and this is messier to express recursively.

\$\endgroup\$
1
  • \$\begingroup\$ Fantastic! Horner's method is the type of trick I was hoping to learn about when posting the challenge. Avoiding taking the differences is something I didn't know would be possible! \$\endgroup\$ Commented Jul 29, 2020 at 18:26
5
\$\begingroup\$

Jelly, 10 bytes

;ŻIṚḅ⁵ݤ÷@

A full program accepting timestamps original-duration speedup-factor which prints the necessary slowdown-factor.

Try it online!

How?

Get a list of the durations of film separated by the occurrences (including any zero-length segments), reverse and convert from base slowdown-factor (where this slowdown-factor is the inverse of the given speedup-factor), then divide the original-duration by that.

;ŻIṚḅ⁵ݤ÷@ - Main link: timestamps S, original-duration T
;          - concatenate (T) to (S) -> S+[T]
 Ż         - prefix with a zero (the start of the film) -> [0]+S+[T]
  I        - deltas -> [S[1]-0, S[2]-S[1], ..., S[n]-S[n-1], T-S[n]]
   Ṛ       - reverse -> [T-S[n], S[n]-S[n-1], ..., S[2]-S[1], S[1]-0]
       ¤   - nilad followed by link(s) as a nilad:
     ⁵     -   3rd argument = speedup-factor
      İ    -   inverse -> 1/speedup-factor - call this F
    ḅ      - convert from base -> (T-S[n])×F^(n)+(S[n]-S[n-1])×F^(n-1)+...+(S[2]-S[1])×F^1+(S[1]-0)×F^0
         @ - using swapped arguments (with implicit right argument T):
        ÷  -   division -> T/((T-S[n])×F^(n)+(S[n]-S[n-1])×F^(n-1)+...+(S[2]-S[1])×F^1+(S[1]-0)×F^0)
           - implicit print
\$\endgroup\$
4
  • \$\begingroup\$ Would it help at all to take input in descending order instead of ascending? \$\endgroup\$ Commented Jul 29, 2020 at 19:07
  • \$\begingroup\$ I don't think it would help \$\endgroup\$ Commented Jul 29, 2020 at 22:28
  • \$\begingroup\$ In which encoding does this take only 10 bytes? \$\endgroup\$ Commented Jul 29, 2020 at 22:42
  • \$\begingroup\$ @NiklasMertsch Jelly has a custom code page (as linked in the header). \$\endgroup\$ Commented Jul 29, 2020 at 23:16
4
\$\begingroup\$

Haskell, 32 bytes

m%r=(m/).foldr(\x u->u/r+x-x/r)m

Try it online!

Port of my Python answer.

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

APL (Dyalog Unicode) 18.0, 15 bytes

÷⊥⍥÷∘(⊃÷2-/,∘0)

Try it online!

J, 16 bytes

#.&.:%{.%2-/\,&0

Try it online!

Inline tacit functions that take the speedup on the left, and duration,occurrences on the right in descending order.

Both code use the same algorithm:

÷⊥⍥÷∘(⊃÷2-/,∘0)
    ∘(        )  On the right argument,
           ,∘0   Append zero
        2-/      Take pairwise differences
      ⊃÷         Divide each number above by the head
                 (division by zero is handled by system setting ⎕DIV←1,
                 which gives 0.)
 ⊥⍥÷             Take reciprocal of both args and do base conversion
÷                Take reciprocal of that

#.&.:%{.%2-/\,&0
\----/\--------/  2-train, so apply the right part on the right arg
             ,&0  Append zero
         2-/\     Take pairwise differences
      {.%         Divide each number above by the head
                  (division by zero gives built-in infinity,
                  whose reciprocal is again zero.)
  &.:%            Apply % (reciprocal) to both args
#.                Base conversion
  &.:%            Undo %, which is the same as applying % again
\$\endgroup\$
2
\$\begingroup\$

J, 20 bytes

Takes the speedup on the left, and the occurrences, length on the right. Calculates the speedup factor.

{:@]%%@[#.2-/\0|.@,]

Try it online!

How it works

 {:@]%%@[#.2-/\0|.@,] 2 f 50 100
               0   ,] prepend 0:   0 50 100
                |.@   reverse:     100 50 0
           2-/\       differences: 50 50
      %@[             1/n:         0.5
         #.           to base:     75
 {:@]                 last element:100
     %                100/75:      1.3333
\$\endgroup\$
3
  • \$\begingroup\$ Is there a way to append 0 instead of prepending 0 in order to eliminate the "reverse" step (You can assume input is provided in descending order instead of ascending in that case)? I tried playing around with your code in the online editor, but it wasn't as simple as I hoped (swapping ] and the 0, and everything else I tried ended with Syntax Errors). \$\endgroup\$ Commented Jul 29, 2020 at 18:38
  • \$\begingroup\$ 0,~] would append 0 (and then you'd need {. in the front to take the first element). But other answers reverse the occurrences list for the base-conversion, too, so I'll keep it this way. \$\endgroup\$
    – xash
    Commented Jul 29, 2020 at 18:49
  • \$\begingroup\$ It seems like some do and some don't: xnor's python answer takes it in descending order for example. You can of course keep it however you prefer for any reason though! \$\endgroup\$ Commented Jul 29, 2020 at 18:59
1
\$\begingroup\$

R, 49 bytes

function(d,f,o)d/diff(c(0,o,d))%*%f^-c(0,seq(!o))

Try it online!

Takes the original duration, the speedup factor, and the ocurrences.

Calculates the time between each occurrence diff(c(0,o,d)), then multiplies them with the appropriate speedup factors f^-c(0,seq(!o)) and sums them as a dot product %*%. Finally divides d by that result.

\$\endgroup\$
1
\$\begingroup\$

Pyth, 14 bytes

chQu+c-GHeQHEh

Try it online!

Port of @xnor's answer to Pyth

Explanation

chQu+c-GHeQHEh
 hQ             : First element from first input
c               : divided by
   u            : value got by reducing from left to right
            E   : the second input
             h  : with default value as first input
                : on lambda G, H:
      -GH       :    G - H
     c   eQ     :    divided by second element from first input
    +      H    :    plus H
\$\endgroup\$
1
\$\begingroup\$

Wolfram Language (Mathematica), 35 33 bytes

s#/Fold[#/s+#2&,{##}-{##2,0}]&

Try it online!

Takes input as f[s][d,o], where o is a sequence of arguments in decreasing order.

\$\endgroup\$
1
\$\begingroup\$

Io, 49 bytes

Port of xnor's Python answer.

method(m,r,l,m/l prepend(m)reduce(u,x,u/r+x-x/r))

Try it online!

\$\endgroup\$
1
\$\begingroup\$

05AB1E, 15 11 bytes

-4 bytes thanks to @KevinCruijssen's port of @JonathanAllan's Jelly answer

ª0š¥RIzβ¹s/

Try it online!

\$\endgroup\$
3
  • 2
    \$\begingroup\$ I didn't get the correct output with the test case: 100, [0], 3. This program outputs 33.3, vs the correct answer of 3. \$\endgroup\$ Commented Jul 29, 2020 at 16:16
  • \$\begingroup\$ Yeah you're right @stevenjackson121 the initial examples for the question were wrong and I had originally written what I have now updated it to be, but it didn't meet the first few examples. I was a bit surprised that it didn't, and assumed I'd misunderstood the question, but then was too busy to look. Here's an updated version with my original solution \$\endgroup\$ Commented Jul 30, 2020 at 10:19
  • 1
    \$\begingroup\$ A port of JonathanAllan's Jelly answer is 11 bytes: ª0š¥RIzβ¹s/, where the middle part DgÝIsm/O in your answer is replaced with RIzβ. \$\endgroup\$ Commented Aug 4, 2020 at 7:18
0
\$\begingroup\$

05AB1E, 18 bytes

¤UćV0š¥εyYNm/}OXs/

Explaination:

¤UćV0š¥εyYNm/}OXs/
¤U                       Extract tail and save duration in X
  ćV                     Extract head and save speedup factor in Y
    0š                   Prepand 0 to the timestamps list
      ¥                  Deltas
       ε     }           map
        y                foreach element
         YNm             factor ** index of element
            /            element / (factor ** index of element) => this will be the duration of this section
              O          sum all up
               Xs        push duration before the result
                 /       division

Input:

A list of numbers in the format: [speedup_factor, ... timestamps_in_minutes ... , duration_in_minutes]

Output:

How much we need to slow down in minutes.

Try it online!

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

C (gcc), 74 69 bytes

Saved 5 bytes thanks to ceilingcat!!!

float f(d,s,o,n,a)float*o,s,a;{for(a=d;n--;)a=a/s+o[n]-o[n]/s;s=d/a;}

Try it online!

Port of xnor's Python answer.

\$\endgroup\$
0

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.