# Toasty, Burnt, Brûlée!

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
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

• Is the time at most 59:59?
– xnor
Nov 3, 2018 at 2:47
• Shouldn't it be 3:31 and up: Brulee?
– user45941
Nov 3, 2018 at 4:17
• Where are all the golfing languages where colons wouldn't be used anyway?
– Jo King
Nov 3, 2018 at 6:13
• I have't realized until now why there aren't any Python submissions... Nov 3, 2018 at 13:43
• Can we take in input with a leading zero so that all inputs are 5 characters long? Nov 3, 2018 at 16:58

# Python 2, 124 118 116

t=eval(input().replace("\x3A","."))


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.

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

# T-SQL, 409379328 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.

Ungolfed:

-- 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

SELECT CASE
WHEN @ < 1 AND @x < 31              -- 0:00 - 0:30
WHEN @ < 1 OR @ = 1 AND @x = 0      -- 0:31 - 1:00
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
END

-- 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

• 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. Nov 8, 2018 at 22:48
• Interesting language for golfing! Nov 9, 2018 at 2:17
• @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. Nov 9, 2018 at 14:15
• 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)=... Nov 9, 2018 at 14:31
• 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. Nov 9, 2018 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

## Ungolfed

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


## Acknowledgments

• .replaceAll can be .replace and Integer.parseInt can be new Integer, or new Short even, to save 10 bytes: Try it online 162 bytes. Nov 19, 2018 at 10:18
• 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. Nov 19, 2018 at 11:22
• Nice. Thanks guys! Nov 21, 2018 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!

<?=[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 SELECT TOP 1b FROM i, (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 þ30тx330)ć‹O„©Ãº™D#θ‚R.•liSÕô6>Āµ·•6ôÀ«™sè  Explanation: þ # 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 • I used a regex to enforce the 59:59 & no negatives rule :-) Nov 3, 2018 at 4:14 • OH WAIT I forgot i added : Nov 3, 2018 at 4:15 • actually done :-) Nov 3, 2018 at 4:21 • 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. Nov 3, 2018 at 13:40 # Retina 0.8.2, 97 bytes .+(..)$*1#$1$*
+1#
#60$* #1{211,} Brulee #1{121,} Burnt #1{61,} Toasty #1{31,} Warm # #1* Bread  Try it online! Link includes test cases. Explantion: .+(..)$*1#$1$*


Convert the minutes and seconds to unary.

+1#
#60$*  Multiply the minutes by 60 and add to the seconds. #1{211,} Brulee #1{121,} Burnt #1{61,} Toasty  Decode the seconds into the toastiness. #1{31,} Warm #  Decode Warm Bread by noting that # (for 0:00) decodes to Bread. #1* 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 if<(t)<[31 say[Bread else if<(t)<[61 say[Warm Bread else if<(t)<[121 say[Toasty else if<(t)<[211 say[Burnt else say[Brulee  # 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. • Would this work? tio.run/… Nov 8, 2018 at 22:56 • @JayCe IDK, the input is "any acceptable format" but then everything takes the string...I'll ask in the comments. Nov 8, 2018 at 23:06 • @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 Nov 9, 2018 at 2:20 • And you can also do 30*c(0,1,2,4,7,Inf) Nov 9, 2018 at 3:59 • @RedwolfPrograms the input isn't a time, it's an array, : is the sequence operator. Nov 9, 2018 at 15:58 # Japt, 48 bytes BÎ% W‡m BÎ% To†ty B¨› BrÔ‡·g[30LLÑ,330]è<Ur58d  Try it online! Saved 5 bytes by actually reading the tips... Explanation: 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. • 46 if lower case allowed Nov 15, 2018 at 19:31 • 47 if not Nov 15, 2018 at 19:33 • @LuisfelipeDejesusMunoz both of those contain a colon, which isn't allowed by the challenge. LÑ saves a byte though, and I didn't think about whether all lowercase is allowed. Nov 15, 2018 at 20:51 # Jelly, 4341 40 bytes fØD~~ḌH“Ð2dʠ‘<Sị“¡Ḳḋ\ḞvṾƤSİƓƥeF½ÞØ+®°»Ỵ¤  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 \>tt tt,kw,kw,kw,ki \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.

• After reading the name of this language, I for some reason have the image of a wizard chanting ASCII code points stuck in my head. Feb 9, 2019 at 2:16
• @RedwolfPrograms *GRIN* cdn.discordapp.com/attachments/272860530505547776/… Feb 9, 2019 at 2:23

# 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>

• @JoKing Whoops, I missed a few possibilities while trying to save bytes. Working on a fix.
– user45941
Nov 4, 2018 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]

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.