When life gives you lemons, make lemonade

21

3

Challenge

You will be given an input string, anywhere the word "Lemon" is found it should be converted to "Lemonade" but the a, d, and e must be borrowed from somewhere else in the sentence.


Example

Example Input:

I found a lemon when I was a kid

Example Output:

I foun a lemonade whn I was  kid

The Lemonade was created by stealing the following superscript letters from the original

I found a lemonade when I was a kid

This is just one possible output example, the "e", "d", and "a", could have been taken from anywhere (except for from the word lemon of course)


Comments

•If there are not enough e, a, or ds you must output what was do-able with the letters given. For example the input bdblemon would output bblemond

•The lemon text might not always be standalone (space on each side). For example you may have the word lemons somewhere in the input and the output should be lemonades

•The input may contain any number of lemons, even 0 lemons (in which case the output would be identical to the input)

•You can make your lemonade with uppercase and lowercase letters, for example leMon could become leMonade, and the ade borrowed can be any case (so it could also have become leMonADe).
The case of the letter you borrowed must remain what it was when you borrowed it.
(Example input -> output, he hAD lemOn -> h h lemOnADe)

•Does not have to be a full program, a function alone is fine.

•You may assume input will be only the CP437 Character Set


Code Golf

This is , so the lowest number of bytes wins!


Pseudo-TestCases

*Note: For any given input there might be multiple possible outputs so your program may not output exactly as these test cases do, this is more just so people can understand the logic:

Input: EpaD leMons
Output: p LeMonaDEs

Input: hello world
Output: hello world

Input: lemon lemon
Output: lemon lemon
*(The e, a, d letters should never be taken from another "Lemon")

Input: HE HAD lemonade
Output: H H lemonADEade

Input: Do you like lemons? You hAd me at lemon!
Output: o you lik lemonADes? You h m t lemonade!

Input: AE lemon
Output:  lemonAE

Input: 55bad lemon
Output: 55b lemonad

Albert Renshaw

Posted 2017-04-30T23:19:51.540

Reputation: 2 955

Answers

6

JavaScript (ES6), 159 157 155 162 bytes

Edit: +7 bytes to "output what was do-able with the letters given" rather than throwing out an error


A recursive function that returns the modified string.

f=(s,a=s.split(/(lemon)/i),n=(a.length-1)*1.5)=>n?f(n,a.map((s,i)=>i&1|!n||(a[i]=s.replace([/a/i,/e/i,/d/i][n%3],c=>(a[--n/3<<1|1]+=c,''))))&&a,n-(n==s)):a.join``

How it works

The expression s.split(/(lemon)/i) splits the input string on lemon but preserves the capture groups in the result.

For instance, "foo lemon bar LEMON baz".split(/(lemon)/i) will produce the array [ 'foo ', 'lemon', ' bar ', 'LEMON', ' baz' ].

We recursively iterate on this array, extracting the characters a, d and e or their uppercase counterparts from the entries located at an even position, and appending them to the entries located at an odd position.

Commented

f = (                                   // given:
  s,                                    //   s = input string or previous value of 'n'
  a = s.split(/(lemon)/i),              //   a = split array, as described above
  n = (a.length - 1) * 1.5              //   n = total number of characters to be found
) =>                                    //
  n ?                                   // if there's still at least one character to find:
    f(                                  //   do a recursive call with:
      n,                                //     1) the current value of 'n'
      a.map((s, i) =>                   //     2) an updated version of 'a', where
        i & 1 | !n || (                 //       for even positions:
          a[i] = s.replace(             //         we look for the next character
            [/a/i, /e/i, /d/i][n % 3],  //           'a', 'e' or 'd' (case insensitive)
            c => (                      //           append it to
              a[--n / 3 << 1 | 1] += c, //           one of the entries at an odd position
              ''                        //           and remove it from the original entry
            )                           //           end of replace() callback
          )                             //         end of replace()
        )                               //       end of position condition
      ) && a,                           //     end of map() -> yield the updated 'a'
      n -                               //     3) the updated value of 'n', skipping the
      (n == s)                          //        current character if not found at all
    )                                   //   end of recursive call
  :                                     // else:
    a.join``                            //   success: join 'a' and return it

Demo

f=(s,a=s.split(/(lemon)/i),n=(a.length-1)*1.5)=>n?f(n,a.map((s,i)=>i&1|!n||(a[i]=s.replace([/a/i,/e/i,/d/i][n%3],c=>(a[--n/3<<1|1]+=c,''))))&&a,n-(n==s)):a.join``

console.log(f("I found a lemon when I was a kid"))
console.log(f("I found a lemon when I was a kid. I found another lemon when I was older."))
console.log(f("bdblemon"))
console.log(f("he hAD lemOn"))

Arnauld

Posted 2017-04-30T23:19:51.540

Reputation: 111 334

Throwing a recursion-error doesn't seem to comply to the first rule ("If there are not enough e, a, or ds you must output what was do-able with the letters given. For example the input bdblemon would output bblemond")? – Kevin Cruijssen – 2017-05-01T12:31:16.943

1@KevinCruijssen Hmm, you're right. I was almost certain that throwing an error was initially allowed. Was it an edit during the grace period of the initial post? (Either that or I dreamed it.) Anyway, I'll try to fix that. Thanks for noticing. – Arnauld – 2017-05-01T12:38:55.913

I looked back in the history before making my comment in case it was indeed edited out. You could be right it might have been edited in the first 5 minutes, but no idea how to check that. And no problem, your answer is still pretty impressive, so I'll +1 it in advance. I have no doubt you'll be able to fix the issue (hopefully without causing to much added bytes). – Kevin Cruijssen – 2017-05-01T12:41:57.040

@KevinCruijssen That's fixed at the cost of 7 bytes for now. – Arnauld – 2017-05-01T13:21:19.300

2@Arnauld Yes sorry I edited that out within the first 2 minutes of the post maybe haha, my apologies – Albert Renshaw – 2017-05-01T17:08:31.883

@AlbertRenshaw No worries. At least, I'm not crazy. :-p – Arnauld – 2017-05-01T17:39:56.370

5

CJam, 130 bytes

LqY5m*{"lemon"_eu}%3/:z{~?}f%{_@\/_:,[{1$+}*]);@f{[\]}@+\1a*}/\{1
=}$0f=\1$,{"ade"{__C#)\Ceu#)|(\0+We\)@_N=@+N\t\}fC}fN0a/L*1a/\.{}

This is split across two lines for clarity; the newline is not counted.

Pseudocode:

FLAG_1 = object()
FLAG_2 = object()
lemon_instances = [] # CJam: L
input_chars = list(all_input()) # CJam: q
lemons = [
    "LEMON", "LEMOn", "LEMoN", "LEMon", "LEmON", "LEmOn", "LEmoN", "LEmon",
    "LeMON", "LeMOn", "LeMoN", "LeMon", "LemON", "LemOn", "LemoN", "Lemon",
    "lEMON", "lEMOn", "lEMoN", "lEMon", "lEmON", "lEmOn", "lEmoN", "lEmon",
    "leMON", "leMOn", "leMoN", "leMon", "lemON", "lemOn", "lemoN", "lemon"
] # CJam: Y5m*{"lemon"_eu}%3/:z{~?}f%
for i in lemons: # CJam: { ... }/
    temp = input_chars.split(i) # CJam: _@\/
    lengths = temp.map(len) # CJam: _:,
    # Here, accum turns an array like [1,2,3] into [1,3,6].
    indices = accum(lengths) # CJam: [{1$+}*]
    indices.pop() # CJam: );
    temp2 = zip(temp, indices) # CJam: @f{[\]}
    lemon_instances = temp2 + lemon_instances # CJam: @+
    input_chars = join_array(temp, FLAG_1) # CJam: 1a*
lemon_instances.sort(key=lambda x: x[1]) # CJam: {1=}$
lemon_instances = [i[0] for i in lemon_instances] # CJam: 0f=
for i in range(len(lemon_instances)): # CJam: \1$,{...}fN
    for c in "ade": # CJam: "ade"{...}fC
        # list_index returns -1 if not found
        lower = list_index(input_chars, c)+1 # CJam: __C#)
        upper = list_index(input_chars, upper(c))+1 # CJam: \Ceu#)
        char_index = (lower or upper) - 1 # CJam: |(
        input_chars.append(FLAG_2) # CJam: \0+
        # -1 refers to the last element in the list
        swap_list_elements(input_chars, char_index, -1) # CJam: e\
        extracted = input_chars.pop() # CJam: )
        lemon_instances[i] += extracted # CJam: @_N=@+N\t\
remove_all(input_chars, FLAG_2) # CJam: 0a/L*
temp1 = input_chars.split(FLAG_1) # CJam: 1a/
# interleave([1, 2, 3], ["a", "b"]) gives [1, "a", 2, "b", 3]
temp2 = interleave(temp1, lemon_instances) # CJam: \.{}
print("".join(temp2))

Esolanging Fruit

Posted 2017-04-30T23:19:51.540

Reputation: 13 542

I'm saddened this doesn't have more upvotes, great answer imo – Albert Renshaw – 2017-05-03T00:37:08.007

4

Retina, 303 bytes

i+`(?<!lemon)(a)(.*)(lemon)(?!a)
$2$3$1
i+`(lemon)(?!a)(.*)(?<!lemon)(a)
$1$3$2
i+(?<!lemona?)(d)(.*)(lemona?)(?![ad])
$2$3$1
i+`(lemona?)(?![ad])(.*)(?<!lemona?)(d)
$1$3$2
i+(?<!lemona?d?)(e)(?!(?<=le)mon)(.*)(lemona?d?)(?![ade])
$2$3$1
i+`(lemona?d?)(?![ade])(.*)(?<!lemona?d?)(e)(?!(?<=le)mon)
$1$3$2

Try it online!

Surely I'm doing something wrong here.

Neil

Posted 2017-04-30T23:19:51.540

Reputation: 95 035