27
\$\begingroup\$

Introduction

Don't you hate it when someone uploads an album you like to YouTube, but the description only contains a track listing? Like this:

1. Everything in Its Right Place - 4:11
2. Kid A - 4:44
3. The National Anthem - 5:50
4. How to Disappear Completely - 5:55
5. Treefingers - 3:42
6. Optimistic - 5:16
7. In Limbo - 3:31
8. Idioteque - 5:09
9. Morning Bell - 4:29
10. Motion Picture Soundtrack - 6:59

Now you don't know when Morning Bell starts unless you sum a bunch of times in your head! Usually, some good soul will come by and leave a handy time table in the (dreaded) comments section, which looks something like this:

(0:00:00) Everything in Its Right Place
(0:04:11) Kid A
(0:08:55) The National Anthem
(0:14:45) How to Disappear Completely
(0:20:40) Treefingers
(0:24:22) Optimistic
(0:29:38) In Limbo
(0:33:09) Idioteque
(0:38:18) Morning Bell
(0:42:47) Motion Picture Soundtrack

Specification

  • Your task is to write a program or function that takes a track listing as input and a time table as output.

    • You may choose to read input from STDIN, or an argument string, or an argument list of lines. Similarly, you may choose to print output to STDOUT, or return a string, or return a list of lines. Failing these, do whatever makes sense for your language.
  • You may assume each input line has the format (\d+)\. [A-Za-z0-9 ]{1,100} - (\d+):(\d\d). For the regex-impaired, this essentially means you can assume each line is well-formatted (as above) and song titles consist only of alphanumeric ASCII characters and spaces, and are no longer than 100 bytes long.

  • A track's length is always at least 0:01 and no more than 59:59.
  • The track numbers are increasing order, starting from 1, and counting up to no more than 99.
  • The total length of an album is no more than 9:59:59.

This is , so shortest code (in bytes) wins.

Test case

Your program should correctly perform the conversion presented in the introduction (Radiohead's Kid A). Here is a bigger test case (Sufjan Stevens' Illinois1) with long strings your program should also work on:

1. Concerning the UFO Sighting Near Highland Illinois - 2:08
2. The Black Hawk War - 2:14
3. Come On Feel the Illinoise - 6:45
4. John Wayne Gacy Jr - 3:19
5. Jacksonville - 5:24
6. A Short Reprise for Mary Todd Who Went Insane but for Very Good Reasons - 0:47
7. Decatur or Round of Applause for Your Stepmother - 3:03
8. One Last Whoo Hoo for the Pullman - 0:06
9. Chicago - 6:04
10. Casimir Pulaski Day - 5:53
11. To the Workers of the Rock River Valley Region - 1:40
12. The Man of Metropolis Steals Our Hearts - 6:17
13. Prairie Fire That Wanders About - 2:11
14. A Conjunction of Drones Simulating the Way - 0:19
15. The Predatory Wasp of the Palisades Is Out to Get Us - 5:23
16. They Are Night Zombies They Are Neighbors They Have Come Back from the Dead Ahhhh - 5:09
17. Lets Hear That String Part Again Because I Dont Think They Heard It All the Way Out in Bushnell - 0:40
18. In This Temple as in the Hearts of Man for Whom He Saved the Earth - 0:35
19. The Seers Tower - 3:53
20. The Tallest Man the Broadest Shoulders - 7:02
21. Riffs and Variations on a Single Note - 0:46
22. Out of Egypt into the Great Laugh of Mankind and I Shake the Dirt from My Sandals as I Run - 4:21

The correct output is:

(0:00:00) Concerning the UFO Sighting Near Highland Illinois
(0:02:08) The Black Hawk War
(0:04:22) Come On Feel the Illinoise
(0:11:07) John Wayne Gacy Jr
(0:14:26) Jacksonville
(0:19:50) A Short Reprise for Mary Todd Who Went Insane but for Very Good Reasons
(0:20:37) Decatur or Round of Applause for Your Stepmother
(0:23:40) One Last Whoo Hoo for the Pullman
(0:23:46) Chicago
(0:29:50) Casimir Pulaski Day
(0:35:43) To the Workers of the Rock River Valley Region
(0:37:23) The Man of Metropolis Steals Our Hearts
(0:43:40) Prairie Fire That Wanders About
(0:45:51) A Conjunction of Drones Simulating the Way
(0:46:10) The Predatory Wasp of the Palisades Is Out to Get Us
(0:51:33) They Are Night Zombies They Are Neighbors They Have Come Back from the Dead Ahhhh
(0:56:42) Lets Hear That String Part Again Because I Dont Think They Heard It All the Way Out in Bushnell
(0:57:22) In This Temple as in the Hearts of Man for Whom He Saved the Earth
(0:57:57) The Seers Tower
(1:01:50) The Tallest Man the Broadest Shoulders
(1:08:52) Riffs and Variations on a Single Note
(1:09:38) Out of Egypt into the Great Laugh of Mankind and I Shake the Dirt from My Sandals as I Run

Leaderboard

For your score to appear on the board, it should be in this format:

# Language, Bytes

var QUESTION_ID=58231,OVERRIDE_USER=3852;function answersUrl(e){return"http://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"http://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>

1. Apologies to Sufjan, whose amazing track names I had to mangle a bit in order to make them fit the simple format this problem is limited to.

\$\endgroup\$
7
  • \$\begingroup\$ May the output contain trailing spaces? \$\endgroup\$ Commented Sep 18, 2015 at 15:39
  • 1
    \$\begingroup\$ Radiohead and Sufjan Stevens? Meh :-P \$\endgroup\$
    – Luis Mendo
    Commented Sep 18, 2015 at 15:45
  • \$\begingroup\$ Nope; the format for each line is (h:mm:ss) Track Name, followed immediately by a newline. \$\endgroup\$
    – lynn
    Commented Sep 18, 2015 at 15:45
  • 1
    \$\begingroup\$ @LuisMendo Feel free to demonstrate your superior music tastes in your answer...? \$\endgroup\$
    – lynn
    Commented Sep 18, 2015 at 15:50
  • \$\begingroup\$ Hahaha. That's a good additional motivation to answer. BTW I liked the challenge and I've upvoted it \$\endgroup\$
    – Luis Mendo
    Commented Sep 18, 2015 at 15:51

9 Answers 9

12
\$\begingroup\$

CJam, 60 57 55 bytes

Thanks to Sp3000 for saving 2 bytes.

qN/{T60bZ0e["(%d:%02d:%02d) "e%\S/1>)':/60bT+:T;W<S*N}/

Test it here.

Explanation

qN/{      e# Read input and split into lines.
  T60b    e# Push T (initially zero, we use this to keep track of the total time in
          e# seconds), and convert it to base 60.
  Z0e[    e# Pad it with zeroes to 3 digits to get hours, minutes, seconds.
  "(%d:%02d:%02d) "e%
          e# Get the (h:mm:ss) part using a format string.
  \S/     e# Pull up the current line, split on spaces.
  1>      e# Discard the first segment, i.e. the track number.
  )':/    e# Pull off the last segment, i.e. the time, and split on colons.
  60b     e# Interpret the two parts as base-60 digits to get the amount of seconds
          e# for the track.
  T+:T;   e# Add this to T and discard it.
  W<      e# Discard the last segment of the remaining string (the hyphen).
  S*N     e# Join the song name back together with spaces and push a line feed.
}/
\$\endgroup\$
1
  • 16
    \$\begingroup\$ goddammit Martin \$\endgroup\$
    – cjfaure
    Commented Sep 18, 2015 at 15:22
6
\$\begingroup\$

Perl, (93 chars plus -p) 94 bytes

s!\d+\. (.+) - (\d+:(\d+))!sprintf"(%d:%02d:%02d) $1",$n/3600,$n%3600/60,$n%60,$n+=$3+60*$2!e

To run:

perl -pe 's!\d+\. (.+) - (\d+:(\d+))!sprintf"(%d:%02d:%02d) $1",$n/3600,$n%3600/60,$n%60,$n+=$3+60*$2!e' <<< '<input>'
\$\endgroup\$
5
\$\begingroup\$

C++, 212 209 202 189 bytes

C++ because.. why not?

#include<iostream>
long d,t,u;main(){std::string a,b(8,0);while(getline(std::cin>>t>>a[0],a,'-')>>t>>b[0]>>u){strftime(&b[0],9,"%T",gmtime(&d));b[0]='(';std::cout<<b+")"+a+'\n';d+=t*60+u;}}

Live: 212 209 202 189

\$\endgroup\$
5
\$\begingroup\$

Python 2, 170 160 Bytes

Been a while since I've done a golf, hopefully this isn't too bad :P

t=0
for i in input().split('\n'):i=i.split(' - ');print'(%d:%02d:%02d)'%(t/3600,t%3600/60,t%60),i[0].split('. ')[1];k=i[-1].split(':');t+=int(k[0])*60+int(k[1])

The input should be surrounded by quotes, and split by newlines, like so:

"1. Concerning the UFO Sighting Near Highland Illinois - 2:08\n2. The Black Hawk War - 2:14\n3. Come On Feel the Illinoise - 6:45\n4. John Wayne Gacy Jr - 3:19\n5. Jacksonville - 5:24\n6. A Short Reprise for Mary Todd Who Went Insane but for Very Good Reasons - 0:47\n7. Decatur or Round of Applause for Your Stepmother - 3:03\n8. One Last Whoo Hoo for the Pullman - 0:06\n9. Chicago - 6:04\n10. Casimir Pulaski Day - 5:53\n11. To the Workers of the Rock River Valley Region - 1:40\n12. The Man of Metropolis Steals Our Hearts - 6:17\n13. Prairie Fire That Wanders About - 2:11\n14. A Conjunction of Drones Simulating the Way - 0:19\n15. The Predatory Wasp of the Palisades Is Out to Get Us - 5:23\n16. They Are Night Zombies They Are Neighbors They Have Come Back from the Dead Ahhhh - 5:09\n17. Lets Hear That String Part Again Because I Dont Think They Heard It All the Way Out in Bushnell - 0:40\n18. In This Temple as in the Hearts of Man for Whom He Saved the Earth - 0:35\n19. The Seers Tower - 3:53\n20. The Tallest Man the Broadest Shoulders - 7:02\n21. Riffs and Variations on a Single Note  - 0:46\n22. Out of Egypt into the Great Laugh of Mankind and I Shake the Dirt from My Sandals as I Run - 4:21"
\$\endgroup\$
2
  • 4
    \$\begingroup\$ I think you can just have %d for the hours counter (if I understand the rules correctly!) for -2! \$\endgroup\$ Commented Sep 18, 2015 at 16:06
  • \$\begingroup\$ Add 4 chars (input to raw_input) to accept the exact format; otherwise I believe it's invalid as it assumes lines in a different format. \$\endgroup\$
    – RK.
    Commented Sep 20, 2015 at 13:44
3
\$\begingroup\$

Gema, 151 characters

\B=@set{t;}
<D>. * - <D>\:<D>=(@div{$t;3600}:@fill-right{00;@div{@mod{$t;3600};60}}:@fill-right{00;@mod{$t;60}}) *@set{t;@add{@add{$t;$4};@mul{$3;60}}}

Sample run:

bash-4.3$ gema '\B=@set{t;};<D>. * - <D>\:<D>=(@div{$t;3600}:@fill-right{00;@div{@mod{$t;3600};60}}:@fill-right{00;@mod{$t;60}}) *@set{t;@add{@add{$t;$4};@mul{$3;60}}}' tracklist.txt
(0:00:00) Concerning the UFO Sighting Near Highland Illinois
(0:02:08) The Black Hawk War
(0:04:22) Come On Feel the Illinoise
(0:11:07) John Wayne Gacy Jr
(0:14:26) Jacksonville
(0:19:50) A Short Reprise for Mary Todd Who Went Insane but for Very Good Reasons
(0:20:37) Decatur or Round of Applause for Your Stepmother
(0:23:40) One Last Whoo Hoo for the Pullman
(0:23:46) Chicago
(0:29:50) Casimir Pulaski Day
\$\endgroup\$
3
\$\begingroup\$

Python 2, 207 206 bytes

h=m=s=0
for i in raw_input().splitlines():
 print("(%d:%.2d:%.2d) "%(h,m,s),i.split('-')[0].split('. ')[1])
 t=i.split('-')[1].split(':')
 m+=int(t[0]);s+=int(t[1]);r=s//60;s-=r*60;m+=r;r=m//60;m-=r*60;h+=r

Usage

$ python test.py
'1. Concerning the UFO Sighting Near Highland Illinois - 2:08\n2. The Black Hawk War - 2:14\n3. Come On Feel the Illinoise - 6:45'
(0:00:00) Concerning the UFO Sighting Near Highland Illinois 
(0:02:08) The Black Hawk War 
(0:04:22) Come On Feel the Illinoise 
\$\endgroup\$
2
  • 1
    \$\begingroup\$ What version of Python 3 are you using? I thought raw_input only existed in Python 2. \$\endgroup\$
    – lynn
    Commented Sep 18, 2015 at 15:53
  • \$\begingroup\$ Fixed. I guess I'm just used to typing "3". @Mauris \$\endgroup\$
    – Zach Gates
    Commented Sep 18, 2015 at 15:56
1
\$\begingroup\$

awk, 119 101 bytes

{split($NF,t,":");$1=$(--NF)="";--NF;print"("substr(strftime("%H:%M:%S",s,1),2)")"$0;s+=t[1]*60+t[2]}

This is way longer than I wanted it to be. The problem is that %H doesn't format the hours like requested, so I needed to calculate the hours myself.

Ack, I'm stupid. The results of strftime were wrong because I needed to tell it to use UTC time. That cut 18 bytes off!

119-byte version

{split($NF,t,":");$1=$(--NF)="";--NF;print"("(h||0)":"strftime("%M:%S",s)")"$0;s=(r=s+t[1]*60+t[2])%3600;h=int(r/3600)}
\$\endgroup\$
0
\$\begingroup\$

Python 3 (3.8>=), 115 bytes

a=0
while 1:_,*s,_,t=input().split();print(f"({a//3600}:%02d:%02d)"%(a//60%60,a%60),*s);a+=int(t[0])*60+int(t[2:4])

Ungolfed version:

a = 0
while True:
    _,*s,_,t = input().split()                         # Skip firt element and the second to last 
    print(f"({a//3600}:%02d:%02d)"%(a//60%60,a%60),*s) # Print time + what is between the number and the -
    a+=int(t[0])*60+int(t[2:4])                        # Increment time

Exit with error.

Attempt This Online!

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

Ruby, 112 109 bytes

-3 bytes thanks to Steffan

a=0
loop{_,*s,_,t=gets.split;puts "(%d:%02d:%02d) "%[a/3600,a/60%60,a%60]+s*' ';a+=t[0].to_i*60+t[2..4].to_i}

Exit with error

Attempt This Online!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ (...)while 1 => loop{...} \$\endgroup\$
    – naffetS
    Commented Jul 8, 2022 at 1:18

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.