Match the Striking Clock

JavaScript (ES6), 104 bytes

Prints time intervals in H.MM,H.MM format.

F=(n,f=0,s=n,t=f++)=>t<f+23?F(n,f,s-=t&1||t/2%12+1,++t,s||alert([f/2%12+.01,-~t/2%12+.01])):f<24&&F(n,f)

Try it online!

Uses essentially the same algorithm as the non-recursive version below.


Non-recursive version, 117 bytes

Outputs a space-delimited string of time intervals in H.MM,H.MM format.

n=>[...Array(24)].map((_,f,a)=>a.map(_=>(s-=t++&1||t/2%12+.5)||(r+=[-~f/2%12+.01,-~t/2%12+.01]+' '),s=n,t=f),r='')&&r

Test cases

let f =

n=>[...Array(24)].map((_,f,a)=>a.map(_=>(s-=t++&1||t/2%12+.5)||(r+=[-~f/2%12+.01,-~t/2%12+.01]+' '),s=n,t=f),r='')&&r

console.log(f(8))
console.log(f(14))
console.log(f(90))
console.log(f(1))
console.log(f(2))

Commented

n =>                           // n = input
  [...Array(24)].map((_, f, a) // FOR f = 0 TO 23:
    => a.map(_ =>              //   FOR t = f TO f + 23:
      (                        //     update s
        s -=                   //       by subtracting:
          t++ & 1 ||           //         - 1 if t is odd (half hour)
          t / 2 % 12 + .5      //         - the current hour if t is even
      ) || (                   //     if s is equal to zero:
        r += [                 //       update the result string by appending:
          -~f / 2 % 12 + .01   //         - the formatted 'from' time
          ,                    //         - a comma
          -~t / 2 % 12 + .01   //         - the formatted 'to' time
        ] + ' '                //       and a padding space
      ),                       //     inner map() initialization:
      s = n,                   //     - s = target number of strikes
      t = f                    //     - 'to' time = 'from' time
    ),                         //   end of inner map()
    r = ''                     //   start with r = empty string
  )                            // end of outer map()
  && r                         // return r

APL (Dyalog Unicode), 62 59 bytesSBCS

Full program body. Prompts for n. Prints list of two-element lists using decimal hours.

∪(⎕=∊l+/¨⊂48⍴∊1,¨⍳12)/(¯.1 .1+⊃,⊢/)¨⊃,/(l←⍳48),/¨⊂.5×48⍴⍳24

Try it online!

⍳24ɩndices 1…24

48⍴ cyclically reshape to length 48, i.e. 1…12,1…12

.5× multiply a half by that

 enclose (to use this entire array as right argument for each left argument)

(),/¨ for each of the following, return all the sub-lists of that length:

⍳48ɩndices 1…48

l← store in l (for lengths)

Now we have all the possible lists of runs of times for each possible run-length.

,/ concatenate (lit. concatenation-reduction) the lists of sub-lists

 disclose (because the reduction reduced the rank from 1 to 0)

( apply the following function to each:

⊢/ the last (lit. right-reduction) element (the end time)

⊃, prepend the first element (the beginning time)

¯.1 .1+ add negative and positive tenths to those

()/ filter those begin-end pairs with:

⍳12ɩndices 1…12

1,¨ prepend a 1 to each

ϵnlist (flatten)

48⍴ cyclically reshape to length 48, i.e. 1,1,1,2…1,11,1,12

 enclose (to use this entire array as right argument for each left argument)

l+/¨ for each of l (1…48) return the sums of all the sub-lists of that length

ϵnlist (flatten)

⎕= compare numeric input to that

 return just the unique elements (begin-end pairs)


Python 3, 118 116 bytes

lambda n:[(a/2+.4,b%24/2+.1)for a in range(24)for b in range(48)if sum((sum(zip([1]*12,range(1,13)),())*2)[a:b])==n]

Try it online!

A timeframe is represented as (t1, t2), t1 and t2 being decimals representing hours. The offset is .1 or 6 minutes.