Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

This challenge is inspired by Mathematics is fact. Programming is not.


The mathematical notation for a factorial, or a fact is an exclamation mark !. The exclamation mark is also a common symbol for not in many programming languages.

Challenge:

Take a string, containing numerals, and the characters: + ! as input and output the following:

Everything in front of an exclamation mark should be evaluated as a mathematical expression, so 2+2 would be 4.

Everything after a single exclamation mark should be appended as accessories to whatever is in front of it, so: 2+2!5 should give 45, because 2+2=4, and 5 is an accessory. 2+2!5+5 should give 410.

Since ! also means not, anything that's not an accessory after the fact should not be appended. So, 2+2!!5 should give 4, since 5 is not an accessory. Now, not(not(true))==true, so 2+2!!!5 should give 45. 2+2!!5!5+5 should give: 410, because 2+2=4, then followed by a factorial and !5!5+5. The first 5 is not a fact, but 5+5 is after another exclamation mark, and is therefore a fact, yet again.

Clarifications:

  • The exclamation marks will not be adjacent to a + on either side.
  • There will not be leading + for numbers (it's 5, not +5).
  • You may optionally include a leading zero if that's the result of the expression in front of the first !. Both 4 and 04 are accepted output for input: 0+0!4

Executive summary: evaluate each sum (treating ! as separators). Then discard all numbers that appear after an even number of ! (counting from the start of the string). Then remove all !.

Test cases:

!
   <- Empty string

5
5

12!
12

!87
87

!!5
   <- Empty string

5+5!2+2
104

5+5!!2+2
10

1!2!3!4!5!6!7!8!9
12468

10+10!!2+2!!3+3!4+4
208

2!!3!5
25

2!!3!5!7
25

10!!!!!!!5
105

This is so the shortest code in bytes (in each language) wins! Explanations are strongly encouraged!

share|improve this question
    
umm...lets say we have 2!!3!5 here is or is not 5 an accessory of 3? – officialaimm 9 hours ago
3  
@officialaimm It's 25 (see added test case). More importantly 2!!3!5!7 would still give 25, because there's an even number of ! left of the 7 (so you don't just count the run right in front of the number, but all the ! left of it). – Martin Ender 9 hours ago
    
Can the output be a Mathematica Row? – ngenisis 8 hours ago

Retina, 35 31 29 bytes

Saved 4 bytes by taking some inspiration from ETHproductions.

Thanks to Leo for saving another 2 bytes.

\d+|\+
$*
1+
$.&
1`!

!\d*!?

Try it online!

share|improve this answer
    
You can save some bytes in the last lines like this – Leo 5 hours ago
1  
@Leo That's really neat, thank you. :) – Martin Ender 5 hours ago

JavaScript (ES6), 58 56 bytes

Saved two bytes thanks to Martin Ender.

let f =
x=>x.replace(/[^!]+/g,eval).replace(/!(\d*)!?\d*/g,"$1")
<input value="2+2!5+5" oninput="try{O.value=f(value)}catch(e){}"><br>
<input id=O value="410" disabled>

Might be improved somehow...

share|improve this answer
    
Nice use of function argument to replace. – Neil 8 hours ago
    
@Neil Thanks, but I found a better way :-) – ETHproductions 8 hours ago
    
Your code snippet is giving me the wrong answer on 1+1!5. I think you forgot to eval the bit before the !. – Value Ink 4 hours ago
    
@ValueInk Ah darn, I don't think there's any easy way to fix that. – ETHproductions 4 hours ago

Jelly, 18 bytes

ṣ”!µḊm2;@ḢW$LÐfVṾ€

Try it online!

How?

ṣ”!µḊm2;@ḢW$LÐfVṾ€ - Main link: string
ṣ”!                - split on '!' characters
   µ               - monadic chain separation (call that x)      e.g. ['1+1','0+0','0+0','0+0','','1+0','','','']
    Ḋ              - dequeue x (all but the leftmost entry of x) e.g.       ['0+0','0+0','0+0','','1+0','','','']
     m2            - modulo 2 index into that result             e.g.       ['0+0',      '0+0',   '1+0',   '']
           $       - last two links as a monad
         Ḣ         -     head x (the leftmost entry of x)        e.g.  '1+1'
          W        -     wrap                                    e.g. ['1+1']
       ;@          - concatenate with reversed arguments         e.g. ['1+1','0+0',      '0+0',   '1+0',   '']
             Ðf    - filter keep:
            L      -     length (keep that have non-zero length) e.g. ['1+1','0+0',      '0+0',   '1+0']
               V   - eval as jelly code (vectorises)             e.g. [  2,    0,          0,       1]
                      Yes, addition is just + and decimal numbers are just strings of digits in Jelly believe it or not!
                Ṿ€ - uneval €ach (creates a string from each one)e.g. [ '2',  '0',        '0'     ,'1']
                      without the € it would uneval the list and hence yield commas too)
                   - implicit print (prints the resulting list [of characters and possibly
                      lists of characters] as if it were all one string.)
share|improve this answer
    
I don't think this works for literal 0+0 in the middle of the input (in a place where it isn't being discarded); it produces the null string, even though it should produce a digit 0. – ais523 5 hours ago
    
Ah, true - I will have to move to a longer solution :( – Jonathan Allan 5 hours ago
    
Should be fixed up (possibly golfable now). – Jonathan Allan 5 hours ago

CJam, 20 bytes

r'!/{_{'+/1b}&}%(\2%

Try it online! (Linefeed-separated test suite.)

share|improve this answer

Jelly, 16 bytes

ṣ”!µḢW;m2$VṾ$L¡€

Try it online!

Explanation

The key observation here is that we can run the steps "out of order"; instead of evaluating the sums then ignoring the ones we don't like, we can ignore the sums in invalid positions, then evaluate the rest.

ṣ”!µḢW;m2$VṾ$L¡€
ṣ”!                Split input on '!'
   µ               Set as the new default for missing arguments
    Ḣ              Take the first element, removing it from the default
     W;  $         Cons with
       m2            every odd-numbered element of {the tail of the !-split input}
               €   For each remaining element
          VṾ$      Evaluate and de-evaluate it
             L¡      a number of times equal to its length

Evaluating a sum like "10+10" will evaluate it to a number, e.g. 20, then de-evaluate it to a string, "20". Repeating that process has no additional effect (it's idempotent). Thus, we effectively evaluate every element of the string, except the null string, which remains unevaluated because it has a zero length.

share|improve this answer
    
That's a great trick to conditionally evaluate each item. Could you somehow take the logical AND of each item and its eval-deval'd value? (I assume the empty string is falsy in Jelly) – ETHproductions 4 hours ago
    
@ETHproductions: Jelly's tacitness makes it unlikely that that would save bytes; it prefers to avoid using the same value twice if possible, and if you do want to reuse a value, you normally have to at least put an extra µ in somewhere (and µ doesn't work inside a loop, meaning that you'd need something even more verbose). I did manage to make it work, as ṣ”!µḢW;m2$ȧVṾ$$€, but it isn't any shorter (and has the characteristic pile up of dollar signs that tends to happen when you push Jelly to the edge of its ability to nest control structures.) – ais523 4 hours ago

Batch, 192 184 bytes

@echo off
set/ps=
call:c . "%s:!=" "%"
echo(%s%
exit/b
:c
set s=
if not %2=="" set/as=%2
:l
shift
shift
if "%1"=="" exit/b
if %1=="" goto l
set/at=%1
set s=%s%%t%
goto l

Having to handle the empty strings is inconvenient.

share|improve this answer

Ruby, 58+1 = 59 bytes

Uses the -p flag.

i=0;$_=' '+$_;gsub(/!?([^!]*)/){(eval$1)if(2>i+=1)||i%2<1}

Try it online! (An extra line of code was added so that it would take all of the input lines and print the output in different lines.)

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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