# Ternary-if Converter

In Java/.NET/C/JavaScript/etc. you can use ternary-ifs to shorten if-statements.

For example (in Java):

// there is a String s and an int i
if(i<0)s="Neg";else if(i>0)s="Pos";else s="Neut";


Can be shortened with a ternary-if to:

s=i<0?"Neg":i>0?"Pos":"Neut";


## Challenge:

Input: A regular if-else (possible with nesting) that sets a single variable.

Output: The converted ternary-if.

## Challenge rules:

• You can assume all if-else cases are possible without brackets (so each if/else-if/else block has a single body).
• You can assume there won't be any spaces, tabs, or new-lines, except for a single space after each else (including at else if).
• You can assume the variable names used are always a single lowercase letter ([a-z]).
• The values given to the variables can be one of:
• Strings (without spaces/tabs/new-lines), which will be surrounded by double-quotes (i.e. "Test", "SomeString", "Example_string", etc.). You can assume the strings will never contain the substrings if or else, nor will it contain spaces, tabs, newlines, (escaped) double-quotes, or the character =. It can contain the characters ><(){}[];?:!&|, but will be in the printable ASCII range only (['!' (33), '~' (126)]).
• Integers (i.e. 0, 123, -55, etc.)
• Decimals (i.e. 0.0, 0.123, -55.55, etc.)
• The values won't ever be mixed. So all variables assigned are integers, and not some are integers and some are strings.
• The conditions within parenthesis can contain the following characters =<>!+-/*%&|[], a-z, 0-9. You can assume there won't be any inner parenthesis, and you can also assume there won't be any (confusing) fields of more than one character used (like if(if<0)).
• You can assume there won't be any short-cuts like i*=10 instead of i=i*10.
• You won't have to handle dangling else cases, so all if can be paired up with an else. I.e. if(a)if(b)r=0;else r=1; isn't a possible input-case. if(a)if(b)r=0;else r=1;else r=2; or if(a&&b)r=0;else if(a&&!b)r=1;else r=-1; are however.
• I/O is flexible. Input and Output can be a string, list of characters, read from STDIN, output to STDOUT, etc. Your call.
• All ternaries will have a right associativity, as is the standard in most languages (but not in for example PHP).

## General rules:

• This is , so shortest answer in bytes wins.
Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
• Standard rules apply for your answer, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters and return-type, full programs. Your call.
• Default Loopholes are forbidden.

## Test cases:

Input:   if(i<0)s="Neg";else if(i>0)s="Pos";else s="Neut";
Output:  s=i<0?"Neg":i>0?"Pos":"Neut";

Input:   if(i%2<1)r=10;else r=20;
Output:  r=i%2<1?10:20;

Input:   if(n<10)if(m<0)i=0;else i=10;else if(m<0)i=-1;else i=1;
Output:  i=n<10?m<0?0:10:m<0?-1:1;

Input:   if(i==1)i=0.0;else i=0.25;
Output:  i=i==1?0.0:0.25;

Input:   if(!a)if(b)r=0;else r=1;else r=2;
Output:  r=!a?b?0:1:2;

Input:   if(a)if(b)r=0;else r=1;else if(c)r=2;else r=3;
Output:  r=a?b?0:1:c?2:3;

Input:   if(a&&b)r=0;else if(a&&!b)r=1;else r=-1;
Output:  r=a&&b?0:a&&!b?1:-1;

Input:   if(i[0]>0)if(j>0)if(q>0)r="q";else r="j";else r="i";else r="other";
Output:  r=i[0]>0?j>0?q>0?"q":"j":"i":"other";

Input:   if(i>0)r="i";else if(j>0)r="j";else if(q>0)r="q";else r="other";
Output:  r=i>0?"i":j>0?"j":q>0?"q":"other";

Input:   if(a>0)if(a<2)x="one";else if(a<3)x="two";else if(a<4)x="three";else x="other";else x="other";
Output:  x=a>0?a<2?"one":a<3?"two":a<4?"three":"other":"other";

Input:   if(b[0]<=b[1])q=5;else if(b[0]==null)q=0;else q=-10;
Output:  q=b[0]<=b[1]?5:b[0]==null?0:-10;

• Technically, in F# if ... then ... else is the ternary operator. So if you write let result = if 10 > 100 then 99 else -99 then the value of result would be -99. – Ciaran_McCarthy Oct 9 '18 at 15:27
• @Ciaran_McCarthy I would expect that to be the case for most, if not all functional leaning languages that have conditional expressions as the default. Clojure, Scala, and Haskell are the same. – Carcigenicate Oct 9 '18 at 16:51
• @tsh Oops.. I shouldn't add test cases late in the evening after a day of work.. Fixed. – Kevin Cruijssen Oct 10 '18 at 8:30
• JavaScript Compressor Closure Compiler works great on all these testcases. Which when taking the given inputs would just generate the expected outputs. But it seems that I cannot claim it as an answer. So I would like to comment here. – tsh Oct 10 '18 at 9:37

# Retina 0.8.2, 32 bytes

+rif.(.*?)\)(.=)
$2$1?
;.{6}=
:


Try it online! Explanation:

rif.(.*?)\)(.=)
$2$1?


Handle an if immediately before an assignment by moving the assignment before the condition and appending a ?. The stage is matched right-to-left to ensure we get the if closest to the assignment, while the \) ensures that we don't match else by mistake.

+


Repeat the stage to take care of nested ifs.

;.{6}=
:


Any remaining assignments are elses so replace the ;else ?= with a :.

• @nwellnhof Thanks for pointing that out; I thought I was golfing a byte off there because it worked on the test cases. – Neil Oct 9 '18 at 22:44

# Python 2, 126121120114 100 bytes

lambda s:findall(' (.=)',s)[0]+sub('if.(.*?)\)(.=)?',r'\1?',sub('.{5} (.=)?',':',s))
from re import*


Try it online!

Saved:

• -1 byte, thanks to Kevin Cruijssen
• @KevinCruijssen Thanks :) – TFeld Oct 9 '18 at 11:22
• Why is the function definition before the import? – Skyler Oct 9 '18 at 17:51
• @Skyler It doesn't actually matter, but it's easier to put the assignment in the header this way – Jo King Oct 9 '18 at 21:51

# Perl 5 -p, 5049 48 bytes

s/if.(.*?)\)(.=)/\2\1?/g;s/.if./?/g;s/;.{6}=/:/g


Try it online!

The 48 byte version is inspired by Neil's Retina answer.

### Explanation

# Replace "if(e1)if(e2)x=" with "x=e1)if(e2?"
s/if.(.*?)\)(.=)/\2\1?/g;
# Replace ")if(" with "?"
s/.if./?/g;
# Replace ";else x=" with ":"
s/;.{6}=/:/g


s/.{5} (.=)?/:/g;s/if.(.*?)\)(.=)?/\1?/g;$_=$2.$_  # Ruby, 72 71 bytes ->s{$a=$2while s.gsub!(/if.(.*?)\)(.=)?(.*?);\w* (.=)?/,'\1?\3:');$a+s}


Try it online!

• Either ;else or else  can be .{5} to save a byte. – Kevin Cruijssen Oct 9 '18 at 12:58
• Thanks, I found something different with the same effect. – G B Oct 9 '18 at 13:03

# Java (JDK), 119 116 bytes

Almost entirely pure regex solution, chopped and changed a bit from a couple of the other answers.

-3 bytes thanks to some more regex trickery from Kevin

s->s.replaceAll(".*(.=).*","$1$0").replaceAll("if.(.*?)\\)","$1?").replaceAll("([ ?]).=","$1").replace(";else ",":")


Try it online!

Explanation

s->                                         // Lambda function taking a String
s.replaceAll(".*(.=).*","$1$0")          // Find assigned variable and append to start of String
.replaceAll("if.(.*?)\\)","$1?") // Replace any 'if' statements with their condition // followed by '?' .replaceAll("([? ]).=","$1")            // Remove all assignments after a '?' or space
.replace(";else ",":");                 // Simple replace (no regex) to remove 'else' statements

• I like the ".*(.=).*","$1$0" you've used, it's 1 byte shorter than the "^(.*)(.=)","$2$1" I had in mind. :) Anyway, you can save 2 bytes changing if\$$ to if. and an additional byte changing (\\?| ) to ([? ]). Try it online 116 bytes. – Kevin Cruijssen Oct 9 '18 at 18:47 • @KevinCruijssen Cheers! I spent so long trying to whittle the regex down, I can't believe I missed that! – Luke Stevens Oct 9 '18 at 19:59 # Kakoune v2018.09.04, 4338 37 bytes xs\w=(?!=)<ret>d<a-h>Psif.<ret>df);r?xs;else<space><ret>c:<esc>  Explanation: Kakoune is a multiple selection based, modal editor, inspired by Vim. 1. x select the whole line 2. s ... <ret> filter the selection with the regular expression \w=(?!=), which matches all variable assignments, and doesn't match == comparisons 3. d delete each selection and put its contents in the default register 4. <a-h> extend all selections to the beginning of their line 5. P paste the content of the default register before each selection 6. s ... <ret> filter the selection with the regular expression if. 7. d delete each selection 8. f extend each selection forward to the next ) 9. ; reduce each selection to its cursor 10. r replace each character of each selection with ? 11. x select the whole line 12. s ... <ret> filter the selection with ;else<space> 13. c ... <esc> clear each selection and replace it with : ### animation of the code on a test case: • Hmm, I've never heard of Kakoune before. I guess there isn't any online compiler for it? If not, could you perhaps add some screenshots of some of the test cases so I can verify it works as intended? Also, if this is your language, you could contact Dennis in the talk.tryitonline.net chat to ask if he could add it to TIO. – Kevin Cruijssen Oct 9 '18 at 15:57 • @KevinCruijssen I added a gif of one of the test cases. It works on all of them, but making the gifs isn't trivial. – Vaelus Oct 9 '18 at 17:45 • Thanks for the explanation and gif, +1 from me. :) Always nice to learn about a new language. – Kevin Cruijssen Oct 9 '18 at 18:39 # Clean, 386375216196 189 bytes Look ma, no regex! import StdEnv,Data.List ?[_,'=':b]= b ?b= b ['if(':s]#(h,[_:t])=span((<>)')')s =h++['?': ?t] [';else ':s]=[':': ?s] [a:b]|b>[]=[a: b]=b @s=hd[[v,e: s]\\['else ',v,e=:'=':_]<-tails s]  Try it online! # JavaScript (Node.js), 80 bytes s=>(p=s.replace(/(?:if.(.*?)$$|;.*? )(.=)?/g,(_,t,v)=>(V=v||V,t)?t+'?':':'),V+p)


Try it online!

Thanks to Kevin Cruijssen, 2 bytes saved.

• if\( can be if. and ;else  can be ;.{5} to save 2 bytes – Kevin Cruijssen Oct 10 '18 at 7:34