10
\$\begingroup\$

Imagine you have two lights. These lights blink on and off at a specific rate:

Light 0: Delay 0ms and then blink every 1000ms
Light 1: Delay 500ms and then blink every 1000ms

Let's simulate these lights for the first 2000ms:

0ms:    Light 0 on
500ms:  Light 1 on
1000ms: Light 0 off
1500ms: Light 1 off
2000ms: Light 0 on

The challenge

Given a list of ordered pairs representing the timing for lights, write a program or function to output the sequence for when they blink.

Input

The input should be in the following format:

TimeToSimulate
Light0Delay,Light0Period
Light1Delay,Light1Period
...

In this format, the example above would be:

2000
0,1000
500,1000

Output

The output should be a series of ordered triples:

Time,LightNum,LightStatus

LightStatus is a truthy value if the light turns on and a falsy value if the light turns off.

The output from the above example would be:

0,0,True
500,1,True
1000,0,False
1500,1,False
2000,0,True

If two lights blink at the same time, the light with the lower number should display first in the output.

Other stuff

  • The input and output formats aren't strict
  • Code shouldn't produce any errors
  • The solution shouldn't rely on race conditions
  • No standard loopholes
  • This is , so shortest solution wins!

Test cases

Input:

2000
0,1000
500,1000

Output:

0,0,True
500,1,True
1000,0,False
1500,1,False
2000,0,True

----

Input:

2
0,1
0,1

Output:

0,0,True
0,1,True
1,0,False
1,1,False
2,0,True
2,1,True

----

Input:

500
100,50
200,100
300,150

Output:

100,0,True
150,0,False
200,0,True
200,1,True
250,0,False
300,0,True
300,1,False
300,2,True
350,0,False
400,0,True
400,1,True
450,0,False
450,2,False
500,0,True
500,1,False

----

Input:

1000
23,345
65,98
912,12
43,365

Output:

23,0,True
43,3,True
65,1,True
163,1,False
261,1,True
359,1,False
368,0,False
408,3,False
457,1,True
555,1,False
653,1,True
713,0,True
751,1,False
773,3,True
849,1,True
912,2,True
924,2,False
936,2,True
947,1,False
948,2,False
960,2,True
972,2,False
984,2,True
996,2,False

Leaderboard Snippet:

var QUESTION_ID=137465,OVERRIDE_USER=41505;function answersUrl(e){return"https://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"https://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>

\$\endgroup\$
  • \$\begingroup\$ How much output is enough? \$\endgroup\$ – aschepler Aug 3 '17 at 22:57
  • \$\begingroup\$ @aschepler What do you mean? The input specifies an amount of time to "simulate" \$\endgroup\$ – Daniel M. Aug 3 '17 at 22:58
3
\$\begingroup\$

JavaScript, 98 97 bytes

a=>b=>[...Array(a+1)].map((_,i)=>b.map((d,j)=>d[0]--||c.push([i,j,d[d[0]=d[1]-1,2]^=1])),c=[])&&c

Try it online

Saved a byte thanks to Shaggy - use currying input syntax.

\$\endgroup\$
  • \$\begingroup\$ Save a byte with currying: a=>b=>. \$\endgroup\$ – Shaggy Aug 3 '17 at 23:08
  • \$\begingroup\$ @Shaggy. You're so fast, I was preparing an edit. \$\endgroup\$ – user72349 Aug 3 '17 at 23:10
  • \$\begingroup\$ Rule of thumb: if there are 2 inputs, always curry! \$\endgroup\$ – Shaggy Aug 3 '17 at 23:11
3
\$\begingroup\$

Python 2, 93 bytes

lambda t,l:sorted(sum([zip(range(x[0],-~t,x[1]),[i]*-~t,[1,0]*t)for i,x in enumerate(l)],[]))

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Jelly,  26  25 bytes

Ḣrm⁸ð€µ;€€"J;"J$€€ẎẎḂ0¦€Ṣ

A dyadic link taking a list of delay, period number-lists and a time-frame number and returning a list of time, light, action integers.

The lights are 1-indexed and 0 represents the 'off' action, while 1 represents the 'on' action.

Try it online!

How?

Ḣrm⁸ð€µ;€€"J;"J$€€ẎẎḂ0¦€Ṣ - Link: [[delay, period],...], time-frame 
    ð€                    - for €ach [delay, period]:
Ḣ                         -   head (get the delay and modify the item to [period])
 r                        -   inclusive range to time-frame = [delay,delay+1,...,time-frame]
   ⁸                      -   chain's left argument = [period]
  m                       -   modulo slice = [delay, delay+period, delay+2*period, ...]
      µ                   - monadic chain separation, call that v
           J              - range(length(v)) = [1,2,...,nLights]
          "               - zip with:
       ;€€                -   concatenate for €ach for €ach (add light indexes to times)
               $€€        - last two links as a monad for €ach for €ach:
              J           -   range (length(switch-times-for-a-light))
             "            -   zip with:
            ;             -     concatenation (i.e. append a 1-based index)
                  ẎẎ      - tighten & tighten again (flatten by 2 to a list of triples)
                      |€  - sparse application of (for €ach):
                     0    - ...to indexes: 0 (=last entry)
                    Ḃ     - ...action: modulo by 2 (even appended indexes ->0s; odds -> 1s)
                        Ṣ - sort the resulting list of triples
\$\endgroup\$
2
\$\begingroup\$

Python 2, 206 214 bytes

  • Added eight bytes to comply with the rules (taking input via stdin).
Q=input();D,T=Q[0],[map(int,q.split(","))for q in Q[1:]];O,l=[],len(T)
for j in range(l):
	t,b=T[j][0],9>8
	while t<=int(D):O+="%0*d,%0*d,%s"%(len(D),t,len(str(l)),j,b),;b=not b;t+=T[j][1]
print"\n".join(sorted(O))

Try it online!

This code generates an unordered lists containing each light's switching times, pads those times and the light identifier, sorts said list and outputs it.

\$\endgroup\$
  • \$\begingroup\$ By standard rules you must take input you cannot expect it to pre-exist in a variable. You'll probably find that using input() will allow you to cut they byte-count down too (no string parsing will be required since Python 2's input() is eval(raw_input())) :). \$\endgroup\$ – Jonathan Allan Aug 4 '17 at 0:13
  • \$\begingroup\$ ...also if you use numbers rather than strings in O they'll sort, which would probably also cut the byte count, \$\endgroup\$ – Jonathan Allan Aug 4 '17 at 0:16
  • \$\begingroup\$ @JonathanAllan Thanks for noticing the rule discrepency; I will not incorporate your suggestions as there is a significantly shorter Python 2 answer by now. \$\endgroup\$ – Jonathan Frech Oct 22 '17 at 21:15
1
\$\begingroup\$

Perl 5, 106 + 1 (-n) = 107 bytes

($a[$i],$b[$i++])=eval for<>;for$i(0..$_){for(0..$#a){$a[$_]+=$b[$_],say"$i,$_,".($s[$_]^=1)if$i==$a[$_]}}

Try it online!

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

Haskell, 121 bytes

import Data.List
t!l=sort$(zip[0..]l)>>=takeWhile(\(a,_,_)->a<=t).(\(i,(d,w))->iterate(\(t,i,s)->(t+w,i,not s))(d,i,2>1))

Try it online.

This is the program I started from:

import Data.List

type LightId = Int
type Time = Int
type State = Bool
type LightEvent = (Time, LightId, State)

lightSimulation :: Time -> Time -> [(Time, State)]
lightSimulation delay interval = iterate step (delay, True)
  where step (time, state) = (time+interval, not state)

addId :: LightId -> (Time, State) -> LightEvent
addId id (t, s) = (t, id, s)

simulate :: Time -> [(Time, Time)] -> [LightEvent]
simulate timeLimit lights = sort $ concatMap lightSim (zip [0..] lights)
  where withinTimeLimit = ((<=timeLimit) . fst)
        lightSims (id, (delay, interval)) = map (addId id) $ takeWhile withinTimeLimit (lightSimulation delay interval)

And before final golfing I has shortened it to:

import Data.List

light (id,(delay,interval)) = iterate step (delay, id, True)
  where step (time, id, state) = (time+interval, id, not state)

simulate timeLimit lights = sort $ concatMap lightSims (zip [0..] lights)
  where lightSims l = takeWhile(\(a,b,c)->a<=timeLimit)$light l
\$\endgroup\$
1
\$\begingroup\$

Röda, 105 87 85 bytes

{|t|enum|[([_+_]*(t-_1[0]+1))()|enum|(_+_)]|{[[_+_4,_3,_4//_2%2=0]]if[_4%_2=0]}|sort}

Try it online!

Explanation:

{|t| /* Declare a lambda with one parameter */
/* The input stream contains arrays */
enum| /* For each array in the input, push an ascending number after it */
/* [1] (for stream content in this point, see below) */
[ /* For each array-number pair in the stream: */
    (
        [_+_] /* Create a copy of the array with the number as the last element */
        *(t-_1[0]+1) /* Create copies of the array for every ms simulated */
    )()| /* Push all copies to the stream */
    enum| /* After each copy, push an ascending number to the stream */
    (_+_) /* Append the number to each array before */
]|
/* [2] (for stream content in this point, see below) */
{
    /* Push an on or off event to the stream: */
    [[
        _+_4,      /* delay + time = actual time */
        _3,        /* light-id */
        _4//_2%2=0 /* does the light go on or off? */
    ]] 
    if[_4%_2=0] /* if the light goes on or off (time%period=0) */
}|
/* [3] (for stream content in this point, see below) */
sort /* Sort the events */
}

The stream contains at point [1] values in the following order:

[delay, period], light-id
 _1[0]  _1[1]    _2

The stream contains at point [2] values in the following order:

delay, period, light-id, time
_1     _2      _3        _4

The stream contains at point [3] arrays with the following structure:

[time, light-id, on_or_off]
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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