# One Bad Ternary Operator Deserves Another

Today's Daily WTF quotes the following line of code...

FailSafe==0?'No technical alarms':((FailSafe&1)!=0&&(FailSafe&2)!=0&&(FailSafe&4)!=0&&(FailSafe&8)!=0?'Detection zones staying in a given state; Bad visibility;
Initialization; Bad configuration':((FailSafe&1)!=0&&(FailSafe&2)!=0&&(FailSafe&4)!=0?'Detection zones staying in a given state; Bad visibility; Initialization':
zones staying in a given state; Initialization':((FailSafe&1)!=0&&(FailSafe&8)!=0?'Detection zones staying in a given state; Bad configuration':((FailSafe&2)!=0&&
configuration':'Unknown')))))))))))))))


Write some code that takes an integer value named FailSafe and returns the same string that the above code would produce from the same integer value.

• The challenge is to rewrite that line, so "boilerplate" code is free, including any code that loads an integer value and outputs the string. Only the code that performs the above transformation from an integer to a string counts.
• You may use a different name to "FailSafe" if you wish, as long as your chosen identifier has the same golf score.
• No calling external resources to perform the lookup.
• Normal code-golf rules apply.
• Are we allowed to store FailSafe in another variable (for example, f=FailSafe or something like that)? – ProgramFOX Jul 8 '14 at 10:52
• @ProgramFOX That's fine, but that assignment is included in the count. Only the boilerplate that leads you the point where there's a variable named FailSafe is free. – billpg Jul 8 '14 at 10:54
• Could you please pretty-print the code for us? Or is the challenge to understand the challenge? – John Dvorak Jul 8 '14 at 10:56
• @JanDvorak I'm not sure I can... – billpg Jul 8 '14 at 11:14
• I hope this: pastebin.com/jzXt4fsp is nicer to read – eithed Jul 8 '14 at 11:22

### Ruby, 210 characters

Similar to @Jan Dvorak's solution but a bit more functional and a bit shorter.

f=FailSafe
e[0]||="Unknown"
e.join"; "


### GolfScript, 167 characters

FailSafe.15&["Unknown"][""]"Bad configuration
Initialization
Detection zones staying in a given state"
n/{{n+1$+}+%}/1>+=n%"; "*"No technical alarms"if  The code assumes the value in variable FailSafe and pushes the result on the stack (i.e. output the string if run as standalone program). You can test the code online. The code basically generates an array of all 16 possible outcomes, selects the error message depending on the four lowest bits of FailSafe. The outermost if then handles the zero case. • I think or instead of if would save you the .. But I admit that I haven't tried to decipher the original code. – Peter Taylor Jul 8 '14 at 15:13 ## Rebol/Red: 208 chars I'm not as interested in golfing this as in agreeing that nested ternary operators are annoying...and mentioning this is actually a nice instance for Rebol/Red's CASE. It's related to SWITCH and really helps flatten things like this out: f: FailSafe append case [ 0 < f and 1 ["Detection zones staying in a given state"] 1 < f and 2 ["Bad visibility"] 3 < f and 4 ["Initialization"] 7 < f and 8 ["Bad configuration"] f > 0 ["Unknown"] true ["No technical alarms"] ] "; "  There's a variant called CASE/ALL that will actually run all the conditions, but the default just stops after the first true one. I'll "golf" it a little to 208: x: func[y][y < (f: FailSafe) and ++ y]append case[x 0["Detection zones staying in a given state"]x 1["Bad visibility"]x 3["Initialization"]y 7["Bad configuration"]f > 0["Unknown"]1["No technical alarms"]]"; " ## APL (172) 2↓⊃,/'; '∘,¨{⍵=0:⊂'No technical alarms'⋄0=16|⍵:⊂'Unknown'⋄'Detection zones staying in a given state' 'Bad visibility' 'Initialization' 'Bad configuration'/⍨⌽⍵⊤⍨4/2}FailSafe  Explanation: • {...}FailSafe: generate the strings • ⍵=0:⊂'No technical alarms': the 0 case • 0=16|⍵:⊂'Unknown': the Unknown case (FailSafe is not 0 but the first four bits are) • 'Detection zones staying in a given state' 'Bad visibility' 'Initialization' 'Bad configuration'/⍨⌽⍵⊤⍨4/2: get the lowest 4 bits in the argument (⍵⊤⍨4/2), reverse (⌽), and select the strings for the bits that are on (/⍨). • '; '∘,¨: add '; ' to the front of each returned string, • ⊃,/: join all the strings together, • 2↓: and remove the first two characters (because there's an extra '; ' at the front.) • Save two bytes by changing ⊃,/ to ∊. – Adám May 29 '17 at 11:46 ## Ruby, 183 characters [(f=FailSafe)<1?"No technical alarms":f&15<1?:Unknown:["Detection zones staying in a given state"*f[0],"Bad visibility"*f[1],"Initialization"*f[2],"Bad configuration"*f[3]]-[""]]*"; "  Yet another Ruby solution, but a bit shorter than the others. This is a single expression that uses the constant FailSafe (in Ruby, all uppercase identifiers are constants) to create the output string. • in ruby you should declare constant (like FailSafe) before using. And you code raise uninitialized constant FailSafe – user13426 Jul 8 '14 at 18:40 • @Зелёный As the question states: "Write some code that takes an integer value named FailSafe" - so my code (like all other answers here) assumes FailSafe is already defined. When you want to run the code, you'll have to define the constant yourself first. – Ventero Jul 8 '14 at 19:04 ## JavaScript, 197195 characters FailSafe?['Detection zones staying in a given state','Bad visibility','Initialization','Bad configuration'].filter(function(_,i){return FailSafe&1<<i}).join('; ')||'Unknown':'No technical alarms'  formatted: FailSafe ? [ 'Detection zones staying in a given state', 'Bad visibility', 'Initialization', 'Bad configuration' ].filter(function(_, i) { return FailSafe & 1<<i; }).join('; ') || 'Unknown' : 'No technical alarms';  Could be further reduced by using ES6 or Coffeescript function expressions. • what if FailSafe is 18? (actually, the original challenge code does only look at the lower 4 bits, so the Unknown case is actually never detected!) So the question is, if we should actually care for it or provide a "fixed" algorithm. – blabla999 Jul 9 '14 at 13:18 • @blabla999: It will return "Bad visibility" because the 2-bit is set and none of the other lower 4 bits. The Unknown case happens when none of the lower 4 bits is set, but FailSafe is != 0 - just as in the original code(try with 16). Whether we should "fix" this you should ask the OP (in a comment on the question), not me… – Bergi Jul 9 '14 at 13:24 • you'r right - me stupid. I got so confused by that piece of code. Sorry for that. – blabla999 Jul 9 '14 at 20:53 # Ruby, 213 characters f=failSafe e=f&1>0?["Detection zones staying in a given state"]:[] e+=["Bad visibility"]if f&2>1 e+=["Initialization"]if f&4>3 e+=["Bad configuration"]if f&8>7 e[0]||=f>0?"Unknown":"No technical alarms" e.join"; "  This will work just fine wrapped in a function body (def transform failSafe; ...; end). It can also be used as a single expression (wrap in parentheses because a semicolon/newline has the lowest priority) or as a sequence of statements with the last expression (e.join"; ") used within an expression. • I'll add a rule to allow a different name. – billpg Jul 8 '14 at 13:05 • e+=["Initialization"]if f&4>3 I want this in Python. – ɐɔıʇǝɥʇuʎs Jul 8 '14 at 14:04 • @ɐɔıʇǝɥʇuʎs are you not impressed by []||=? – John Dvorak Jul 8 '14 at 14:34 • Not sure what it does... Also: since FailSafe must be a constant in Ruby Huh. Python's attitude is more like "Yeah, you can break stuff, but don't expect me to clean up the mess" – ɐɔıʇǝɥʇuʎs Jul 8 '14 at 14:43 • @ɐɔıʇǝɥʇuʎs ||= is like += but with || - a ||= b is equivalent to a = a || b. It is commonly used to default a variable when it is falsy. – Aaron Dufour Jul 8 '14 at 15:04 # VBScript, 204 234 232 characters (edit: improved score by 2 by using array() instead of split(). 232 now.) f=failsafe:for b=0to 3:s=s&split(",; Detection zones staying in a given state,; Bad visibility,,; Initialization,,,,; Bad configuration",",")(f and 2^b):next:array("No technical alarms","Unknown",mid(s,3))(2+(f=0)+(len(s)=0))  (edit: forgot the "unknown" part. 234 chars now.) f=failsafe:for b=0to 3:s=s&split(",; Detection zones staying in a given state,; Bad visibility,,; Initialization,,,,; Bad configuration",",")(f and 2^b):next:split("No technical alarms,Unknown,"&mid(s,3),",")(2+(f=0)+(len(s)=0)) (original, 230) for b=0to 3:s=s&split(",; Detection zones staying in a given state,; Bad visibility,,; Initialization,,,,; Bad configuration",",")(FailSafe and 2^b):next:array(mid(s,3),"No technical alarms")(-(len(s)=0)) Of course, this is just part of a script. to test it, try something like this: FailSafe=cint(inputbox("Please enter Failsafe as an integer")) f=failsafe:for b=0to 3:s=s&split(",; Detection zones staying in a given state,; Bad visibility,,; Initialization,,,,; Bad configuration",",")(f and 2^b):next msgbox array("No technical alarms","Unknown",mid(s,3))(2+(f=0)+(len(s)=0))  • me too forgot the Unknown case ;-) – blabla999 Jul 9 '14 at 11:38 • @blabla999 Indeed. Fixed. Thanks! – JesterBLUE Jul 9 '14 at 12:41 ## Smalltalk, 243 characters FailSave>15ifTrue:'Unknown'ifFalse:[((((1to:4)select:[:b|FailSafe isBitSet:b])collect:[:b|#('Detection zones staying in a given state' 'Bad visibility' 'Initialization' 'Bad configuration')at:b])asStringWith:'; ')ifEmpty:'No technical alarms']  formatted for readability: FailSafe > 15 ifTrue:'Unknown' ifFalse:[ ((((1 to:4) select:[:b | FailSafe isBitSet:b ]) collect:[:b| #( 'Detection zones staying in a given state' 'Bad visibility' 'Initialization' 'Bad configuration') at:b ] ) asStringWith:'; ') ifEmpty:'No technical alarms']  Thanks to Bergi, for pointing to the bug in the first version. This brings up an idea: if I map the FailSafe value into a 6-bit mask, (mapping 0 -> 16 and greater-than-15 -> 32), I can get rid of the final tests. The mapping to the 6bit mask m can be done with: m := {16},(1 to: 15) at:FailSafe+1 ifAbsent:32. that is, m will be 16 for a zero FailSafe, and 32 for out-of-bounds values. Then select and collect strings as above. This gives the new code: m := {16},(1 to:15) at:FailSafe+1 ifAbsent:32. (((1 to:6) select:[:b | m isBitSet:b ]) collect:[:b| #( 'Detection zones staying in a given state' 'Bad visibility' 'Initialization' 'Bad configuration' 'No technical alarms' 'Unknown') at:b ] ) joinWithAll:'; '  (I also replaced asStringWith: by joinWithAll:, which is an alias). Although this seems to be a nice idea, this has the same character count - sigh. Maybe some other programming language with denser operator names scores better here! I could save a few chars by not using a temporary variable for m, but recompute it in the loop and by not using a literal array for the string vector, to get a count slighty below 240 chars. Finally, the mask m could also be computed by m:={32},(1 to: 16) at:(FailSafe+1 min:17), which might be shorter in APL. Then exchange the last two strings in the vector. PS: The first version assumes FailSafe is non-negative, like some other solutions here do. The second can deal with anything, even nil or other non-numbers. • What about the Unknown configuration? – Bergi Jul 8 '14 at 18:10 • ouch sorry - I have to fix it. – blabla999 Jul 9 '14 at 10:31 ## CoffeeScript, 161 160 221 chars F = FailSafe;F<16 and (F and [0..3].filter((i)->(1<<i)&F).map((i)->(['Detection zones staying in a given state','Bad visibility','Initialization','Bad configuration'])[i]).join('; ') or 'No technical alarms') or 'Unknown'  • What happened to Unknown and No technical alarms? – Bergi Jul 8 '14 at 18:09 • Aw crap. I should have been suspicious when I beat the GolfScript answer... – Ryan Kennedy Jul 8 '14 at 18:11 • As always, I forgot the edge cases... – Ryan Kennedy Jul 8 '14 at 18:16 VB.net Function StateText(f As FailFlag) As String If f=0 Then Return "No Technical Alarm" Dim t="" If f.HasFlag(f1) Then t &= "Detection zones staying in a given state; " If f.HasFlag(f2) Then t &= "Bad visibility; " If f.HasFlag(f4) Then t &= "Initialization; " If f.HasFlag(f8) Then t &= "Bad configuration; " Return If( t<>"", t.TrimEnd("; "),"Unknown") End Function <Flags> Enum FailFlag f1 = 1 f2 = 2 f4 = 4 f8 = 8 End Enum  Edit: Better Entry Function StateText(f As FailFlag) As String If f = 0 Then Return "No Technical Alarm" Dim t = String.Join("; ", From e In [Enum].GetValues(GetType(FailFlag)) Where f.HasFlag(e) Select [Enum].GetName(GetType(FailFlag), e).Replace("_", " ")) Return If( t<>"", t,"Unknown") End Function <Flags> Enum FailFlag Detection_zones_staying_in_a_given_state = 1 Bad_visibility = 2 Initialization = 4 Bad_configuration = 8 End Enum  ## Perl, 208 197 Characters $f=$FailSafe;%m=(1,'Detection zones staying in a given state',2,'Bad visibility',4,'Initialization',8,'Bad configuration');($f?join'; ',@m{map{$f&$_?$_:()}1,2,4,8}:'No technical alarms')||'Unknown'  With boilerplate code to make it work: #!/usr/bin/env perl$FailSafe=17;
print failmsg() . "\n";

sub failmsg {
$f=$FailSafe;%m=(1,'Detection zones staying in a given state',2,'Bad visibility',4,'Initialization',8,'Bad configuration');($f?join'; ',@m{map{$f&$_?$_:()}1,2,4,8}:'No technical alarms')||'Unknown'
}

• Reread the code: There isn't a bounds check. – titanofold Jul 9 '14 at 12:48

Java 275 characters (not counting unnecessary white space)

    String s = "";
int b = 1;
for (String m : new String[]{"Detection zones staying in a given state; ","Bad visibility; ", "Initialization; ", "Bad configuration; "}) {
if ((FailSafe & b) != 0) s = s + m;
b <<= 1;
}
return (s.length() == 0) ? (FailSafe == 0) ? "No technical alarms" : "Unknown" : s.substring(0, s.length() - 2);
`