20
\$\begingroup\$

Given an expression matching the regex /^[-~]*x$/, evaluate it in terms of x and output a string matching the regex /^-?x[+-]\d+$/.

For example, the string -~x evaluates to x+1, while the string -~-x evaluates to -x+1, and the string -~-~--x evaluates to x+2.

We start from x and evaluate the string right to left. - negates the term, while ~ converts y to -y-1.

Testcases:

    x  x+0
   ~x -x-1
  -~x  x+1
 ~-~x -x-2
-~-~x  x+2
--~~x  x+0
  ~-x  x-1
 -~-x -x+1

This is . Shortest answer in bytes wins.

The input/output format is strict. The "x" is mandatory.

\$\endgroup\$
12
  • \$\begingroup\$ Can we output x+010 instead of x+10 for -~-~-~-~-~-~-~-~-~-~x? It matches the second regex. \$\endgroup\$
    – user72349
    Commented Sep 15, 2017 at 18:34
  • \$\begingroup\$ You can, though I see no reason why. \$\endgroup\$
    – Leaky Nun
    Commented Sep 15, 2017 at 18:36
  • 3
    \$\begingroup\$ The tilde has different meaning in different languages. You should probably clarify that you intend the Python meaning \$\endgroup\$
    – Luis Mendo
    Commented Sep 15, 2017 at 19:10
  • 3
    \$\begingroup\$ @LuisMendo read the last sentence of my third paragraph \$\endgroup\$
    – Leaky Nun
    Commented Sep 15, 2017 at 19:15
  • 1
    \$\begingroup\$ @LeakyNun Ah, sorry, I didn't see that. Anyway, I think it should appear earlier on. The first two paragraphs and part of the third talk about ~ while it hasn't been defined \$\endgroup\$
    – Luis Mendo
    Commented Sep 15, 2017 at 20:47

10 Answers 10

12
\$\begingroup\$

Python 2, 42 41 39 bytes

lambda s,x=0:'-x%+d'[len(s)%2:]%eval(s)

Try it online!

\$\endgroup\$
0
7
\$\begingroup\$

Retina, 47 44 bytes

+`--|~~

((~)|-)*x
$&+$#2
T`+`-`^~.*
~
-
--

Try it online! Edit: Saved 3 bytes thanks to @MartinEnder. Expanation:

+`--|~~

Delete pairs of adjacent duplicates.

((~)|-)*x
$&+$#2

Count the number of ~s which gives us the magnitude of the term.

T`+`-`^~.*

If the first character is a ~ then the term should be negative.

~
-
--

If the number of ~s and -s is odd then the x should be negative.

\$\endgroup\$
0
6
\$\begingroup\$

JavaScript, 59 bytes

x=>['-'[x.length&1]]+'x'+['+'[(x=eval(x.join` `))<0^0]]+~~x

Try it online!

\$\endgroup\$
5
  • 2
    \$\begingroup\$ Beat me by 16 secs and 38 bytes. Well done. \$\endgroup\$
    – Luke
    Commented Sep 15, 2017 at 18:53
  • \$\begingroup\$ Fails for test cases containing multiple - in a row. (i.e. --~-~x) \$\endgroup\$
    – Luke
    Commented Sep 15, 2017 at 18:59
  • \$\begingroup\$ @Luke. I'm not sure what do you mean. My script works for these test cases too. \$\endgroup\$
    – user72349
    Commented Sep 15, 2017 at 19:02
  • \$\begingroup\$ This survives my new testcase :D \$\endgroup\$
    – Leaky Nun
    Commented Sep 15, 2017 at 19:22
  • \$\begingroup\$ @ThePirateBay: oops, nvm then... \$\endgroup\$
    – Luke
    Commented Sep 15, 2017 at 19:27
2
\$\begingroup\$

PowerShell Core, 102 bytes

$s=-1
switch -r($args[$args.Count..0]){.{$a=-$a;$s=-$s}~{$a--}}"$s`x+$a"|% *ce '+-','-'|% *ce '1x','x'

Try it online!

Passes an expression as a string using splatting
Then processes it from right to left
For each char, negate $s and $a, and if the char is ~ , decrement $a
Then concatenate them all: $s + "x+" + $a
Replace +- with -
Remove the useless 1 before x

\$\endgroup\$
1
\$\begingroup\$

Perl 5, 75 + 1 (-n)= 76 bytes

map{$y=-$y;$y--if/~/}reverse/-|~/g;printf"%sx%+d",((-1)**y/-~//)=~s/1//r,$y

Try it online!

\$\endgroup\$
1
\$\begingroup\$

C (gcc), 69 bytes

a;s;f(char*p){for(a=s=0;*p;a-=*p++%5*~-s)s^=2;printf("-x%+d"+!!s,a);}

Try it online!

-1 byte thanks to @ThePirateBay

\$\endgroup\$
0
1
\$\begingroup\$

Ruby, 36 bytes

Port of user48543‘s Python answer.

->s{x=0
"-x%+d"[s.size%2..]%eval(s)}

Attempt This Online!

\$\endgroup\$
1
\$\begingroup\$

><> (Fish), 91 79 bytes

Was producing incorrect output, but for a change fixing this actually saved me bytes.

10>i:'-'=?v:'~'=?vv
 .\r*-10r~<1-@:$~/~
d3/"+"on; .3dv?(0r/
;n^?)-10:o"x"\"-"o/

Try this

enter image description here

enter image description here

Significantly harder to parse in reverse order. Basically produce a expression of the form ax + b

  • For a -, set a to -a.
  • For a ~, set b to b-a, then re-use the same code to set a to -a.

Rest of the code is printing the solution. Special cases for printing the - in front of x and needing a + if the extra number is not negative.

\$\endgroup\$
0
\$\begingroup\$

05AB1E (legacy), 20 bytes

á0:.E…-x+ì„+-¤:IgÉi¦

Port of (deleted) user48543's Python answer.

Try it online or verify all test cases.

Explanation:

á      # Only keep the letters of the (implicit) input (the "x")
 0:    # Replace the "x" in the (implicit) input with "0"
   .E  # Evaluate and execute it as Python code
…-x+ì  # Prepend string "-x+"
„+-¤:  # Replace a potential "+-" with "-"
IgÉi   # If the length of the original input is odd:
    ¦  #  Remove the leading "-"
       # (after which the result is output implicitly)
\$\endgroup\$
0
\$\begingroup\$

Java 8, 186 168 167 bytes

s->{s=s.replaceAll("--|~~","");int l,i=s.length()-(l=(s=s.replace("-~","")).length())>>1;return(l-(s=s.replace("~","")).length()>0?"-"+s+~i:s+"+"+i).replace("--","");}

Definitely room for improvements..

-1 byte thanks to @ceilingcat replacing (a-b)/2 with a-b>>1.

Try it online.

Explanation:

s->{                            // Method with String as both parameter and return-type
  s=s.replaceAll("--|~~","");   //  Remove all "--" and "~~"
  int l,                        //  Temp integer to reduce bytes
      i=s.length()-(l=(s=s.replaceAll("-~","")).length())>>1;
                                //  Remove all "-~" and save count in `i`
  return(l-(s=s.replaceAll("~","")).length()
                                //  Remove all remaining "~"
         >0?                    //  and if its non-empty:
           "-"                  //   Start with a minus sign
           +s                   //   followed by the remaining `s`
           +~i                  //   followed by `-i-1`
          :                     //  Else:
           s                    //   Start with the remaining `s`
           +"+"                 //   followed by a plus sign
           +i                   //   followed by `i`
         ).replaceAll("--","");}//  And then remove all "--"
\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.