Universal Spooky Meme Translator

43

10

Introduction

Turns out, aliens love memes just as much as we do. Every alien race we've encountered so far has their own version of 2spooky4me (see the following question) and equivalent, though, with some variation. The inhabitants of planet CUTE1f can't handle a lot of spook, so their preferred spook is 1spooky2me, while skeletor7 memers love them some spook, so they tend to use 9spooky11me.

Challenge

Translating memes is hard work, so you've been tasked with writing a universal meme translator to help these guys access the memenet correctly. Your program will accept a meme and a transformation to apply to the digit sequences in that meme to make it appropriate for the inhabitants of a different planet.

Input

Your program will receive two string inputs:

  1. The input meme (e.g. 2spooky4me). Matches [a-zA-Z0-9]+.
  2. The transformation to apply to it (e.g. +1, to go from 2spooky4me to 3spooky5me). Matches [+\-*/^]\d+ (you must accept +, -, *, /, and ^ as operators, regardless of the native representation in your language).

Output

Your program must return a string output (printed to standard output or equivalent) with the given transformation applied to the digit sequences in the input meme. In a weird turn of events, it also turns out that all races encountered so far prefer integral memes over fractional ones, so these transformations should perform integer arithmetic (e.g. 1spooky1me /2 should result in 0spooky0me).

Examples

Standard arithmetic operations apply:

Input:  2spooky4me +1
Output: 3spooky5me

Input:  2spooky4me -1
Output: 1spooky3me

Input:  2spooky4me *15
Output: 30spooky60me

Input:  10spooky900me /5
Output: 2spooky180me

Digit sequences are integral; integer truncation should occur in cases like this:

Input:  idontunderstandmemes3 /2
Output: idontunderstandmemes1

Your input may not have any digit sequences:

Input:  notreallyafunnymeme *100
Output: notreallyafunnymeme

You must support exponentiation, even if it is not a native operation in your language of choice:

Input:  2spooky4me ^3
Output: 8spooky64me

There's no limit on string length of number of digit sequences in the string:

Input:  some1meme2sequences3can4be5really6long7 /2
Output: some0meme1sequences1can2be2really3long3

Addendum

If your language supports arbitrary-precision integers as a language feature, you must use those. If it does not, you do not need to support arbitrary-precision integers. For example, you must use Integer in Haskell instead of Int because it's available as part of the language; in Java, you are not required to use BigInteger because it's a library feature, not a language feature.

Input:  2000000000000000000000000000000000000000000000000000000000000000000000000000000‌​000000000000000000000000000000000spooky4me /2
Output: 1000000000000000000000000000000000000000000000000000000000000000000000000000000‌​000000000000000000000000000000000spooky2me

This is , so standard loopholes are forbidden, and the shortest answer in bytes wins!

Leaderboard

The Stack Snippet at the bottom of this post generates the leaderboard from the answers a) as a list of shortest solution per language and b) as an overall leaderboard.

To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:

## Language Name, N bytes

where N is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:

## Ruby, <s>104</s> <s>101</s> 96 bytes

If there you want to include multiple numbers in your header (e.g. because your score is the sum of two files or you want to list interpreter flag penalties separately), make sure that the actual score is the last number in the header:

## Perl, 43 + 2 (-p flag) = 45 bytes

You can also make the language name a link which will then show up in the snippet:

## [><>](http://esolangs.org/wiki/Fish), 121 bytes

<style>body { text-align: left !important} #answer-list { padding: 10px; width: 290px; float: left; } #language-list { padding: 10px; width: 290px; float: left; } table thead { font-weight: bold; } table td { padding: 5px; }</style><script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="language-list"> <h2>Shortest Solution by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr> </thead> <tbody id="languages"> </tbody> </table> </div> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr> </thead> <tbody id="answers"> </tbody> </table> </div> <table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr> </tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr> </tbody> </table><script>var QUESTION_ID = 79809; var ANSWER_FILTER = "!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe"; var COMMENT_FILTER = "!)Q2B_A2kjfAiU78X(md6BoYk"; var OVERRIDE_USER = 45941; var answers = [], answers_hash, answer_ids, answer_page = 1, more_answers = true, comment_page; function answersUrl(index) { return "https://api.stackexchange.com/2.2/questions/" + QUESTION_ID + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER; } function commentUrl(index, answers) { return "https://api.stackexchange.com/2.2/answers/" + answers.join(';') + "/comments?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + COMMENT_FILTER; } function getAnswers() { jQuery.ajax({ url: answersUrl(answer_page++), method: "get", dataType: "jsonp", crossDomain: true, success: function (data) { answers.push.apply(answers, data.items); answers_hash = []; answer_ids = []; data.items.forEach(function(a) { a.comments = []; var id = +a.share_link.match(/\d+/); answer_ids.push(id); answers_hash[id] = a; }); if (!data.has_more) more_answers = false; comment_page = 1; getComments(); } }); } function getComments() { jQuery.ajax({ url: commentUrl(comment_page++, answer_ids), method: "get", dataType: "jsonp", crossDomain: true, success: function (data) { data.items.forEach(function(c) { if (c.owner.user_id === OVERRIDE_USER) answers_hash[c.post_id].comments.push(c); }); if (data.has_more) getComments(); else if (more_answers) getAnswers(); else process(); } }); } getAnswers(); var SCORE_REG = /<h\d>\s*([^\n,<]*(?:<(?:[^\n>]*>[^\n<]*<\/[^\n>]*>)[^\n,<]*)*),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/; var OVERRIDE_REG = /^Override\s*header:\s*/i; function getAuthorName(a) { return a.owner.display_name; } function process() { var valid = []; answers.forEach(function(a) { var body = a.body; a.comments.forEach(function(c) { if(OVERRIDE_REG.test(c.body)) body = '<h1>' + c.body.replace(OVERRIDE_REG, '') + '</h1>'; }); var match = body.match(SCORE_REG); if (match) valid.push({ user: getAuthorName(a), size: +match[2], language: match[1], link: a.share_link, }); else console.log(body); }); valid.sort(function (a, b) { var aB = a.size, bB = b.size; return aB - bB }); var languages = {}; var place = 1; var lastSize = null; var lastPlace = 1; valid.forEach(function (a) { if (a.size != lastSize) lastPlace = place; lastSize = a.size; ++place; var answer = jQuery("#answer-template").html(); answer = answer.replace("{{PLACE}}", lastPlace + ".") .replace("{{NAME}}", a.user) .replace("{{LANGUAGE}}", a.language) .replace("{{SIZE}}", a.size) .replace("{{LINK}}", a.link); answer = jQuery(answer); jQuery("#answers").append(answer); var lang = a.language; lang = jQuery('<a>'+lang+'</a>').text(); languages[lang] = languages[lang] || {lang: a.language, lang_raw: lang.toLowerCase(), user: a.user, size: a.size, link: a.link}; }); var langs = []; for (var lang in languages) if (languages.hasOwnProperty(lang)) langs.push(languages[lang]); langs.sort(function (a, b) { if (a.lang_raw > b.lang_raw) return 1; if (a.lang_raw < b.lang_raw) return -1; return 0; }); for (var i = 0; i < langs.length; ++i) { var language = jQuery("#language-template").html(); var lang = langs[i]; language = language.replace("{{LANGUAGE}}", lang.lang) .replace("{{NAME}}", lang.user) .replace("{{SIZE}}", lang.size) .replace("{{LINK}}", lang.link); language = jQuery(language); jQuery("#languages").append(language); } }</script>

Itai Ferber

Posted 2016-05-12T19:09:45.810

Reputation: 533

3Your last test case is wrong. You have one too many zeros in the output for it to be /5. – Fund Monica's Lawsuit – 2016-05-12T19:14:29.210

Welcome to PPCG! As [tag:arithmetic] refers solely to Elementary Arithmetic, I suggest you retag this question to [tag:math], which would be more appropriate for a challenge that requires exponents.

– George Gibson – 2016-05-12T19:18:21.393

5

First of all this is a reasonably well put together first post, so congrats :) Note we have a Sandbox where you can post your challenge for feedback before it goes live.

– FryAmTheEggman – 2016-05-12T19:21:07.840

3Welcome to PPCG (even though you've apparently been here for 2+ years). Nice first challenge. Does the addendum about arbitrary precision integers mandate that, for example, Java must use BigInteger for its calculations? – AdmBorkBork – 2016-05-12T19:24:11.883

@GeorgeGibson Ah, thank you! I wasn't sure about how to tag it, but thank you for letting me know. – Itai Ferber – 2016-05-12T19:29:26.620

@FryAmTheEggman Thanks! I'll definitely go through the sandbox next time. :) – Itai Ferber – 2016-05-12T19:30:03.900

@TimmyD Clarified in the post — if it's a language feature, then yes. If it's just available as part of the standard library, then no. e.g. yes in Haskell, no in Java – Itai Ferber – 2016-05-12T19:33:24.823

1The exponential one is evil. – Bálint – 2016-05-12T19:55:01.910

@Bálint Why, thank you. – Itai Ferber – 2016-05-12T20:24:00.967

Do we have to use the symbols +, -, *, / and ^ or can we use the symbols our language uses natively? – Dennis – 2016-05-12T20:41:12.193

18Every alien race we've encountered so far... That's totally true! :-) – Luis Mendo – 2016-05-12T20:48:33.660

@Dennis You must use the symbols +, -, *, /, and ^... Sorry not sorry. – Itai Ferber – 2016-05-12T20:50:25.340

2It's your challenge and ultimately up to you, but that's not really fair towards languages that happen to use a different syntax. – Dennis – 2016-05-12T20:51:33.727

@Dennis True. However, that would then tie specific inputs to specific languages, which I think goes against the spirit of the question, no? Is this a common thing among other code golf questions? – Itai Ferber – 2016-05-12T20:55:48.887

@Dennis If it is common to make exceptions for languages in this way, then I will amend my question. I think you would know way better than I do. – Itai Ferber – 2016-05-12T20:56:41.650

Yes, this is common. – Dennis – 2016-05-12T20:57:15.897

1@Dennis I think the challenge is fine as-is. It's an explicit translation request, so it should fall under the "specific format" exception. – AdmBorkBork – 2016-05-12T20:58:35.017

BTW, I'd expected something like "and because some aliens are scared from long code, you need to write it as short as possible" – Bálint – 2016-05-12T21:19:12.903

@Dennis As a compromise, would it be appropriate to award bonus bytes if your language does not support those arithmetic operators by default but you implement them anyway? (Allowing you to stick to the defaults if necessary.) – Itai Ferber – 2016-05-12T22:27:08.663

Bonuses in code-golf are generally not a good idea. At this point, I wouldn't change the challenge anymore. – Dennis – 2016-05-12T23:13:51.753

If you insist on BigInt functionality, you should include a test case that requires them. My previous revision of the Julia submission was failing 2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000spooky4me, /2. Fixing that cost 17 bytes... :( – Dennis – 2016-05-12T23:32:13.777

@Dennis Yikes, sorry! :( Added an example above. – Itai Ferber – 2016-05-13T02:00:06.187

2I might be overlooking it in the spec but do we need to handle inputs like 2spooky4me -5? – Martin Ender – 2016-05-13T12:40:05.420

What's the answer to 2spooky4me, /0? – Magic Octopus Urn – 2016-10-13T18:27:31.650

9spooky11me is of a slightly bad taste, and it's not spooky at all (it's just macabre/tragic/sad/reminding<bad>)... maybe you can choose 6spooky66me instead? Satanism is not prohibited, as far as I know :) – Erik the Outgolfer – 2016-10-13T18:55:28.663

@carusocomputing That's undefined, as the operation doesn't really make sense. – Itai Ferber – 2016-10-13T19:03:07.993

@ItaiFerber As in your code can error or cannot error on it? – Magic Octopus Urn – 2016-10-13T19:04:40.627

1@carusocomputing Your code is allowed to error on it; it's not really a valid input. – Itai Ferber – 2016-10-13T19:05:18.023

Answers

10

Jolf, 15 14 bytes

ρi«\d+»dC!6+HI

Try it here!

Explanation

ρi«\d+»dC!6+HI
ρ «\d+»         replace all digits
 i              in the input
       d        (functional replace)
         !6     eval (using jolf's custom infix eval)
           +H   the number as a string plus
             I  the second input
        C       floor the result (integer truncate)

Fun to note, I updated Jolf after this challenge, adding some RegExp builtins. This could be 12 11 bytes:

ρiLRdC!6+HI

Conor O'Brien

Posted 2016-05-12T19:09:45.810

Reputation: 36 228

24

Ruby, 50 44 43 bytes

FGITW answer. Gotta go fast!

Thanks to @Neil for saving 6 bytes.

Oh right, crossed out 44 is still 44

->m,t{m.gsub(/\d+/){eval$&+t.sub(?^,'**')}}

Value Ink

Posted 2016-05-12T19:09:45.810

Reputation: 10 608

Oh, man, this is almost exactly an answer I was poking away at: a=gets;$><<gets.gsub(/\d+/){eval$&+a}. Mine missed the ^ != ** thing, though, and is probably a bit longer. – Fund Monica's Lawsuit – 2016-05-12T20:47:30.527

3+1 for having your whole solution be 4 bytes shorter than what's needed in PowerShell just to handle ^. :D – AdmBorkBork – 2016-05-12T20:49:11.027

15

Perl, 36 34 bytes

s/\d+/"0|$&$^I"=~s#\^#**#r/gee

The source code is 30 bytes long and it requires the switches -pi (+4 bytes). It takes the first input from STDIN, the second input as an argument to -i.

Thanks to @DenisIbaev for golfing off 2 bytes!

Test it on Ideone.

Dennis

Posted 2016-05-12T19:09:45.810

Reputation: 196 637

Yep, I figured if anybody could beat my Ruby answer, it would be Dennis and/or be in Perl, and you ended up fulfilling both expectations at the same time – Value Ink – 2016-05-13T00:49:30.197

1-pi is 4 bytes? – CalculatorFeline – 2016-05-13T20:16:42.920

@CatsAreFluffy Current consensus is to count the edit distance from the invocation without the flags. That includes a space to separate -pi from the rest of the command.

– Dennis – 2016-05-13T20:26:10.290

"0|$&" is shorter than "0|".$&. – Denis Ibaev – 2016-05-16T13:50:50.533

@DenisIbaev Since the input is alphanumeric, "0|$&$^I" works too. Thanks! – Dennis – 2016-05-16T20:19:33.750

9

PowerShell v2+, 139 137 bytes

param($a,$b)-join($a-split"(\d+)"|%{if($_-match"\d+"){if($b[0]-ne'^'){[math]::Floor((iex $_$b))}else{"$_*"*$b.Trim('^')+1|iex}}else{$_}})

Ooof ... 47 bytes just to account for ^ since that's not a native operator in PowerShell. Saved 2 bytes thanks to @TessellatingHeckler.

Takes input as $a=<word>, $b=<operation>, like .\universal-spooky-meme.ps1 2spooky4me ^3. We -split $a on digits, enclosing that in parens so we keep the delimiters, and pipe the resultant array through a loop |%{...}. If the current piece is a number, we're in the first if. We need to check whether the first character of $b is ^. If it's not, we simply concatenate our current piece and $b and send it to iex (similar to eval), then leave that on the pipeline. Otherwise, we need to create an exponentiation string with "$_*"*$b.Trim('^')+1 and pipe that to iex, and leave that on the pipeline. For the given 2spooky4me ^3 example, this will be 2*2*2*1 and 4*4*4*1, respectively.

Otherwise, we just leave the string as-is on the pipeline.

All of those results are gathered from the pipeline with the encapsulating parens before being -joined back together into one string. That is the re-left on the pipeline, and output is implicit at program termination.

Examples

PS C:\Tools\Scripts\golfing> .\universal-spooky-meme.ps1 2spooky4me ^5
32spooky1024me

PS C:\Tools\Scripts\golfing> .\universal-spooky-meme.ps1 2spooky4me /3
0spooky1me

AdmBorkBork

Posted 2016-05-12T19:09:45.810

Reputation: 41 581

I wrote my own before looking at answers, then I pinched some of your ideas as well - thanks. I think you could replace Floor(("$_$b"|iex)) with Floor((iex $_$b)) to save a couple, or maybe iex $_+$b. – TessellatingHeckler – 2016-05-13T23:28:13.190

@TessellatingHeckler Thanks for the two bytes! – AdmBorkBork – 2016-05-16T12:30:38.463

8

JavaScript (ES7), 58 57 bytes

(s,t)=>s.replace(/\d+/g,n=>0|eval(n+t.replace('^','**')))

Edit: Saved 1 byte when I remembered that replace also works on literal strings.

Neil

Posted 2016-05-12T19:09:45.810

Reputation: 95 035

Cool, I'm working on an ES6 solution – Bálint – 2016-05-12T20:11:23.503

Can you curry to save a byte? – gcampbell – 2016-05-15T13:17:10.083

1@gcampbell Yes, but I'm too lazy to. – Neil – 2016-05-15T19:50:53.190

6

Python 2, 156 89 88 87 bytes

Inspired by the other answers that use their languages' substitution function with a function handler to process the numeric parts of the long input string with the operator. Unlucky for Python, the ^ must be replaced by **, which costs a whopping 18 bytes. The .group(0) call just to access the match object's string representation does not make things better...

Thanks to QPaysTaxes for spotting a spurious space and RootTwo for the unnecessary argument to .group!

import re
lambda i,o:re.sub(r'\d+',lambda p:str(eval(p.group()+o.replace('^','**'))),i)

ojdo

Posted 2016-05-12T19:09:45.810

Reputation: 410

I think you can get rid of the space after i,o: – Fund Monica's Lawsuit – 2016-05-12T20:50:41.983

You can save two more bytes: (1) by using p.group(). (it defaults to 0); and (2) insert r=re.sub; replace first re.sub call with r and then use r('^','**',o) instead of o.replace(...) – RootTwo – 2016-05-13T06:56:07.433

@RootTwo: For me, the r('^','**',o) then requires escaping ^ to \^ in order to match the character, not the beginning of o, net saving no bytes :-( - but thanks for pointing out the unnecessary 0! – ojdo – 2016-05-13T14:35:14.600

6

Pyth, 29

Jws.i:zK"\d+"3m.vs.iJ]+d;:zK1

This works by extracting each number from the meme, and then interleaving (.i) it followed by a space and wrapped in a list with the other argument. So if our number is 7 and we had ^20 we would get the list: ["^", "7 ", "20"]. Flattening and using Pyth's eval (.v) on this always gives the operation we want. Finally these values are interleaved with the original string split on occurrences of numbers.

This could be a byte shorter if both inputs were surrounded by quote characters, or two bytes shorter if only one of them could be quoted.

Try it here or run a Test Suite

FryAmTheEggman

Posted 2016-05-12T19:09:45.810

Reputation: 16 206

5

Javascript (ES6) 99 bytes

Another example, why we hate to wait for ES7 to get compatibility

(a,b)=>a.match(/\d+|\D+/g).map(_=>(d=- -_)?eval(b[0]=="\^"?Math.pow(_,b.slice(1)):d+b)|0:_).join``

Runnable example:

f=(a,b)=>a.match(/\d+|\D+/g).map(_=>(d=- -_)?Math.ceil(eval(b[0]=="\^"?Math.pow(_,b.slice(1)):d+b)):_).join``

alert(f(prompt("Enter string!"), prompt("Enter operation!")));

Bálint

Posted 2016-05-12T19:09:45.810

Reputation: 1 847

Your matching regexes seem to be a bit off. In the runnable example, you leave out uppercase letters, which strips them out of the result ("2spooky4ME", "+1" => "3spooky5"), and in the first example, you match against \d+|\D+, which is equivalent to .+. [a-zA-Z0-9]+ is the regex you want, no? Or [a-zA-Z]+|[0-9]+ if the splitting makes a difference? – Itai Ferber – 2016-05-12T20:31:12.543

It would probably be easier to invoke Math.pow directly as you're having to special-case it anyway. Also, are you using integer division? – Neil – 2016-05-12T20:37:08.223

@Neil I forgot that, minute – Bálint – 2016-05-12T20:53:36.877

@Neil is there a better way for ceiling? – Bálint – 2016-05-12T21:07:33.710

Not sure why you want ceiling but |0 might help. – Neil – 2016-05-12T23:56:37.620

@Neil I thought you need ceiling – Bálint – 2016-05-13T06:17:52.307

@ItaiFerber I'm not sure why that would be better, and I tested, and it's correct. Please learn about regexes – Bálint – 2016-05-13T06:28:49.653

1@ItaiFerber \d+|\D+ Isn't quite the same as .+. They aren't the same because the kleene expansion happens before the or. It would be the same if it looked like (\d|\D)+, but as is, it wouldn't match all of say 2a in one group, it would be two separate groups. – FryAmTheEggman – 2016-05-13T19:42:46.727

@FryAmTheEggman Right, duh. Again, too hasty an evaluation here. Thanks! – Itai Ferber – 2016-05-14T03:27:03.630

@Bálint Sorry about that – Itai Ferber – 2016-05-14T03:27:28.753

You can curry to save a byte – Cyoce – 2016-10-13T17:52:18.980

5

Julia, 71 59 54 bytes

/ =÷
x%y=replace(x,r"\d+",t->"big($t)"y|>parse|>eval)

The requirement to use big if available makes this a lot longer than it could be...

Try it online!

Dennis

Posted 2016-05-12T19:09:45.810

Reputation: 196 637

4

PowerShell (v4), 124 120 bytes

# New 120 byte version:
$s,$a=$args;[regex]::Replace($s,'\d+',{($(if($a-ne($a=$a.Trim('^'))){
"$args*"*$a+1}else{"$args$a"})|iex)-replace'\..*'})

# Previous 124 byte version
$s,$a=$args;[regex]::Replace($s,'\d+',{if($a[0]-eq'^'){
[math]::pow("$args",$a.Trim('^'))}else{iex "$args$a-replace'\..*'"}})

(the newlines are only here to avoid horizontal scrolling, they work when saved as one line).

Comments, and ungolfed version was requested:

$meme, $instruction = $args

# Scriptblock which processes the numbers
# to be replaced. $args is the input number.
$replacement = {

    # Generates a string of the calculation, by:
    # Removing leading ^ character, if present.
    # ^3 -> 3,      +3 -> +3
    # See if it was present, and switch code paths.
    # (Can be one combined step in the golf)
    # Switch code paths for "raise to the power of",
    # or basic arithmetic.
    $trimmedInstruction = $instruction.Trim('^')
    $tmp = if ( $instruction -ne $trimmedInstruction ) {

        # String multiplication, changes
        # function input "45" and instruction "3" into
        # "45*45*45*+1". The "3" implicitly casts to [int]
        # the +1 is there to make the trailing * not crash.
        "$args*" * $instruction + 1

    } else {
        # Cobble the basic math together as a string
        # "45" and "+10" becomes
        # "45+10"
        "$args$instruction"
    }

    # eval() the generated string (e.g. "45+10" or "45*45*45*+1")
    $tmp = Invoke-Expression $tmp      # iex

    # Use a regex golf to replace trailing .23423
    # decimals in case of division with remainder.
    # Acts as [math]::floor(), harmless on other numbers.
    $tmp -replace'\..*'
}

# A regular expression replacement which picks out all 
# the numbers (\d+) and runs them through the
# replacement function. Returns a string which 
# ends up on stdout
[regex]::Replace($meme, '\d+', $replacement)
  • .Net regex library can do a replace with a scriptblock that executes on the content of the match, and PowerShell casts types strings to numbers, and iex is like eval() in other languages. It just does "2spooky" "+3" -> eval("2+3")
  • Except... it can't handle ^ operator or any other convenient exponentiation like **, it can only use the [math]::Pow() library call so there's a big block to handle that branch.
    • The updated version steals an idea from @TimmyD and does string multiplication instead - "2*" * n which becomes "2*2*2*2*" and then adds +1 on the end to multiply by one instead of complaining about the trailing *.
  • Except... .Net does Banker's Rounding which rounds to the nearest even number by default, and 3/2 = 2 rather than 3/2 = 1. This challenge calls for truncation, and that means [math]::Truncate(). Instead, I save characters by using -replace to trim a decimal point and anything after it.

Test cases:

PS D:\> .\meme.ps1 2spooky4me +1
3spooky5me

PS D:\> .\meme.ps1 2spooky4me -1
1spooky3me

PS D:\> .\meme.ps1 2spooky4me *15
30spooky60me

PS D:\> .\meme.ps1 10spooky900me /5
2spooky180me

PS D:\> .\meme.ps1 idontunderstandememes3 /2
idontunderstandememes1

PS D:\> .\meme.ps1 "idontunderstandememes3" "/2"
idontunderstandememes1

PS D:\> .\meme.ps1 "notreallyafunnymeme" "*100"
notreallyafunnymeme

PS D:\> .\meme.ps1 "2spooky4me" "^3"
8spooky64me

PS D:\> .\meme.ps1 "some1meme2sequences3can4be5really6long7" "/2"
some0meme1sequences1can2be2really3long3

PS D:\> .\meme.ps1 2000000000000000000000000000000000000000000000000000000000000000000000000000000‌​000000000000000000000000000000000spooky4me /2
1E+78‌​0spooky2me

NB. In the last test the numbers overflow into type [BigInteger] automatically, but they get rendered in scientific notation. Luckily, every known race able to communicate between the stars has enough scientific development to be able to process scientific notation without problem.

TessellatingHeckler

Posted 2016-05-12T19:09:45.810

Reputation: 2 412

1You can see in other answers how they provide a rather unreadable golfed version and then a separate ungolfed version for examining the code behavior. You should do this with yours (namely, remove the newlines in the golfed version). – jpmc26 – 2016-05-16T07:21:30.660

Thanks for the credit, but not my trick -- I pulled it from the PowerShell Tips thread. – AdmBorkBork – 2016-05-16T12:31:13.933

Apparently, I care enough to leave a comment, and someone else cares enough to upvote my comment. ;) – jpmc26 – 2016-05-16T20:39:44.783

No, I said you should have a fully golfed version and a fully ungolfed version. The golfed one will require scrolling. The ungolfed one will not and will be more readable than the one you have. – jpmc26 – 2016-05-16T20:57:00.370

1@jpmc26 Ok, I've edited in an ungolfed, commented version. – TessellatingHeckler – 2016-05-18T17:50:46.850

4

Kotlin, 416 413 Bytes

The lack of an eval() in Kotlin really upped that byte count...

fun main(a:Array<String>){var r=Regex("\\d+");var i=a[0];var n=a[1].takeLast(a[1].length-1).toInt();when(a[1][0]){'+'->print(r.replace(i,{m->""+(m.value.toInt()+n)}));'*'->print(r.replace(i,{m->""+(m.value.toInt()*n)}));'/'->print(r.replace(i,{m->""+(m.value.toInt()/n)}));'-'->print(r.replace(i,{m->""+(m.value.toInt()-n)}));'^'->print(r.replace(i,{m->""+(Math.pow(m.value.toDouble(),n.toDouble())).toInt()}));}}

Try it Online!

Ungolfed

fun main(a: Array<String>) {
    var r = Regex("""\d+""")
    var i = a[0]
    var n = a[1].takeLast(a[1].length - 1).toInt()
    when (a[1][0]) {
        '+' -> print(r.replace(i, { m -> "" + (m.value.toInt() + n) }))
        '*' -> print(r.replace(i, { m -> "" + (m.value.toInt() * n) }))
        '/' -> print(r.replace(i, { m -> "" + (m.value.toInt() / n) }))
        '-' -> print(r.replace(i, { m -> "" + (m.value.toInt() - n) }))
        '^' -> print(r.replace(i, { m -> "" + (Math.pow(m.value.toDouble(), n.toDouble())).toInt() }))
    }
}

The_Lone_Devil

Posted 2016-05-12T19:09:45.810

Reputation: 191

3

Lua, 145 93 bytes

r=io.read;m=r()o=r()m=m:gsub("%d",function(n)return loadstring("return..."..o)(n)end)print(m)

Blab

Posted 2016-05-12T19:09:45.810

Reputation: 451

Why not just post a function? – Bálint – 2016-05-13T08:10:41.450

3

Bash + GNU coreutils, 144 Bytes

d=
u=$1,
for((i=0;i<${#u};i++)){ l=${u:i:1}
[[ "$l" =~ [0-9] ]]&&d=$d$l||{ [ -z $d ]||echo -n `bc<<<$d$2`&&{ [ $l != , ]&&echo -n $l; };d=; }
}

This looks at the alteration between digits and non-digits, that's why a random invalid input character (comma) is appended to the input string. This comma is then ignored in the output. The convention of the OP follows exactly the syntax of bc which is used here to do the maths.

rexkogitans

Posted 2016-05-12T19:09:45.810

Reputation: 589

By the way because of discussion in the PowerShell-solution by @TessellatingHeckler: In my solution, you can translate the program to a single line by replacing the line breaks to semicolons, which does not change its length. – rexkogitans – 2016-05-17T17:58:38.887

2

R, 163 bytes

As someone who's learning regular expressions and string substitution in R, this proved to be a quite difficult challenge. Especially because matching the numbers is easy but I couldn't find a way to use multiple substitutions with gsub. Furthermore, I don't know if eval(parse(paste0(... is the most efficient way to switch between operations. Maybe the switch-function is better suited here.

function(s,o){p=strsplit;y=p(gsub("\\d+","?",s),"?")[[1]];x=na.omit(as.integer(p(s,"[a-zA-Z]+")[[1]]));y[y=="?"]=floor(eval(parse(,,paste0("x",o))));cat(y,sep="")}

Explanation

f=function(s,o){
    p=strsplit                                    # alias for stringsplit    
    y=p(gsub("\\d+","?",s),"?")[[1]]              # substitute numbers with "?" and split into vector on "?"
    x=na.omit(as.integer(p(s,"[a-zA-Z]+")[[1]]))  # split at alphabetical char, return vector with numbers to be operated on
    y[y=="?"]=floor(eval(parse(,,paste0("x",o)))) # replace inserted "?" with vector of numbers operated on
    cat(y,sep="")                                 # print concatenated vector
}

Billywob

Posted 2016-05-12T19:09:45.810

Reputation: 3 363

I think you can save a ton of bytes if you use gsub with a closure on the matches, which is what you hinted at in your comment. I don't know how to do it in R though. I struggled with that too until I found out how to do that in Groovy; was pretty much a game changer. – Magic Octopus Urn – 2016-10-13T19:37:16.410

2

Javascript (ES6), 85 Bytes

x=(s)=>{var a=s.split(" ");return[...a[0]].map(x=>(!isNaN(x))?eval(x+a[1]):x).join``}

console.log(x("2spookie5me +1"));

Ungolfed:

x = (s) => {
  var a = s.split(" ");
  return [...a[0]].map(x => (!isNaN(x)) ? eval(x + a[1]) : x).join ``
}
console.log(x("2spookie5me +1"));

Bladimir Ruiz

Posted 2016-05-12T19:09:45.810

Reputation: 151

Anyone know if i can split spaces using Spread operator? From this s.split(" "); to [" "...s]; At least thats the idea. – Bladimir Ruiz – 2016-10-13T14:35:29.617

You don't need () around the lambda argument, you don't need var, and you should use parens and the comma operator instead of braces and return – Cyoce – 2016-10-13T18:15:58.203

Also, ^ is a special case to JavaScript, it is a bitwise XOR instead of Math.pow – Sunny Pun – 2016-10-13T18:29:44.477

2

Groovy, 64 60 Bytes

{a,b->a.replaceAll(/\d+/,{Eval.me(it+b.replace("^","**"))})}

Replaces all instances of digits with a closure that evaluates the operation on the digit portions of the word passed. If passed an exponent function, it replaces it with the proper notation. Groovy implicitly handles BigInteger/BigDecimal conversion when using Eval.me() because parsed strings can potentially be out of the 2^32-1 range.

Explained

{a,b->...} - Closure with two arguments.

a.replaceAll(/\d+/,{...}) - Search for all digit sequences in string and replace with a closure.

{Eval.me(it+b.replace("^","**"))} - More specifically, a closure with each match having the operation appended to it, then evaluated as groovy code.

.replace("^","**") - Replace the first instance of ^ with the groovy exponent operator ** in the operation provided. If you want this to work with full equation strings that use exponents, use replaceAll() instead for a +3 byte penalty.

Fun side-note his is a valid test scenario:
(22348952345238905290858906209862398036spooky409552me, /200*4943^8-23939+((100/203)+600)

Magic Octopus Urn

Posted 2016-05-12T19:09:45.810

Reputation: 19 422

1

RProgN, 39 Bytes

►x='%d+'§x'%D+'''Rx'%d+'''Rg'y'=y_}R

Explained

►x='%d+'§x'%D+'''Rx'%d+'''Rg'y'=y_}R
►                                       # Spaceless segment.
 x=                                     # Assign the top value of the stack '[+*/-]\d+' 
   '$d+'§                         }R     # Replace everything in the pattern %d+ (all numbers) based on an anonymous function 
         x'%D+'''R                      # Replace all Non-digits in the modifer with nothing, leaving just the second argument for the operator.
                  x'%d+'''R             # Snip all digits, separating our operator from our digits such that digit operator exists in the stack.
                           g'y'=        # Grab the function that is represented by the top of the stack (the operator in this case)
                                y       # Run it
                                 _      # Floor the result. 

Technically invalid answer, because this language did not exist for it. However, it was not specifically designed for it, nor any particular addition. So I'm running it. Sue me.

Try it Online!

ATaco

Posted 2016-05-12T19:09:45.810

Reputation: 7 898

0

Perl 6, 111 bytes

{/(\w+)\s(<[+\-*/^]>)(\d+)/&&my \b=+$2;my \o=(*+b,*-b,* *b,*div b,* **b)[index "+-*/^",$1];$0.subst(/\d+/,o):g}

Unfortunately EVAL is disabled by default. Also, you have to use div for integer division.

bb94

Posted 2016-05-12T19:09:45.810

Reputation: 1 831