# Type-check an expression

Given an infix expression, determine whether all constants are of the same type.

Operators will consist only of these dyadic operators: +-/*

Your program or function should take a valid expression string as input, and output a truthy value if the constants in the expression are of the same time, and a falsey value otherwise.

The expression will consist solely of constants, and may contain any of the following types:

• String, of the form "String" (Always double quotes, can be empty, no escape characters, may contain any ASCII text)
• Integer, of the form 14 (Always positive or zero)
• Float, of the form 7.3f (Always positive or zero, always has a decimal component, eg 14.0f)
• Byte, of the form 0x42 (0-255, Always 2 hexadecimal characters)
• Boolean, of the form true (true or false, case insensitive)

The expression will not contain parentheses, as order of operation doesn't affect type when no type coercion is present.

A lone constant with no operators is a valid expression.

An empty expression is not a valid expression.

You may assume that the expression string contains no whitespace outside of string literals.
Note: Alternatively you may assume that there will always be spaces between constants and operators, as seen in the testcases. If you make this assumption, please specify as such in your answer

You do not have to handle invalid expressions such as 1 +.

# Scoring

This is , so fewest bytes wins!

# Test cases

2 + 3
True

"Hello" / "World"
True

true * false
True

"Hello" + 4
False

"Hello" + "4"
True

3 + 2.4f / 8
False

0xff * 0xff
True

0xff + 2
False

6
True

" " + ""
True

"4 + false" + "word"
True

• Does "case insensitive" for Boolean values mean that we have to support all cases? Or that we can decide which case to use? – Arnauld Apr 30 '19 at 16:09
• @Arnauld must support all cases – Skidsdev Apr 30 '19 at 16:31
• @JonathanAllan my interpretation was that we had to handle any mixture of cases (e.g. truE+fALSe). If not I can save two bytes in my solution. – Nick Kennedy Apr 30 '19 at 19:50

# JavaScript (ES6),  79 77  75 bytes

Saved 2 bytes thanks to @ExpiredData

Expects whitespace around operators. Returns a Boolean value.

s=>![/".*?"/g,/0x../g,/\S+f/g,/\d/,/e/i].filter(e=>s!=(s=s.split(e)+''))[1]


Try it online!

### How?

1. We remove all strings, using /".*?"/g
2. We remove all bytes, using /0x../g
3. We remove all floats, using /\S+f/g
4. We look for a remaining digit with /\d/; if we do find one, there must be at least one integer
5. We look for a remaining "e" or "E" with /e/i; if we do find one, there must be at least one Boolean value

All removed expressions are actually replaced with a comma, which is harmless.

We filter out the regular expressions causing no change to the input string and test whether less than two of them remain at the end of the process.

• true and false are marked as being case insensitive, I think that means you need to make your regex ignore case when searching for these t and s (I could be wrong though). – Jonathan Allan Apr 30 '19 at 16:03
• @JonathanAllan I've put a temporary fix and asked the OP. – Arnauld Apr 30 '19 at 16:09
• 75 bytes – Expired Data May 1 '19 at 7:57
• @ExpiredData Nice. :) Thanks! – Arnauld May 1 '19 at 8:08

# Jelly, 30 23 bytes

ṣ”"ŒœḢYŒlḲŒœḢeþ@“.e¶x”E


Try it online!

A monadic link that takes a string as input and returns 1 for true and 0 for false (Jelly’s boolean values). Expects whitespace around operators.

I’ve added a few new test cases to the TIO including one with three operators and one with mixed case for booleans.

### Explanation

ṣ”"                     | Split input at double-quotes
Œœ                   | Split into two lists, one of odd indices and one even. The even indices will have the contents of the quoted bits in the input (if any)
Ḣ                  | Keep only the odd-indexed items
Y                 | Join with newlines (so now all quoted strings in input are a single newline)
Œl               | Convert to lower case (so that booleans are case insensitive)
Ḳ              | Split at spaces
ŒœḢ           | As before just take odd indices
eþ@“.e¶x”  | Check for each section which they contain of .e¶x (respectively floats, booleans, strings and hex; integers will have none of these)
E | Check each section is equal (will return true for single section)


# Perl 5-p, 73 bytes

for$f(qw/".*?" \d+.\d+f 0x.. ....?e \d+/){s/$f//gi&&last}$_=/^[+\/* -]*$/


Try it online!

How?

Attempt to remove strings, floats, hex, boolean, and integers, in that order. Stop as soon as something is removed. After stopping, check to see if the remaining string consists only of operators and whitespace. It if does, the trype check is true; if not, it's false.

First attempt: Perl 5 -MList::Util=all -p, 99 bytes

s/".*?"/!/g;for$f(qw/! \d+ \d+\.\d+f 0x[0-9a-f]{2} (true|false)/){$\||=all{/^$f$/i}/[^+\/* -]+/g}}{


Try it online!

• $_=/^[+\/* -]*$/ may be changed by $_=!y#-+/* ##c, and ....?e by .*e – Nahuel Fouilleul May 2 '19 at 9:11 • otherwise in one regex, 63 bytes – Nahuel Fouilleul May 2 '19 at 9:22 • 58 bytes assuming there will always be spaces between constants and operators – Nahuel Fouilleul May 2 '19 at 9:37 # C# (Visual C# Interactive Compiler), 113111 109 bytes n=>@""".*?"" 0x.. \S+f \d e|E".Split().Single(x=>n!=(n=System.Text.RegularExpressions.Regex.Replace(n,x,"")))  Port of Arnauld's javascript answer. Is 72 bytes with the flag /u:System.Text.RegularExpressions.Regex. Try it online! # Japt-!, 36 bytes ".*?" 0x.. %S+f %d e|E¸è@UÀ(U=rXÃÉ  Try it • – Shaggy May 1 '19 at 22:31 # 05AB1E, 50 24 bytes '"¡āÉÏ»lð¡āÉÏε".e x"Så}Ë  -26 bytes by making a port of @NickKennedy's Jelly answer, so make sure to upvote him!! Expects input with spaces at the operands. Explanation: '"¡ '# Split the (implicit) input-string by '"' āÉÏ # Only keep all values at 0-based even indices » # Join them by newlines l # Converted to lowercase (for true/false) ð¡ # Split by spaces (NOTE: # cannot be used here, since inputs without # operands wouldn't be wrapped inside a list) āÉÏ # Keep all values at 0-based even indices again ε".e x"Så} # Check for each item for each of [".","e","\n","x"] if it's in the item Ë # Check if all inner lists are the same # (which is output implicitly as result)  # Python 2, 102 bytes import re def f(s): m=map(eval,re.split('[*+-/]',s)) return all(map(lambda t:type(t)==type(m[0]),m))  Try it online! Not entirely sure how to represent some of these types in Python. For example, 0xff and 2 are both treated as integers. And 2.4f isn't a valid type in Python, I think. Capitalized True and False for testing Booleans. Edit: Grammar • Will fail the last test case – Gymhgy Apr 30 '19 at 16:08 • ...and (as it stands) the true * false one. – Jonathan Allan Apr 30 '19 at 18:46 • It passes for "True * False". I can try to make it work with lower case, but I figured since bools are always capitalized in python it would be sufficient. – GotCubes Apr 30 '19 at 19:12 • Currently this does not fulfill the challenge criteria. Namely: It does not handle booleans case insensitively, it errors on floats, and it incorrectly returns true when given an expression consisting of bytes and integers – Skidsdev May 1 '19 at 13:38 # Stax, 26 bytes ïd"┬Z\¡►L!8$lm╗╕╤☻ú≡╝ò6Å>^


Run and debug it

This program expects spaces around the operators. In general, it works by applying a few transformations to the input such that the maximum character for each expression type is distinct.

Unpacked, ungolfed, and commented, it looks like this.

i           suppress automatic evaluation of input
'"/2::'s*   replace quoted strings with 's'
.\d'9R      replace all digits with '9'
.ez|t       replace 'e' with 'z'
j2::        split on spaces, and discard alternating groups (operators)
{|Mm        calculate the maximum character in each remaining group
:u          resulting array contains exactly one distinct value


Run this one

r(a:t)|a=='"'=a:r(tail$snd$span(/=a)t)|elem a"+-*/"=r t|0<1=a:r t
r n=n
f x|z<-[last$'i':(filter(elemt)"fex\"")|t<-words$r x]=all(==z!!0)z

• f x=let z=...in ... can be f x|z<-...=.... – Jonathan Frech Mar 21 '20 at 15:35

# JavaScript: 69 bytes.

a=>{b=a.split(/\+|\-|\*|\//);return typeof eval(b[0])==typeof eval(b[1])}


## Remarks

• eval is a dangerous operation.
• I used bad JavaScript practices in the process, like implicit globals and auto-semicolons.

## Explanation

• b = ... sets the variable b to the array created by splitting a based on the dyadic operations
• return ... returns true if the types of the return values of eval match, false otherwise.
• Don't worry about good practices here. In our daily jobs we are not doing things seen here. ☺ Your code could be reduced to a=>typeof eval((b=a.split(/\+|\-|\*|\//))[0])==typeof eval(b[1]), but unfortunately its glitches would stay: 1) Integers, floats and hexadecimal will all result “number” while the requirement asks to find them different. 2) Your solution should also handle expressions with fewer or more than 2 constants. – manatwork Feb 2 at 12:21
• On code golf, it would be worrying if you hadn't used bad practices ;) – xigoi Feb 2 at 15:29