It turns out that my toaster is a tad broken. It lost WiFi (You know, it's one of those newfangled smart toasters), and its been going bonkers! Since it no longer works, I've been having to hack into my breakfast's source code and run Plate.bread.toastAs(3); every morning. Will you help?

My toaster takes one input: the amount of time you want to toast your bread. This is written as min:sec, such as 5:45 or 0:40 (Up to 59:59). It then returns a specific value for different levels of toastiness:

0:00-0:30 = Bread
0:31-1:00 = Warm Bread
1:01-2:00 = Toasty
2:01-3:30 = Burnt
3:31 and up = Brûlée (or Brulee)

But here's the catch: my toaster has a broken keyboard! Your code can't contain any semicolons or...colons. This might be harder than the toaster repairman said it would be...

Here are some test cases, so you can...test your cases?

0:00 = Bread
5:50 = Brulee or Brûlée
2:00 = Toasty
ChicknMcNuggets = Anything
-1:00 = Anything
0:60 = Anything
1 = Anything
60:00 = Anything
1:00:00 = Anything
  • \$\begingroup\$ Is the time at most 59:59? \$\endgroup\$ – xnor Nov 3 '18 at 2:47
  • 5
    \$\begingroup\$ Shouldn't it be 3:31 and up: Brulee? \$\endgroup\$ – Mego Nov 3 '18 at 4:17
  • 3
    \$\begingroup\$ Where are all the golfing languages where colons wouldn't be used anyway? \$\endgroup\$ – Jo King Nov 3 '18 at 6:13
  • 1
    \$\begingroup\$ I have't realized until now why there aren't any Python submissions... \$\endgroup\$ – Redwolf Programs Nov 3 '18 at 13:43
  • 1
    \$\begingroup\$ Can we take in input with a leading zero so that all inputs are 5 characters long? \$\endgroup\$ – Quintec Nov 3 '18 at 16:58

19 Answers 19


Python 2, 124 118 116

print["Bread","Warm Bread","Toasty","Burnt","Brulee"][sum([t>3.3,t>2,t>1,t>.3])]

Try it online!

-6 with thanks to @tsh and also thanks for tho TIO test cases.

-2 with a couple of cool tips from @BlackOwlKai

Throws a ValueError for invalid inputs that cannot be converted to a float. For numbers less than 0 it returns "Bread" because it is still bread. Guess if we are really strict on ensuring that the input is a valid time it could be done but for me the interesting bit was how to avoid the : in Python.

  • \$\begingroup\$ 118 bytes \$\endgroup\$ – tsh Nov 3 '18 at 16:03
  • \$\begingroup\$ @tsh Thanks for the neat trick and thanks also for the TIO tests. \$\endgroup\$ – ElPedro Nov 3 '18 at 16:48
  • \$\begingroup\$ -1 byte by replacing float by eval \$\endgroup\$ – Black Owl Kai Nov 3 '18 at 18:11
  • 1
    \$\begingroup\$ Thanks @BlackOwlKai. Hadn't seen that. Will update tomorrow with appropriate credits ☺ \$\endgroup\$ – ElPedro Nov 3 '18 at 22:01
  • 1
    \$\begingroup\$ -1 byte because chr(58) can be shortened to "\x3A" \$\endgroup\$ – Black Owl Kai Nov 3 '18 at 22:11

T-SQL, 409 379 328 318 bytes

DECLARE @i varchar(9)DECLARE @a time='0'+CHAR(58)+@i DECLARE @ int=DATEPART(N,@a),@s int=DATEPART(S,@a)SELECT CASE WHEN @<1AND @s<31THEN'Bread'WHEN @<1OR @=1AND @s=0THEN'Warm Bread'WHEN @<2OR @=2AND @s=0THEN'Toasty'WHEN @<3OR @<4AND @s<31THEN'Burnt'ELSE'Brulee'END WHERE LEN(RIGHT(@i,LEN(@i)-CHARINDEX(CHAR(58),@i)))=2

-30 bytes: removed AS keywords, combined DECLARE statements (thanks to BradC)
-51 bytes: changed declarations/where clause to take advantage of SQL's datetime functionality
-10 bytes: changed MINUTE to N and SECOND to S (thanks to BradC)

Did you know that SQL can't natively split strings in any decent capacity? Don't let STRING_SPLIT fool you; it doesn't work for this. Or at least, I'm not smart enough to figure it out.

Different from BradC's table-based T-SQL solution.


-- Input variable
DECLARE @i varchar(9)

-- Time declarations (passes in as form "00:mm:ss")
-- CHAR(58) maps to ':'
DECLARE @a time = '0' + CHAR(58) + @i

-- Integer declarations
DECLARE @ int = DATEPART(N, @a),    -- minutes
        @s int = DATEPART(S, @a)    -- seconds

            WHEN @ < 1 AND @x < 31              -- 0:00 - 0:30
                THEN 'Bread'
            WHEN @ < 1 OR @ = 1 AND @x = 0      -- 0:31 - 1:00
                THEN 'Warm Bread'
            WHEN @ < 2 OR @ = 2 AND @x = 0      -- 1:01 - 2:00
                THEN 'Toasty'
            WHEN @ < 3 OR @ < 4 AND @x < 31     -- 2:01 - 3:30
                THEN 'Burnt'
            ELSE 'Brulee'                       -- 3:31 - 59:59

-- Setting input as a time means that you only have to check if the seconds input is two characters, all other checks accounted for
WHERE LEN(RIGHT(@i, LEN(@i) - CHARINDEX(CHAR(58), @i))) = 2
  • \$\begingroup\$ You could do something like SELECT value FROM STRING_SPLIT(@i,CHAR(58)), although I'm wondering if a TRY_CAST(@i AS TIME) might cut some corners. \$\endgroup\$ – BradC Nov 8 '18 at 22:48
  • \$\begingroup\$ Interesting language for golfing! \$\endgroup\$ – Redwolf Programs Nov 9 '18 at 2:17
  • \$\begingroup\$ @BradC I tried doing STRING_SPLIT like that, but it doesn't exactly work as you'd think - it actually returns both values from each side simultaneously, and you can't do any checks on the data (at least that I could figure out). As for using TRY_CAST, it looks like it would require having "00:" appended to the front. I might be able to work further with that. \$\endgroup\$ – Meerkat Nov 9 '18 at 14:15
  • 1
    \$\begingroup\$ Yeah, STRING_SPLIT returns them as separate rows. Even without changing those parts, you can still save a ton of bytes by keeping only your very first DECLARE and changing the rest to commas. Also drop AS and just do DECLARE @i varchar(99),@a varchar(9)=... \$\endgroup\$ – BradC Nov 9 '18 at 14:31
  • \$\begingroup\$ Yeah, good call. Since @a and @b both require @i though, I have to declare that separately. Can still save quite a few bytes there though. \$\endgroup\$ – Meerkat Nov 9 '18 at 14:35

Java 8, 148 bytes

a lambda from String to String

t->{float n=new Float(t.replace("\72","."))\u003breturn n>3.3?"Brulee"\u003an>2?"Burnt"\u003an>1?"Toasty"\u003an>.3?"Warm Bread"\u003a"Bread"\u003b}

\u003b and \u003a are source-level Unicode escape sequences for ; and : respectively.

Try It Online


t -> {
    float n = new Float(t.replace("\72",".")) \u003b
        n > 3.3 ? "Brulee" \u003a
            n > 2 ? "Burnt" \u003a
            n > 1 ? "Toasty" \u003a
            n > .3 ? "Warm Bread" \u003a


  • \$\begingroup\$ .replaceAll can be .replace and Integer.parseInt can be new Integer, or new Short even, to save 10 bytes: Try it online 162 bytes. \$\endgroup\$ – Kevin Cruijssen Nov 19 '18 at 10:18
  • \$\begingroup\$ 148 bytes by changing the split to a simple ternary operator and using a float instead of an int to spare on the "hundreds" bytes. \$\endgroup\$ – Olivier Grégoire Nov 19 '18 at 11:22
  • \$\begingroup\$ Nice. Thanks guys! \$\endgroup\$ – Jakob Nov 21 '18 at 4:13

JavaScript (SpiderMonkey), 100 bytes

a=>'Bread,Warm Bread,Toasty,Burnt,Brulee'.split`,`[((t=a.replace(/\D/,'.'))>3.3)+(t>2)+(t>1)+(t>.3)]

Try it online!

JavaScript (Node.js), 91 bytes

a=>[,b='Bread','Warm '+b,o='Toasty',o,u='Burnt',u,u][new Date([70,a])/-~18e5+1|0]||'Brulee'

Try it online!

  • \$\begingroup\$ The second solution is invalid since it contains a : in the source code. \$\endgroup\$ – kamoroso94 Nov 3 '18 at 18:00
  • \$\begingroup\$ @kamoroso94 rolled back. \$\endgroup\$ – tsh Nov 3 '18 at 18:35

PHP, 96 bytes

<?=[Bread,"Warm Bread",$t=Toasty,$t,$u=Burnt,$u,$u,Brulee][min(7,2*$argn+substr($argn,-2)/30)]?>

requires PHP 5.5 or later. Run as pipe with -nF or try it online.


T-SQL, 143 155 145 bytes

(VALUES(31,'Bread'),(61,'Warm Bread'),(121,'Toasty'),(211,'Burnt'),(1E4,'Brulee'))t(a,b)
WHERE a>DATEDIFF(s,0,'0'+CHAR(58)+v)

Line breaks are for readability only. Different method than Meerkat's variable-based SQL solution.

Input is taken via pre-existing table i with varchar field v, per our IO standards. That input table is cross-joined to an in-memory table t with our cutoff values (in seconds) and the desired labels.

The magic happens in the WHERE clause: DATEDIFF calculates the difference in seconds between midnight and our input (with an extra 0: attached to the front), then returns the lowest matching label (via the TOP 1).

Invalid inputs either return an unpredictable value or throw an error:
Conversion failed when converting date and/or time from character string.

The question was a little vague, but if needed I can avoid these errors (and return nothing) by adding the following LIKE pattern to the WHERE clause, bringing the total bytes to 238 211 201:

AND RIGHT('0'+v,5)LIKE'[0-5][0-9]'+CHAR(58)+'[0-5][0-9]'

EDIT: My original shorter submission was failing for inputs over 24:00, since I was treating it as hh:mm. Had to add the '0'+CHAR(58)+ prefix, which added 12 bytes.

EDIT 2: Shaved 27 bytes from the LIKE in my alternate version

EDIT 3: Removed ORDER BY from both versions, as it proved unnecessary in testing. (SQL doesn't guarantee sort order will be maintained without an explicit ORDER BY, but it seemed to work fine for me in this specific case.)


05AB1E, 43 42 bytes


Try it online or verify some more test cases.


þ                # Leave only the digits of the (implicit) input
                 #  i.e. "1:15" → 115
 30              # Push 30
   т             # Push 100
    x            # Pop and push 100 and 100 doubled (200)
     330         # Push 330
        )        # Wrap the stack into a list: [inputDigits,30,100,200,330]
         ć       # Pop and push the head and rest of array as separated items to the stack
          ‹      # Check for each if its smaller than the head (1=truthy, 0=falsey)
                 #  i.e. [30,100,200,330] and 115 → [1,1,0,0]
           O     # Take the sum of this
                 #  i.e. [1,1,0,0] → 2
„©Ãº™            # Push string "warm bread"
     D#          # Duplicate it, and split it by spaces: ["warm","bread"]
       θ         # And only leave the last element: "bread"
        ‚R       # Pair them into a list, and reverse that list: ["bread","warm bread"]
.•liSÕô6>Āµ·•    # Push string "bruleetoastyburnt"
             6ô  # Split into parts of size 6: ["brulee","toasty","burnt"]
               À # Rotate it once towards the left: ["toasty","burnt", "brulee"]
«                # Merge both lists together:
                 #  ["bread","warm bread","toasty","burnt","brulee"]
 ™               # Titlecase each word: ["Bread","Warm Bread","Toasty","Burnt","Brulee"]
  s              # Swap so the number is at the top of the stack again
   è             # Index it into the list (and output implicitly)
                 #  i.e. 2 → "Toasty"

See this 05AB1E tip of mine (sections How to use the dictionary? and How to compress strings not part of the dictionary?) to understand why „©Ãº™ is "warm bread" and .•liSÕô6>Āµ·• is "bruleetoastyburnt".

þ30тx330)ć can alternatively be 30тx)DOªsþ for the same byte-count: Try it online.


Javascript(ES6+), 180 bytes

Node.js(180 bytes)

let f=(s,i=s.split("\u{3a}"),j=i[0]*60+1*i[1],k="Bread",l=assert(new RegExp("^(.|[0-5].)\u{3a}[0-5].$").test(s)))=>eval("(j<31)?k\u{3a}(j<61)?'Warm '+k\u{3a}(j<121)?'Toasty'\u{3a}(j<211)?'Burnt'\u{3a}'Brulee'")

Browser(188 bytes):

let f=(s,i=s.split("\u{3a}"),j=i[0]*60+1*i[1],k="Bread",l=console.assert(new RegExp("^(.|[0-5].)\u{3a}[0-5].$").test(s)))=>eval("(j<31)?k\u{3a}(j<61)?'Warm '+k\u{3a}(j<121)?'Toasty'\u{3a}(j<211)?'Burnt'\u{3a}'Brulee'")

Gotta use those unicode escape sequences :-) just a big chain of ternary operators, with variables defined by default parameters. Also a one-liner, so no semicolon-hungry js

  • \$\begingroup\$ I used a regex to enforce the 59:59 & no negatives rule :-) \$\endgroup\$ – Michael Nov 3 '18 at 4:14
  • \$\begingroup\$ OH WAIT I forgot i added : \$\endgroup\$ – Michael Nov 3 '18 at 4:15
  • \$\begingroup\$ actually done :-) \$\endgroup\$ – Michael Nov 3 '18 at 4:21
  • 1
    \$\begingroup\$ You don't need a regex to enforce the 59:59 and no negatives...they can result in anything, be it an error, nothing, or Brulee. \$\endgroup\$ – Redwolf Programs Nov 3 '18 at 13:40

Retina 0.8.2, 97 bytes

Warm #

Try it online! Link includes test cases. Explantion:


Convert the minutes and seconds to unary.


Multiply the minutes by 60 and add to the seconds.


Decode the seconds into the toastiness.

Warm #

Decode Warm Bread by noting that # (for 0:00) decodes to Bread.


If we don't have a toastiness yet then the bread is still cold.


Perl 6, 86 79 67 bytes

-4 bytes thanks to nwellnhof! -12 bytes by porting tsh's solution

{<<Bread'Warm Bread'Toasty Burnt Brulee>>[sum S/\D/./X>.3,1,2,3.3]}

Try it online!


C (gcc), 130 bytes

f(a){if(*strchr(a,58)=48,a=atoi(a),a=(int*[]){"Bread","Warm Bread","Toasty","Burnt","Brulee"}[(a>30)+(a>1e3)+(a>2e3)+(a>3030)]){}}

Try it online!


Snap! 4.2, 257 251 bytes

Minified the text version some more.

I haven't found any answers in Snap!, a visual programming language similar to Scratch, so I'll use scratchblocks2 syntax, pretending that Snap! exclusive blocks are valid in scratchblocks2.

Try it online! (click the button with the two arrows to see the code)

when gf clicked
ask[]and wait
set[l v]to(split(answer)by(unicode(58)as letter
set [t v]to(((item(1 v)of(l))*(60))+(item(2 v)of(l
say[Warm Bread

R, 127 122 bytes

function(t)cut((x=eval(parse(t=t)))[1]*60+tail(x,1),30*c(0:2,4,7,Inf),c("Bread","Warm Bread","Toasty","Burnt","Brulee"),T)

Try it online!

Returns a factor with the appropriate level.

-5 bytes thanks to JayCe.

  • \$\begingroup\$ Would this work? tio.run/… \$\endgroup\$ – JayCe Nov 8 '18 at 22:56
  • \$\begingroup\$ @JayCe IDK, the input is "any acceptable format" but then everything takes the string...I'll ask in the comments. \$\endgroup\$ – Giuseppe Nov 8 '18 at 23:06
  • \$\begingroup\$ @JayCe I'm not sure what you mean. As far as I can see, it takes the time as an input to a function which is an acceptable input IMO \$\endgroup\$ – Redwolf Programs Nov 9 '18 at 2:20
  • \$\begingroup\$ And you can also do 30*c(0,1,2,4,7,Inf) \$\endgroup\$ – JayCe Nov 9 '18 at 3:59
  • \$\begingroup\$ @RedwolfPrograms the input isn't a time, it's an array, : is the sequence operator. \$\endgroup\$ – Giuseppe Nov 9 '18 at 15:58

Japt, 48 bytes

W‡m BÎ%

Try it online!

Saved 5 bytes by actually reading the tips...


`BÎ%...BrÔ‡`·                       Compressed array of possible outputs
             g                      Get the one at the index given by...
                         è          The number of items...
              [30LLÑ,330]           From the list [30,100,200,330]...
                          <Ur58d    Which are less than the input without ":"

An extra byte could be saved by outputting in all lower case.


Jelly, 43 41 40 bytes


Try it online!

Explanation (old)

“¡Ḳḋ\ḞvṾƤSİƓƥeF½ÞØ+®°» is the compressed string Warm Bread\nToasty\nBurnt\nBrulee\nBread, found by the compression optimizer.

fØD                               Filter out the non-digits (i.e. colon) from input
   ~~                             Use binary NOT twice to convert to digit list
      HḞ                        Halve and floor. Now we have "01:45" -> 72.
        “Ç1cƥ‘                    The array [14,49,99,164]
              <                   Vectorized less than
               S                  Sum
fØD~~ḌHḞ“Ç1cƥ‘<S                How many threshold times is input less than?
                                           (0 -> Bread, 4 -> Brulee.)
                ị               Index (note 0ị gives the last list item) into
                       ¤        the new dyadic link given by
                 “...»            The long string, decoded and
                      Ỵ           split by newlines.

Inspired by Kamil Drakari's answer.

-2 bytes using snippet ~~Ḍ from Dennis.


Runic Enchantments, 118 bytes

\uqn.3X)?\ . 1C)?\.2C)?\'Ŋ)?\"Brulee"
\D"daerB"L" mraW"/
$L"ytsaoT"L?9"tnruB"L?aL?3 F/

Try it online!

Utilizes some unprinting ASCII characters (STX, EOT, SOH, STX, VT, SOH, STX, DC2, SOH, and STX in that order) on the first line, which is reading in a sequence of bytes in the order that they're going to be needed on the stack. 3 divide ('t'/2 equals :) and reflective-write operations are then performed. This puts 3 : (duplicate) commands where there are currently . (NOP) in order to non-destructively compare the input with the time thresholds. A fourth : is left on the stack before reading input.

Time is read in as a string, then split on :, and concatenated back into a string. As values above 59:59 do not have any specification on output, values like 1:00:00 will have undefined (but deterministic) output. This string is then converted to a number and compared against 30, 100, 200, and 330 (the byte value of Ŋ). "Bread" (line 3, executing RTL) is used twice, both for Bread and Warm Bread results, saving at least 5 bytes.

Saves 1 byte by not having a classic terminator command (;) by using Fizzle on the last line instead. This convinces the parser that the program is guaranteed to terminate without causing it to do so immediately (and, more importantly, not touching the stack). Valid inputs will leave the stack empty so that when it loops around and touches a w the IP is terminated for performing an illegal action.


Javascript, 115 101 bytes

-6 from tsh

d=>[b="Bread","Warm "+b,a="Toasty",a,c="Burnt",c,c][~~(parseInt(d)*1.999+d.slice(-2)/30.1)]||"Brulee"

JavaScript (ES6), 171 bytes

(x,y=Math.ceil(x.split(/\D/).reduce((a,b)=>(+a)*60+(+b))/30))=>["Bread","Bread","Warm Bread","Toasty","Toasty","Burnt","Burnt","Burnt","Brulee","Brulee","Brulee"][y>8?8:y]

Run some test cases with this Stack Snippet:

var f=(x,y=Math.ceil(x.split(/\D/).reduce((a,b)=>(+a)*60+(+b))/30))=>["Bread","Bread","Warm Bread","Toasty","Toasty","Burnt","Burnt","Burnt","Brulee","Brulee","Brulee"][y>8?8:y]

var result = document.getElementById("result");
["0:00", "0:30", "0:31", "1:00", "1:01", "2:00", "2:01", "2:30", "2:31", "3:00", "3:01", "3:30", "3:31", "4:00", "4:01", "4:30", "4:31", "5:00", "6:00"].forEach(x => result.innerHTML += `${x}: ${f(x)}\n`);
<pre id="result"></pre>

  • \$\begingroup\$ @JoKing Whoops, I missed a few possibilities while trying to save bytes. Working on a fix. \$\endgroup\$ – Mego Nov 4 '18 at 5:26

F#, 177 bytes

let t i=
 let s=i.ToString().Split(char 58)
 let m=int s.[0]*60+int s.[1]
 if m<31 then"Bread"elif m<61 then"Warm Bread"elif m<121 then"Toasty"elif m<211 then"Burnt"else"Brulee"

Try it online!

Thanks to Jo King for straightening out my, umm, needlessly literal interpretation of the challenge...

F# is fairly okay for functions without semi-colons or colons. The only real issue was that I couldn't do i.Split directly without a type annotation - F# would not have been able to deduce the type of i based on the method call. That would have required defining the type directly in the function, like let t (i:string)= which would have been against the rules.

But I could easily get by it by i.ToString(), which then allowed me to call Split on it. Then char 58 is a colon character, and after that it's straight-forward.

  • \$\begingroup\$ But that's what the requirements specification said! :P \$\endgroup\$ – Ciaran_McCarthy Nov 18 '18 at 1:31

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.