# Derivative of a product

In calculus, the derivative of a mathematical function defines the rate at which it changes. The derivative of a function f(x) can be marked as f'(x), and these can sometimes be abbreviated to f and f'.

The derivative of the product of two functions fg is f'g + g'f. The derivative of three fgh is f'gh + fg'h + fgh'. In general, the derivative of a product of any number of functions is the sum of the product of all but one, multiplied by the derivative of the remaining one, for each individual function.

Your challenge is to take a string of distinct alphabetical characters and transform it into its derivative. No spacing or simplification is required, and terms separated by + may be in any order. The string will contain at least two characters.

This is , so the shortest code wins!

## Testcases

abc -> a'bc+ab'c+abc'
de -> d'e+de'
longabcdef -> l'ongabcdef+lo'ngabcdef+lon'gabcdef+long'abcdef+longa'bcdef+longab'cdef+longabc'def+longabcd'ef+longabcde'f+longabcdef'
short -> s'hort+sh'ort+sho'rt+shor't+short'

• Can we assume all letters are distinct?
– att
May 7 at 1:33
• @att Sure, tht's fine. May 7 at 2:09
• Is output with a leading + acceptable? May 7 at 5:12
• do the functions in each term need to remain in the original order? In other words, is aabc'+bca'+cab' an acceptable output for abc? May 7 at 9:10
• @DominicvanEssen That's a tricky one... I'm gonna say no simply because it's a major part of the challenge, and pretty much all answers would have to change to remain competitive under that. May 7 at 11:18

# Pip, 15 bytes

aRL#aJ'+<>#aJ''


Attempt This Online!

### Explanation

aRL#aJ'+<>#aJ''
a                Command-line arg       "abc"
#a            Length of arg          3
RL              Repeat-list            ["abc"; "abc"; "abc"]
J'+         Join on "+"            "abc+abc+abc"
<>#a     Groups of size len(a)  ["abc"; "+ab"; "c+a"; "bc"]
J''  Join on "'"            "abc'+ab'c+a'bc"


# Python, 54 bytes

lambda s:((l:=len(s))*(l*"'"+-~l*(s+"+")))[-~l*~l::-l]

Attempt This Online!

# Python, 56 bytes

lambda s:((l:=-~len(s))*(l*(s+"+")+-~l*"'"))[l:-3*l:-~l]

Attempt This Online!

## Old Python, 58 bytes

lambda s:((l:=-~len(s))*(l*(s+"+")+l*"'"+"+"))[l:-3*l:-~l]

Attempt This Online!

## How?

 a b c d +
(a)b c d +
a(b)c d +
a b(c)d +
a b c(d)+
' ' ' '(')'
a b c d(+)
a b c d +
(a)b c d +
a(b)c d +
a b(c)d +
' ' '(')' '
a b c(d)+
a b c d(+)
a b c d +
(a)b c d +
a(b)c d +
' '(')' ' '
a b(c)d +

etc.


# C (clang), 6964 59 bytes

-10 thanks to @Noodle9 and @ceilingcat

l;f(char*a){for(l=0;a[l];)printf("+%.*s'%s"+!l,++l,a,a+l);}


Try it online!

# Brainfuck, 87 84 bytes

>,>---[>+<+++++++]>++[>,]<[<]<[<]>[[.>]>.>[.[-<<+>>]>[.>]<[<]<++++.----[->+<]<[<]]>]


Saved 3 bytes thanks to Nitrodon.

Try it online!

Explanation:

memory progress for abc:
null a null 'bc
null ab null 'c
null abc' null

string is split to two parts by null character

>,>                load first character
---[>+<+++++++]>++ load ' to memory; taken form esolangs wiki
[>,]               load rest of input
<[<]<[<]>          go to beginning of memory
[
[.>]              print first part
>.>               print '
[                 check if there is text after '
.                print first char of second part
[-<<+>>]         move char to the first part
>[.>]            print rest of second part
<[<]<            go to position of '
++++.----        use ' to print plus
[->+<]           move '
<[<]             go before beginning
]
>                 move back to beginning
if there wasn't text after ' move after end instead
]

• I think you can save 2 bytes by moving ' after printing the rest of the second part. May 9 at 20:24
• @Nitrodon Thank you, it saved even 3 bytes!
– Jiří
May 10 at 15:28

# Factor, 53 bytes

[ dup length [1,b] [ cut "'"glue ] with map "+"join ]


Try it online!

If the order of each product doesn't matter:

# Factor, 43 bytes

[ all-rotations [ 39 suffix ] map "+"join ]


Try it online!

## Explanation

                  ! "short"
all-rotations     ! { "short" "horts" "ortsh" "rtsho" "tshor" }
[ 39 suffix ] map ! { "short'" "horts'" "ortsh'" "rtsho'" "tshor'" }
"+"join           ! "short'+horts'+ortsh'+rtsho'+tshor'"


# Jelly, 14 bytes

J‘œṖ€j€”'j”+”'


Try It Online!

J‘œṖ€j€”'j”+”'  Full Program
J               [1, 2, ..., len]
‘              [2, 3, ..., len + 1]
œṖ€           For each of these, partition (*)
j€”'       Join each partition on ' (**)
j”+    Join on +
”'  An unparseable nilad forces the current string to be printed

(And then the ' is printed at the end)

(*)  partition takes a list on the left but since we give it a single number,
it auto-wraps it so we just get all needed splits
(**) the last partition only has one sublist so join doesn't work properly here


# Wolfram Language (Mathematica), 45 36 bytes

aRiffle[a/.#->#<>"'"&/@a,"+"]<>""


Try it online!

Input [{characters...}]. Assumes all characters in input are unique. Returns a string.

### Wolfram Language (Mathematica), 35 bytes

ToString@Expand[Dt[1##]/._@a_:>a']&


Try it online!

Input [symbols...]. Assumes symbols are unique and not defined. Returns a spaced string.

Dt treats strings as constants.

# JavaScript (Node.js), 83 $$\\cdots\$$ 72 69 bytes

s=>g=(r="",i=0)=>s[i]?g(r+("+"+s).slice(!i,++i+1)+"'"+s.slice(i),i):r


Try it online!

Saved 7 8 bytes thanks to emanresu A!!!
Saved 3 bytes thanks to Samathingamajig!!!

• r.join+ and s[i-1] I think May 7 at 23:44
• @emanresuA Very nice, this is my first JavaScript golf so thanks very much! :D May 7 at 23:51
• You might be able to save some more bytes by using a string for r although conditionally adding the + might cost more bytes than it's worth. May 7 at 23:52
• Maybe if you conditionally add the + and just return r at the end? May 8 at 0:17
• @emanresuA Found it! Thanks for the encouragement. :))) May 8 at 17:57

# JavaScript (Node.js), 46 44 bytes

l=>[...l].map(s=>l.replace(s,s+"'")).join+


Try it online!

-2 bytes thanks to emanresu A

• This answer only works with 'distinct alphabetical characters'. May 9 at 10:37
• Welcome to Code Golf, and nice first answer! Be sure to check out our Tips for golfing in Javascript page for ways you can golf your program! In particular, you're generally allowed to take input as a char array instead of a string, and .join('+') can become .join+ May 9 at 10:39
• @emanresuA The problem with "[taking] input as a char array instead of a string" is that .replace would be messed up. Is there another thing you're suggesting that will allow there to be less bytes with regards to the char array? May 9 at 19:22
• @Samathingamajig Oh, never mind :P May 9 at 19:43

# Retina, 15 13 bytes

L$|+.$>'$'  Try it online! -2 thanks to Neil. Match every character. For each one, take the text before the separator after the matched string, followed by an apostrophe, followed by the text after the matched string. Print as a list with separator +. • L$|+w. / $>'$' is 14 bytes. (But I didn't know you didn't need the ' before the +; that's only documented to work with ¶.)
– Neil
May 7 at 6:46
• Make that 13 bytes, because I forgot to remove the w.
– Neil
May 7 at 6:51

# Charcoal, 10 bytes

⪫⪪⪫Ｅθθ+Ｌθ'


Try it online! Link is to verbose version of code. Explanation: Port of @DLosc's Pip answer.

    θ       Input string
Ｅ        For each character
θ      Input string
⪫         Join on
+     Literal string +
⪪          Split into substrings of length
θ   Input string
Ｌ    Length
⪫           Join on
'  Literal string '
Implicitly print


# Husk, 14 12 bytes

J''CL¹J'+SRL


Try it online!

Same approach as DLosc's Pip answer.

# BQN, 28 bytesSBCS

{1↓⥊'''∾˘⟨∘,≠𝕩⟩⥊«⥊'+'∾˘⊢⌜˜𝕩}


Run online!

returns the required string with a trailing space. removing that is +3 bytes

-3 from ovs, who also made this tacit.

• ''' feels so cursed to me lol May 8 at 8:24
• save 1 byte by changing ⥊'+'∾˘𝕩⥊˜∾˜≠𝕩 to (∾'+'∾¨≠⥊⋈)𝕩. Still seems a bit awkward, though... May 8 at 10:05
• 𝕩⥊˜∾˜≠𝕩 can be ⊢⌜˜𝕩. Then tacit is the same length
– ovs
May 8 at 10:12

# Vyxal, 12 11 bytes

żƛ?n\'Ṁ;\+j


Try it Online!

## Explained

żƛ?n\'Ṁ;\+j
żƛ           # For each item P in the range 1...len(input):
?n         #   at position P in the input,
\'Ṁ      #   insert a '
;     # end map
\+j  # join the result of that on "+" and output

• I have a completely different 11 May 7 at 0:41
• interesting. I'm still golfing so maybe I'll break 12 May 7 at 0:42
• @emanresuA is that the 11 you had? May 7 at 0:47
• Yep :) - Maybe there's something better May 7 at 0:50
• A flag to make implicit stack pushing in lambdas use the input instead of lambda arguments would be useful May 7 at 2:01

# Bash, 83 bytes

v=$1\';until [$v = \'$1 ];do a+=+$v;v=$(sed "s/$$.$$'/'\1/"<<<$v);done;echo ${a#+}  Try it online! # K (ngn/k), 21 bytes Most straightforward K solution. {"+"/?[x;;"'"]'1+!#x}  Try it online! ### Explanation {"+"/?[x;;"'"]'1+!#x} ?[x;;"'"] / insert "'" in string at ' / each position 1+!#x / 1..len of string "+"/ / join the resulting strings with "+"  # C (gcc), 151 bytes char*f(char*c,int i){char*r=malloc(i*i+i);char*o=r,k=0;for(;k<i*i;){if(k++%(i+1)==1)*o++='\'';*o++=*c++;if(!*c)c-=i,*o++='+';}*o--=0;*o='\'';return r;}  Try it online! • 122 bytes May 8 at 20:08 # BQN, 21 bytesSBCS 1↓⟜∾'+'∾¨1↓↑∾⟜'''⊸∾¨↓  Run online! ↑ gives prefixes, ↓ suffixes. ∾⟜'''⊸∾¨ joins matching prefixes and suffixes with a single quote. 1↓ removes the first value (empty prefix ∾ ' ∾ full suffix). '+'∾¨ prepends a + to each string. 1↓⟜∾ joins the string and removes the leading +. • 20 bytes using Fold to join the string May 9 at 21:50 # R, 81 75 bytes Edit: -6 bytes thanks to Giuseppe function(x,[=substring)paste0(x[1,s<-1:nchar(x)],"'",x[s+1],collapse="+")  Try it online! Takes advantage of the vectorization of substring over a vector of start (& optional end) positions, and the vectorization & argument-recycling of paste over vectors of strings to paste-together. • 75 bytes May 10 at 16:04 • @Giuseppe - Ow. How on earth did I manage not to do that? Thanks. May 10 at 16:19 # Python, 47 bytes lambda s:"+".join(s.replace(c,c+"'")for c in s)  Attempt This Online! How it works: a b c d --> a' b c d a b c d --> a b' c d a b c d --> a b c' d a b c d --> a b c d' then join with '+'  # Retina 0.8.2, 14 bytes .$$&'$'+
.$ Try it online! Link includes test cases. Explanation: .$$&'$'+


Replace each variable with its derivative multiplied by the other terms plus a trailing + to sum the products together.

.$ Delete the final trailing +. # Jelly, 10 bytes ṛ€j”+sLj”'  Try it online! Port of DLosc's Pip solution.  € For each element of the input, ṛ the input. j”+ Join the copies on +, sL split into slices the length of the original input, j”' and join those on '.  # Jelly, 11 bytes p”'$ṛ¦ⱮJj”+


Try it online!

The implementation of ¦ is a bit questionable, so we can just abuse Cartesian product to make up for it.

p”'            Pair each element of the input with ',
$ṛ¦ and substitute elements of that into the input at ⱮJ each index, individually. j”+ Join the results on +.  Just for fun, without preserving the order within each term, ṭ-Ƥ”'ż@j”+ is 10. # PARI/GP, 58 bytes s->j=strjoin;j([j(strsplit(s,c),Str(c"'"))|c<-Vec(s)],"+") Attempt This Online! A port of @att's Mathematica answer. Takes input as a string. Requires that all characters are unique. ## PARI/GP, 64 bytes v->i=1;j=strjoin;j([j([j(v[1..i]),j(v[i++..#v])],"'")|c<-v],"+") Attempt This Online! Take input as a list of characters. # Julia, 40 bytes a->join([replace(a,i=>"$i'") for i=a],+)

Attempt This Online!

only works with all letters distinct

#### Why...how...what...

• [... for i=a] iterates over the string a and store the results in a list. i will be a Char
• replace(a, i=>"\$i'") replaces all characters equal to i in a with i followed by '
• join(..., +) joins the list with +. + is a function, so string(+) == "+" is used.
• Why...how...what... Can you remove the space between the ) and the for? May 9 at 9:31
• @emanresuA sadly no. It might have been possible in older versions of Julia May 9 at 9:48
• I will add an explanation May 9 at 9:49

# 05AB1E, 10 bytes

ε''«Nǝ}'+ý


Try it online!

ε       map each character (of the implicit input string)
''     the ' character
«      append to the current character
N      iteration index
ǝ      replace the input string's Nth character with the character with ' appended
}
'+      + character
ý       join by it

• Nice answer, +1 from me, but you forgot to remove the explicit Iy inside your TIO link. :) May 9 at 8:59

# Burlesque, 20 bytes

JiTjiS{''IC}Z[[-'+IC


Try it online!

J      # Dup
iT     # Tails
j      # Swap
{
''IC  # Intercalate "'"
}Z[    # Zip together then map
[-     # Drop head
'+IC   # Intercalate "+"


# SNOBOL4 (CSNOBOL4), 99 bytes

	I =INPUT
N	X =X + 1
I TAB(X) . L REM . R	:F(O)
O =O "+" L "'" R	:(N)
O	O TAB(1) REM . OUTPUT
END


Try it online!

# Javascript (Node.js), 114 bytes

function a(b){l=b.length;s="";for(i=1;i<=l;i++){if(i>1)s+='+';s+=b.substring(0,i)+"'"+b.substring(i,l);}return s;}


Try it online!

I forgot to add "+"

+10 characters to remove a trailing '+'

• slice instead of substring is shorter.
– m90
May 8 at 12:39