text:
How much code would a codegolf golf if a codegolf could golf code?
Write a function or program that takes two words as input and outputs variants of the popular English tongue-twister "How much wood would a woodchuck chuck if a woodchuck could chuck wood?".
The output will use the first word four times

How much wood would a woodchuck chuck if a woodchuck could chuck wood?

and the second word four times

How much wood would a woodchuck chuck if a woodchuck could chuck wood?

with the rest of the output being the same for any inputs.

How muchwoodwould awoodchuckchuckif awoodchuckcouldchuckwood?

The input and output can be in any format that your language reasonably recognizes as dealing with strings of text. The output must be exactly in the indicated format, including capitalization, spaces and lack thereof, and the ending question mark. An optional trailing newline is acceptable.
Ideally your code will handle input containing any printable ASCII characters. However, it is permitted to restrict the input to reasonable subsets of printable ASCII; just indicate this in your answer. Handling larger character sets is of course fine.
Example input-output pairs:
"wood", "chuck"
"How much wood would a woodchuck chuck if a woodchuck could chuck wood?"

"ground", "hog"
"How much ground would a groundhog hog if a groundhog could hog ground?"

"bar", "keep"
"How much bar would a barkeep keep if a barkeep could keep bar?"

"money", "belt"
"How much money would a moneybelt belt if a moneybelt could belt money?"

"rain", "fall"
"How much rain would a rainfall fall if a rainfall could fall rain?"

"hair", "cut"
"How much hair would a haircut cut if a haircut could cut hair?"

"green", "house"
"How much green would a greenhouse house if a greenhouse could house green?"

"jabber", "wock"
"How much jabber would a jabberwock wock if a jabberwock could wock jabber?"

"pine", "apple"
"How much pine would a pineapple apple if a pineapple could apple pine?"

"Rob", "Lowe"
"How much Rob would a RobLowe Lowe if a RobLowe could Lowe Rob?"

"code", "golf"
"How much code would a codegolf golf if a codegolf could golf code?"

"fish", ""
"How much fish would a fish  if a fish could  fish?"

"", "fish"
"How much  would a fish fish if a fish could fish ?"

"", ""
"How much  would a   if a  could  ?"

"  ", "     "
"How much    would a               if a         could         ?"

"would a", "how much"
"How much would a would a would ahow much how much if a would ahow much could how much would a?"

This is code-golf, so fewest bytes wins. Answers are welcome in all languages, even if some other language can do it in fewer bytes.
(Inspired by this meme, which uses one input pair better than this rigid pattern does....)

May we assume the two words will be two distinct words?

...I guess "", "" means no :p

@dzaima Edited to clarify. I don't want the input character set to be the main focus, so I'll trust golfers for the most part.

IMHO I think a) the phrase doesn't make sense with "could", since maybe it wouldn't anyway b) you really need the homophone.

How reasonable is "reasonable"?

Is input allowed to be taken in reverse order: e.g. 'chuck' 'wood'?

I am mildly disappointed that none of the test cases were "ground", "hog" (since "woodchuck" is another name for a "groundhog"...)

@Chronocidal I can't stand to see you disappointed....

@maxb I guess I don't see any reason to disallow the "wrong" order for inputs ... a tiny bit confusing maybe, but just saying so in the answer seems like enough to me.

Two. It would golf two code.

Aw, I was hoping this would be about a short program that can do some simple golfing transformation(s) on other code.

I am going to have the "jabber", "wock" one stuck in my head, now.

It doesn't quite fit the pattern, but I'm fond of "How many dice would a dyed die dye if a dyed die could dye dice?"

Shouldn't the invariant space between "chuck" and "wood" in the example's third form also be code-quoted?

"How much would a would a would ahow much how much if a would ahow much could how much would a?" - ROFL

Python 3, 70 67 bytes
"How much {0} would a {0}{1} {1} if a {0}{1} could {1} {0}?".format

Try it online!
I mean, if the shoe fits..
Thanks to manatwork for catching a typo
Thanks to Remco Haszing for the excellent -3 bytes idea
I am running off of the assumption that this would still be a valid submission (because man, it's too cool not to try). If OP could clarify whether this is acceptable (because I haven't written a function, per se), that would be appreciated.
Update: Blessing received, all is good :)

Previous version:
lambda a,b:f"How much {a} would a {a+b} {b} if a {a+b} could {b} {a}?"

Maybe irrelevant, but the automatic format string is not readily available in python versions prior to 3.6

@M.Herzkamp So?

@ruohola I think M.Herzkamp is trying to say the title to this answer should be "Python 3.6" rather than "Python 3".

Even shorter and Python 2 compatible (67 bytes): "How much {0} would a {0}{1} {1} if a {1}{0} could {1} {0}?".format. This returns a function bound to the unformatted string.

I'm no Python expert, but since print("How much {0} would a {0}{1} {1} if a {0}{1} could {1} {0}?".format("wood","chuck")) generates the desired output, I see no reason not to accept it :)

T-SQL, 82 bytes
SELECT'How much '+w+' would a '+w+c+' '+c+' if a '+w+c+' could '+c+' '+w+'?'FROM t

Input is taken from pre-existing table \$t\$ with columns \$w\$ and \$c\$, per our IO rules.
One byte longer, but for some reason slightly more pleasing:
SELECT REPLACE(REPLACE('How much 1 would a 12 2 if a 12 could 2 1?',1,w),2,c)FROM t

This version works on a subset of inputs that don't include the numeral 2 in the first word \$w\$.
Because I'm in SQL, I can pre-load all examples into the table, and run them all at once:

+1000000 virtual trains for megatrain

I assume that "w" and "c" stand for "wood" and "chuck" respectively :P

This can be done in 67 bytes in Oracle as called from SQL*Plus (so no table): select'How much &1 would a &1&2 &2 if a &1&2 could &2 &1?'from dual

Bash, 50 bytes
echo How much $2 {would,$1\ if}\ a\ $2$1 could $@?

Try it online!
-5 bytes due to help from comments below.

-3 bytes

-2 bytes more

@NahuelFouilleul: Your edits are clever, but they require reversing the order of the input parameters from the original challenge.

@Grimy: A good use of $@, but it requires reversing the order of the input.

You added an unnecessary backslash when adapting Nahuel's golf. Here's 53.(Though really it should be 50, nothing stops you from taking the first word as $2 and the second word as $1.)

@Grimy: I see the comment on the challenge from original poster allowing the reversing of the parameters. I'm updating the answer to the excellent answer of 50 bytes. Thanks!

Could you please elaborate how this works? The brace expansion and backslashes are doing my head in!

@roblogic: The backslashes quote the spaces to avoid word splitting on the spaces, and the curly braces are expanded twice to form two words, once with each string inside the braces, and the characters that trail the braces (but part of the word) are added to the end of each string. Adding square braces to help visualize the word splitting: “[a{bc,de}f]” becomes two words: “[abcf] [adef]”. So “[{would,$1\ if}\ a\ $2$1]” becomes “[would\ a\ $2$1] [$1\ if\ a\ $2$1]”

Stax, 33 31 30 29 bytes
-1 thanks to recursive!
¢èO∩sP↑å♥|1╧ì}ò♂xb■δå«█Γ╨╦►Q²

Run and debug it at staxlang.xyz!
Push each component to the stack in reverse order, then join all with spaces.
Unpacked (35 bytes) and explanation:
X'?+;`IM'`x;+Y`~^$`,y`75\`x`Q)("`LJ
X                                      Set register X to the first word
                                       "wood"
 '?+                                   Append a question mark, popping from the input stack
                                       "wood?"
    ;                                  Peek from input stack and push to main stack
                                       "chuck" "wood?"
     `IM'`                             Literal "could"
                                       "could" "chuck" "wood?"
          x;+Y                         Peek register x. Peek input. Concatenate. Set register Y.
                                       "woodchuck" "could" "chuck" "wood?"
              et cetera, ad nauseam
                                  LJ   Listify the stack and join with spaces
                                       Implicit print

Everything between `` is compressed string literal. That comma is vital. The last time I read from the input stack, I must pop rather than peek to avoid an extra "chuck" on the end of my output.
You'll notice that I put both inputs on the same line for a few test cases, and that they're in reverse order. This is necessary in order to take empty strings or strings of spaces as input.
27 26 bytes with restrictions on input
å▓Zf╢7)╪♪²p╞8ó╪l▼]<¡REïSèΣ

Run and debug it at staxlang.xyz!
Just like @dzaima's SOGL, this will fail if the first input contains the lowercase letter 'y'. Pushes the string "How much b would a by y if a by could y b?", then makes a pair of replacements.

"You'll notice that I put both inputs on the same line for a few test cases, and that they're in reverse order. This is necessary to take empty strings or strings of spaces as input."
If you use no input separator, the input will be undisturbed, empty strings and all.  It just makes it kind of awkward to show multiple test cases.

Additionally, it seems the leading , in your 31 byte solution can be removed.  The following + implicitly pops from the input stack, so the behavior is identical.

JavaScript, 70 bytes
Boring!
a=>b=>`How much ${a} would a ${a+b} ${b} if a ${a+b} could ${b} ${a}?`

Try it online!
Mildly less boring!
a=>"How much 0 would a 01 1 if a 01 could 1 0?".replace(/\d/g,x=>a[x])

Try it online!

Are you allowed to output a curried function like in that first example?

@Feathercrown, I'm not outputting a function, I'm calling both (e.g., f(a)(b)) as you can see in the TIO. But yes, our consensuses to allow curried functions and I think we're close to a consensus on allowing a function to actually be returned.

By output I meant the code returns a function when evaluated; no calling is in the given code that counts for bytes. I was just checking to make sure currying was okay, since I've only ever seen noncurried functions returned.

SOGL, 32 30 bytes
^.](9V;⅜‛°@Ε¬tπs%.½Ω‘⁽ b,ŗ y,ŗ

Try it here!
The first input can't contain the letter y, which seems to leave a reasonable subset of ASCII (and unicode) left.
½ouiīZģ9Ο|ΧyΚ⅞ō÷Jeq(‚7‘ is a compressed string of "how much b would a by y if a by could y b?" (characters chosen so the required words are all in the top 512 words of the dictionary which compress better), then b is replaced with the 1st input and y with the 2nd.

+2 internet points for one of the most random restrictions I can remember (in your shorter solution)

@GregMartin Not that random. I don't speak SOGL, but I ended up with the same restriction on 'n' when sequencing two replacements y -> wood and n -> chuck. A tenth of a Dignity Point says that's the case here as well.

I think the main spirit of this question is to be open about allowing solutions ... only as an aside might I opine that not allowing an actual letter in an input is a bit sketchy. Anyway: why is b not allowed in the first input yet e is ok in the second input?

@GregMartin whoops, I meant to say that the 1st input can't contain e, as otherwise it'd be replaced with the 2nd input in the 2nd replacement

Is it not possible for replacement target to be non-alpha to avoid having to ban an alpha from the input?

@WGroleau I do have 36 bytes with the forbidden character being ")", but as can be seen, that's 4 bytes longer because b and be are in the top 512 words, which compress better

@WGroleau writing that, I finally understood why it was so better - I had thought that SOGL compressed the top 256 words, but the top 512 also has the letter "y", so that's another -2

In English, the letters ‘e’ and ‘t’ are the two worst to forbid.  ‘y’ is way down the list.

R, 90 77 76 bytes
-13 thanks to Sumner18
-1 thanks to Giuseppe

function(x,y,`[`=gsub)2[y,1[x,"How much 1 would a 12 2 if a 12 could 2 1?"]]

Try it online!

Can do a double gsub for -13 bytes instead. https://tio.run/##Nc2xDoMgEIDhvU9xYZKEDjg36dqhU98A8FAqckYl6NNbFLvdffkvN@0WHvfdxmAWR6FaxcbbOeqqFps4BylWwV6UYIimAwmJom9AgayhBmfLZE6sQT4Z57utWCJqmGCmi6Zn/JZFqylDjziWfaCAWxaNfikyKRcyWOV9gU6548bEK2gnxKPoKM5Y6Ku0xiNK9H80uoAZ1Dj6K/qQzvCmdO2GmqNoyVvG9x8

@Sumner18 Thanks. Yeah, gsub definitely makes more sense.

If you feel like using pryr, you can get it down to 73.

You should specify that you assume the input x doesn't include the character 2; it fails in this case (TIO).

76 with aliasing of gsub

ZX Spectrum Basic, 87 bytes
Just for completeness, straightforward implementation:
INPUT a$,b$: PRINT "How much ";a$;" would a ";a$;b$;"  ";b$;" if a ";a$;b$;" could ";b$;" ";a$;"?"

Using the IF keyword (1 byte) golfes it down by 3 bytes, but breaks the "same capitalization" condition:
INPUT a$,b$: PRINT "How much ";a$;" would a ";a$;b$;"  ";b$;" IF a ";a$;b$;" could ";b$;" ";a$;"?"

It's nice to show slightly-cheaty versions too :)

Oh, Speccy! To be young again...

Kotlin, 59 bytes
{i,j->"How much $i would a $i$j $j if a $i$j could $j $i?"}

Try it online!

Kotlin sounds like a lot of fun!

@M.Herzkamp it sure is!

PHP, 72 bytes
[,$a,$b]=$argv;echo"How much $a would a $a$b $b if a $a$b could $b $a?";

Try it online!
Or:
PHP, 72 bytes
How much <?=![,$a,$b]=$argv,"$a would a $a$b $b if a $a$b could $b $a?";

Try it online!
Input from command line, output to STDOUT.

JavaScript (V8), 72 bytes
(a,b)=>['How much',a,'would a',c=a+b,b,'if a',c,'could',b,a+'?'].join` `

Try it online!
The variable assignment actually saves 0 bytes, but I figured I'd keep it in just to make this slightly unique.

But one big template string is 1 character shorter: Try it online!.

@manatwork I tried this but included an extra space by mistake :P Thanks!

05AB1E, 37 35 31 30 bytes
“Howƒ×1€Þ a ÿ0€¬ a ÿƒˆ01?“T$ú‡

Try it online or verify all test cases.
Or alternatively:
…a ÿªðì₁“Howƒ×2€Þ65€¬6ƒˆ52?“r‡

Try it online or verify all test cases.
-5 bytes thanks to @Grimy.
Takes a list of two items, wood as first value and chuck as second.
Explanation:
“Howƒ×1€Þ a ÿ0€¬ a ÿƒˆ01?“
        # Push dictionary string "How much1 would a ÿ0 if a ÿ could01?",
        # where the `ÿ` are automatically filled with the (implicit) input-list,
        # implicitly joined together to a single string
        #  i.e. ["wood","chuck"] → "How much1 would a woodchuck0 if a woodchuck could01?"
T       # Push 10
 $      # Push the input-list and 1
  ù     # Pad the strings in the input-list with this 1 amount of leading spaces
        #  ["wood","chuck"] → [" wood"," chuck"]
   ‡    # Transliterate the 10 ([1,0]) to these strings in the sentence
        #  → "How much wood would a woodchuck chuck if a woodchuck could chuck wood?"
        # (after which the result is output implicitly)

…a ÿ    # Push dictionary string "a ÿ",
        # where the `ÿ` are automatically filled with the (implicit) input-list,
        # implicitly joined together to a single string
        #  i.e. ["wood","chuck"] → "a woodchuck"
    ª   # Append this to the (implicit) input-list: ["wood","chuck","a woodchuck"]
     ðì # Prepend a space before each string: [" wood"," chuck"," a woodchuck"]
₁       # Push builtin 256
“Howƒ×2€Þ65€¬6ƒˆ52?“
        # Push dictionary string "How much2 would65 if6 could52?"
r       # Reverse the values on the stack
 ‡      # Transliterate [2,5,6] to [" wood"," chuck"," a woodchuck"] in the string
        #  → "How much wood would a woodchuck chuck if a woodchuck could chuck wood?"
        # (after which the result is output implicitly)

See this 05AB1E tip of mine (section How to use the dictionary?) to understand why “Howƒ×1€Þ a ÿ0€¬ a ÿƒˆ01?“ is "How much1 would a ÿ0 if a ÿ could01?" and “Howƒ×2€Þ65€¬6ƒˆ52?“ is "How much2 would65 if6 could52?".

31

30

@Grimy Very nice! I really like both of those. Ingenious idea of using the $ù like that to save the additional byte, thanks.

Alternate 30. I'm not finding any 29, so your explanation is safe for now ;)

33, 78 bytes
"How much "p1btpt" would a "ptpz2btp" "ptbtp" if a "ptpbtp" could "ptbtp" "ptp

Try it online!
Takes the input as command-line arguments.
Bonus: 91 bytes
"How much "p1bztp" would a "p1bztp2bztp" "p2bztp" if a "p1bztp2bztp" could "p2bztp" "p1bztp

Try it online!
Gives output resembling itself when given inputs 1bztp and 2bztp

Said this out loud, now I need to clean all the spit off my monitor.

Rust, 75 bytes
|a,b|print!("How much {} would a {0}{} {1} if a {0}{1} could {1} {0}?",a,b)

Try it online!
Using this trick, which let's you skip the formatting index once per item to format.
Also using print!(), because it's one byte shorter than building a string with format!() and returning it.

Applesoft BASIC, 77 76 bytes
1INPUTA$,B$:?"How much "A$" would a "A$B$" "B$" if a "A$B$" could "B$" "A$"?

The above may not look like proper BASIC, but Applesoft allows for a few shortcuts when using the PRINT statement:

Use of ? in place of PRINT when entering the statement
Concatenation characters (either ; or +) may be omitted
If the statement ends in a quoted string, the final quote may be omitted Thanks, Mark!

The line number is required, or the INPUT statement will cause an ?ILLEGAL DIRECT ERROR

Can you omit the trailing quotation mark?  Applesoft Basic is a Microsoft Basic derivative, and many versions of Microsoft Basic let you omit the closing quote on a string if it ends the line.

@Mark, Thanks for tip!

PowerShell, 65 bytes
param($a,$b)"How much $a would a $a$b $b if a $a$b could $b $a`?"

Try it online!
The only thing of note is that you have to escape the question mark because those can be valid parts of a PowerShell identifier

C#, 165 148 133 bytes
class P{static void Main(string[]a){System.Console.Write("How much {0} would a {0}{1} {1} if a {0}{1} could {1} {0}?\n",a[0],a[1]);}}

Thanks to Andrew Baumher for telling me about interpolated strings!!
EDIT: Full class now addedEDIT: Thanks to Kenneth K. for giving me a few tips for shortening itEDIT: Thanks to Andrew again for telling me that using interpolated string is actually longer in this scenario.

Using modern C#'s '$' (interpolated strings), you can save a few bytes by replacing {0} with {a[0]}, or better yet, taking two variables instead of an array so you can just use a and b. So as to not steal your thunder, so to speak, I'll add it as a different version of c#

Wow didn't know about that! Thanks for the info

@canttalkjustcode generally, functions are accepted. For C#, this includes lambdas: a=>System.Console.WriteLine($"How much {a[0]} would a {a[0]}{a[1]} {a[1]} if a {a[0]}{a[1]} could {a[1]} {a[0]}?")

This IS true but it's only in C# Interactive that you can use lambda expressions like this. In full C# you need a full lamda statement. A simple void statement would be faster as shown in the following snippet:

void M(string[]a){System.Console.WriteLine($"How much {a[0]} would a {a[0]}{a[1]} {a[1]} if a {a[0]}{a[1]} could {a[1]} {a[0]}?");}
System.Func<string>M=a=>System.Console.WriteLine($"How much {a[0]} would a {a[0]}{a[1]} {a[1]} if a {a[0]}{a[1]} could {a[1]} {a[0]}?");
System.Action<string>M=a=>System.Console.WriteLine($"How much {a[0]} would a {a[0]}{a[1]} {a[1]} if a {a[0]}{a[1]} could {a[1]} {a[0]}?");

And to as why I am doing classes instead of functions? Just because most people using C# on this site do it too. Its just to keep fair competition

@JoKing It takes it from standard input.

int M instead of void M saves you a byte. And you don't need the public--neither class nor function. Also, Console.Write with a trailing \n saves a couple of bytes.

But int M requires me to have a return value right?

Ooh, sorry, you're correct.

Learned about interpolated strings from other code golfers myself, actually. Just doing my part, i guess, lol. Though if you're using a[0] and a[1], it might actually be shorter to use {0} and {1}. You'll save 24 bytes in the text section, then lose 10 bytes defining those values, for a net gain of 14. It works better with single character variables.

It's crazy. Have learned so much on this site in 3 days. Using {0} and {1} is indeed shorter. Why did the byte count decrease in the first place then?

VBA, 107 bytes
Function q(a,b)
b=b&" "
c="ould "
q="How much "&a&" w"&c&"a "&a&b&b&"if a "&a&b&"c"&c&b&a&"?"
End Function

Should run as VBScript too, I used two shortcuts: "ould " is repeating and "chuck" never appears without an additional space.

You can get this down to 75 bytes by converting to immediate window function as a=[A1]:b=[B1&" "]:o="ould ":?"How much "a" w"o"a "a b b"if a "a b"c"o b a"?. Takes input from [A1] and [B1]. We have Tips for golfing in VBA that you consider taking a look into.

Then you could take input named range [A] and [B] as inputs bringing it down to 73. I don't quite understand how yours goes through though, feel free to add your own answer.

That unfortunately goes against how STDIN and STDOUT are defined for Excel VBA - you can use any unnamed range on the activesheet, but are not permitted to use named ranges per an earlier decison by the community

Haskell, 76 bytes
a?b=a++" "++b
a!b="How much"?a?"would a"?a++b?b?"if a"?a++b?"could"?b?a++"?"

Try it online!
First try, so I hope I didn't break any rules.

Python 3, 80 bytes
lambda n:'How much {0} would a {0}{1} {1} if a {0}{1} could {1} {0}?'.format(*n)

Try it online!
when in rome, use str format.
Edited using squid's trick.

Wouldn't this be invalid? It's a snippet - not a function or a program, right?

Yeah; needs a lambda n: before it, and can drop the print().

You should change your code to print How much ... instead of how much ....

It should suffice to just define an anonymous function as 'how much {0} would a {0}{1} {1} if a {0}{1} could {1} {0}?'.format.

@xnor Still pretty new, what would the TIO look like for that then? I'd think that without some way to pass in an arg it would be runnable.

@Tryer Try it online!, see also my tip about object methods

I didn't even know you could define a function in that way to have it take arguments without using lambda. Thank you!

C# (Visual C# Interactive Compiler), 66 65 bytes
x=>y=>$"How much {x} would a {x+y} {y} if a {x+y} could {y} {x}?"

Try it online!
same as everyone else, except C#.
-1 byte by using currying strat a=>b=>c instead of (a,b)=>c

Change function signature from Func<string,string,string> to Func<string,Func<string,string>> and change (x,y) to x=>y=>

Seems like a cheap tactic, but meta discussion says it's fair game, so might as well. Thanks.

Jelly, 39 bytes
ŒPKŒP“µkþ¿µ‘ị“þ>Æƈ)taJṖ;ạʂ\4S%dñl»Ỵ¤ż”?

A full program accepting a list of two strings.
Try it online!
...Or (also a full program accepting a list of two strings)
⁽4ṀDBịs€2ṭ€€⁶“þ>Æƈ)taJṖ;ạʂ\4S%dñl»Ỵ¤ż”?

Try it online!

Wolfram Language (Mathematica), 68 bytes
StringRiffle@{How,much,#,would,a,c=#<>#2,#2,if,a,c,could,#2,#<>"?"}&

Try it online!

# C (clang), 78 bytes
#define f(a,b)"How much "#a" would a "#a#b" "#b" if a "#a#b" could "#b" "#a"?"

Try it online!
Using stringification

C (gcc), 85 bytes
f(a,b){printf("How much %s would a %s%s %s if a %s%s could %s %s?",a,a,b,b,a,b,b,a);}

Try it online!
Thanks to @ErikF suggestion to use gcc, btw I've seen that clang accepts f(*a,*b){ // which is 2 Bytes expensive anyway
Saved 2 thanks to @ceilingcat.

For the second submission, if you use gcc instead of clang you can remove the parameter types (85 bytes): Try it online!

You could also use printf positional arguments TIO (but it's still 85 bytes). Oh well.

R, 95 bytes
function(a,b)cat("How much ",a," would a ",a,b," ",b," if a ",a,b," could ",b," ",a,"?",sep='')

Try it online!

Welcome to the site! Your TIO link seems to link to the wrong code? In addition, as far as I can tell, you've assumed the input to be in the variables a and b, which is disallowed under our Default Input/Output rules

Thanks @cairdcoinheringaahing for the comment. I rewrote it in function form, hope it complies with the rules now.

Using stringr saves you a few.

APL (Dyalog Unicode), 56 59 bytes
{∊'How much '⍺' would a '⍺⍵' '⍵' if a '⍺⍵' could '⍵' '⍺'?'}

Try it online!
Pretty straightforward dfn. Saves a byte by cutting ∊ if we're allowed to return an array of strings instead of a single string.
3 bytes added because I'd forgotten to add the question mark.

Did you count the Greek letters as one byte?

@TomášZato yes. Dyalog APL's glyphs can be represented in a single byte using Adám's Single Byte Character Sheet which is standard for APL answers here.

Japt -S, 44 39 bytes
[`How Û2`U`Ùd a`N=¬V`if a`N`Öd`VU+'?]

Try it

Jelly, 41 37 bytes
⁾be,y“Ø[gœıJ9°m.OṚuHlh3Ƥ⁾$ɲ0øḲʂṇHẎṆȥ»

Try it online!
A full program taking a pair of strings as its argument and printing the processed string. A monadic link could be formed by adding a F to the end (thanks to @JonathanAllan for pointing this out).
I’ve now switched to using "b" and "e" as placeholders, inspired by @dzaima’s SOGL answer so be sure to upvote that one too! This does mean that the first word can’t include the letter e.

Forth (gforth), 116 bytes
: x 2over type ; : y 2dup type ; : f ." How much "x ."  would a "x y ."  "y ."  if a "x y ."  could "y ."  "x ." ?";

Try it online!
Code Explanation
\ x = output the first word
: x               \ start a new word definition
  2over type      \ copy the "first" word to the top of the stack and print it
;                 \ end word definition

\ y = output the second word
: y               \ start a new word definition
  2dup type       \ copy the "second" word to the top of the stack and print it
;                 \ end word definition

: f               \ start a new word definition
  ." How much "x  \ print "How much " followed by the first word
  ."  would a "x  \ print " would a " followed by the first word
  y ."  if a "x   \ print the second word followed by " if a " and then the first word
  y ."  could "y  \ print the second word, then " could " then the second word again
  ."  "x ." ?"    \ print a space followed by the first word, followed by "?"
;                 \ end word definition

Lua, 82 bytes
a,b=...print((('How much x would a xy y if a xy could y x?'):gsub('.',{x=a,y=b})))

Try it online!
Full program, take input as arguments.
Nothing special here. Hope that there's shorter version, but no obvious ways to shorten this at first glance.

Bash, 58 bytes
echo "How much $1 could a $1$2 $2 if a $1$2 could $2 $1?"

Takes input as command line arguments.
Try it online!

Batch, 56 bytes
@echo How much %1 would a %1%2 %2 if a %1%2 could %2 %1?

Python 3, 67 bytes
'How much {0} would a {0}{1} {1} if a {0}{1} could {1} {0}?'.format

Try it online!
Point-free Python

Welcome to the site! I'd recommend you add a link to an online interpreter (like Try it online!), so that others can verify your program!

Thanks for the suggestion/link @cairdcoinheringaahing. I added the link, and I'll spend some time to familiarize myself with TIO.

Perl 5, 56 bytes
/ /;$_="How much $' would a $'$` $` if a $'$` could $_?"

Try it online!

PHP, 61 bytes
<?=strtr('How much 1 would a 12 2 if a 12 could 2 1?',$argv);

Try it online!
Taking advantage of PHP's strtr array replacement mode. In strtr, when second parameter is an array, it replaces array keys with the corresponding value for that key.
PHP's $argv index/key 0 is always filled by PHP and starting from index 1, command line arguments are put in it. So I pass the two words as command arguments which will be placed at index 1 and 2 in $argv and then the 1s and 2s in the string will be replaced by those values.

PHP (7.4), 62 bytes
fn($a)=>strtr('How much 0 would a 01 1 if a 01 could 1 0?',$a)

Try it online!

PHP (7.4), 63 bytes
fn($a,$b)=>"How much $a would a $a$b $b if a $a$b could $b $a?"

Try it online!

Ruby, 69 71 bytes
->a,b{"How much #{a} would a #{a+b} #{b} if a #{a+b} could #{b} #{a}?"}

Try it online!

I'm afraid you misread the challenge. The 1st modal verb is “would”.

Noooooo my beautiful byte saves...

Canvas, 42 40 39 bytes
；⁸⁸⁷⁷“UＮｑＯ1Uŗ７_ＷW７eV↷:７⁹`3ｕ5G!oａ⁷⁴ｄ：⌐Ｑ‟

Try it here!
Canvas's compression unfortunately currently doesn't have an English dictionary mode as I'm lazy.

Pyth, 49 bytes
AQjd["How much"G"would a"J+GHH"if a"J"could"H+G\?

Try it online!
AQ:  Take the two-element list Q (input) and assign the first element to G, the second to H
jd:   join on d (=" ") the following list
[:    starts list definition, ends implicitly with the end of the program.
      All following values are elements of the list
J+GH: concatenate G and H so it won't be joined with a space between, save it to J
\?:   One-character string consisting of "?"

Red, 77 bytes
func[a b][rejoin["How much "a" would a "a b" "b" if a "a b" could "b" "a"?"]]

Try it online!

Excel, 79 bytes
=SUBSTITUTE(SUBSTITUTE("How much 0 would a 01 1 if a 01 could 1 0?",0,A1),1,A2)

Simple substitution.  First string cannot contain 1.

As it turns out, this is the same length as the more straightforward approach which has no restrictions on input: ="How much "&A1&" would a "&A1&A2&" "&A2&" if a "&A1&A2&" could "&A2&" "&A1&"?"

Not if you use named ranges A and B. ="How much "&A&" would a "&A&B&" "&B&" if a "&A&B&" could "&B&" "&A&"?"

@user3819867, would that not be ="How much "&A:A&" would a "&A:A&B:B&" "&B:B&" if a "&A:A&B:B&" could "&B:B&" "&A:A&"?"

Named range, you can define the name in names manager (Ctrl+F3). You can enter any non-reserved string, including 1 char length.

Have toyed with named ranges before.  Don;t think its in the spirit of CodeGolf.  Do we add bytecount for the naming?

Dart, 61 bytes
f(a,b)=>"How much $a would a $a$b $b if a $a$b could $b $a?";

Try it online!

You can move the function name to the header and omit it from the byte-count.

@Oliver I'm curious where this has been specified, I haven't read anything regarding that anywhere and always assumed function names had to be included

Anonymous functions are accepted by the community, unless the challenge specifies otherwise

Scala, 74 bytes
(a:String,b:String)=>s"How much $a would a $a$b $b if a $a$b could $b $a?"

Try it online!

MathGolf, 40 bytes
▌_l@lll╩Bßx¬╩5╩♦Γ╫¬╩-╩♦?ß¬╩à╩e?ß¬]─ uδ'?

Try it online!
Probably suboptimal. Relies on manipulating the stack, and generating the sentence starting from the end. I might write an explanation if someone really wants it, nothing magic is happening.

Java (JDK), 76 bytes
a->b->"How much "+a+" would a "+a+b+" "+b+" if a "+a+b+" could "+b+" "+a+"?"

Try it online!

Emacs Lips, 79 bytes
(lambda(a b)(concat"How much "a" would a "a b" "b" if a "a b" could "b" "a"?"))

Perl 5 -pa, 61 bytes
$_="How much 0 would a 01 1 if a 01 could 1 0?";s/\d/$F[$&]/g

Try it online!

Julia 1.0, 56 bytes
a/b="How much $a would a $a$b $b if a $a$b could $b $a?"

Try it online!

Clojure, 102 bytes
(#(println"How much"%1"would a"(str %1%2)%2"if a"(str %1%2)"could"%2(str %1\?))(read-line)(read-line))

Try it online!

Python 2, Python 3 - 78 bytes
lambda a,b:' '.join(('How much',a,'would a',a+b,b,'if a',a+b,'could',b,a))+'?'

Try it online!
no format strings, a tad shorter than @Tryer 's format

V (vim), 46 bytes
iHow much ò would a aò b if a òò could b ò?

Try it online!
Hexdump:
00000000: 6948 6f77 206d 7563 6820 f220 776f 756c  iHow much . woul
00000010: 6420 6120 1261 f220 1262 2069 6620 6120  d a .a. .b if a
00000020: f2f2 2063 6f75 6c64 2012 6220 f23f       .. could .b .?

AWK, 64 bytes
$0="How much "$1" could a "$1$2" "$2" if a "$1$2" could "$2" "$1

Try it online!
I tried being clever with string substitutions and/or print statements, but I couldn't make it shorter.

SAP ABAP, 95 bytes
FORM f USING a b.WRITE:'How much',a,'would a',a && b,b,'if a',a && b,'could',b,a &&'?'.ENDFORM.

Input should be of type string to preserve spaces/not add any extra ones. Example program:
REPORT z.
PARAMETERS:
    a TYPE string LOWER CASE,
    b TYPE string LOWER CASE.
PERFORM f using a b.

Rather boring code, not much to golf. Removing spaces where they are not needed. String concatenation using a && b is obviously shorter than doing a NO-GAP,b.
While modern ABAP can do string interpolation (WRITE:|{ a } { b }|.), it doesn't save a single byte, because as per usual there are too many mandatory spaces. The boring alternative (WRITE:a,b.) even implicitly appends a space to the output after each ,, making  the choice an easy one...
For comparison:
WRITE:|How much { a } would a { a }{ b } { b } etc...|.
WRITE:'How much',a,'would a',a && b,b,'etc...'

I could lose 10 bytes here if it's legal to use the variables defined in the surrounding program (this allows me to remove USING a b). But then my subroutine depends on the correct naming of these two variables in the calling program, which leads me to believe that it's probably not allowed.


text:
Church Booleans
Church booleans
A Church boolean is a function that returns x for true and y for false where x is the first argument to the function and y is the second argument to the function. Further functions can be composed from these functions which represent the and not or xor and implies logical operations.
Challenge
Construct the Church booleans and and not or xor and implies Church gates in a language of your choice. and or and xor should take in two functions (representing Church booleans) and return a function (representing another Church boolean). Likewise, not should invert the function it takes and the implies gate should perform boolean implies logic where the first argument implies the second.
Scoring
The total length of all of the code required to make Church true and false in your language and the and not or xor and implies Church gates excluding the function's name. (for example, false=lambda x,y:y in Python would be 13 bytes). You can reuse these names later in your code with them counting 1 byte toward the byte total of that gate.
Pseudo code Examples:
The functions you create should be able to be called later in your code like so.
true(x, y) -> x
false(x, y) -> y
and(true, true)(x, y) -> x
and(true, false)(x, y) -> y
# ... etc

Do we have to treat the function inputs (or closest substitutes) as black-box functions, or can we inspect the code within? And must the return values of the logical operations be the same functions as previously defined as the Church booleans, or can they be something else which does the same thing?

@UnrelatedString the inputs to the function are essentially a cat program that copy input to output, but based on if they are true or false. For example, a true church boolean takes in two inputs (which chould be "foo" and 3, basically anything) and returns the first argument ("foo"). They don't have to be the exact functions you previously described, but I would imagine it would save a lot of space if you did this.

@JonathanAllan I added it later, and I am regretting it. I should've just kept it to purely gates.

@JonathanAllan I edited it so it was correct. The prompt is as it should be now.

Can we take lists as arguments (e.g. true([x, y]), and([true, true])([x, y]))?

@ar4093 I am going to rule no as technically this isn't true to the underlying lambda calculus in this question. The proposed functions you have take in 1 argument not 2 like a true Church Boolean.

@ar4093 FWIW, I don't see any fundamental problem with saying "Define an N-ary _F_unction as a unary function whose argument must be a list of N items. Then the _F_unctions corresponding to the Church booleans are..." I mean, the top-voted Haskell answer already exploits currying ("Define a 2-ary _F_unction as a unary function which returns a unary function. Then the _F_unctions corresponding to the Church booleans are..."). Sometimes currying is idiomatic; sometimes taking-a-list-of-args is idiomatic. And heck, sometimes golfed solutions are unidiomatic. ;)

@RyanSchaefer I think you should reconsider allowing the arguments to be in an ordered list, as one could simply wrap the arguments at the beginning of the solutions. I don't think that requiring that does anything to improve this challenge (in fact I think it limits interesting golfing potential). Of course, this is just my opinion, and it is fine if you do not agree.

Please can you double-check the score on my Node.js answer as three people have now disagreed with my understanding of your paragraph on scoring.

The scoring is rather confusing. Wouldn't it be better to let people submit anonymous functions, but if they use them in other parts they have to assign them, just like usual

@JoKing I’ve stated my opinion that i would change the scoring if I could but it’s too late now because of all the answers.

FWIW, even though I see a lot of people apparently confused about the scoring, I think the rule is great. The rule recognizes that any identifier can be golfed down to one byte, so it doesn't penalize people for using nice function names like true, false, xor. (OTOH, it makes it harder to count bytes because the code whose bytes you count is hardly ever the same as the code that you run. So that's a downside.)

Binary Lambda Calculus, 13.875 12.875 bytes (103 bits)
Binary Lambda Calculus Language (BLC) by John Tromp is basically an efficient serialization format for lambda calculus. It is a great fit for this task, as Church notation is even the "idiomatic" way to work with booleans in BLC.
I used the following lambda functions for the combinators, some of which I copied and golfed from the Haskell answer:, which were found by an exhaustive search with a proof limit of 20 β-reductions for each case. There is a good chance these are shortest possible.
True:  (\a \b a)
False: (\a \b b)
Not:   (\a \b \c a c b)
And:   (\a \b b a b)
Or:    (\a a a)
Xor:   (\a \b b (a (\c \d d) b) a)
Impl:  (\a \b a b (\c \d c))

These translate to the following (binary) BLC code sequences:
 bits |  name | BLC
------+-------+---------
    7 | True  | 0000 110
    6 | False | 0000 10
   19 | Not   | 0000 0001 0111 1010 110
   15 | And   | 0000 0101 1011 010
    8 | Or    | 0001 1010
   28 | Xor   | 0000 0101 1001 0111 0000 0101 0110
   20 | Impl  | 0000 0101 1101 0000 0110

Functions above are in total 111 bits long (13.875 bytes) 103 bits long (12.875 bytes). They don't need to be aligned to byte boundaries to be used inside a program, so it makes sense to count fractional bytes.
There is no code re-use between the combinators, because there are no variables/references/names in BLC - everything had to be copied over. Still, the efficiency of the encoding makes for quite a terse representation.

I don't know blc, but will And:   (\a \b a b a) work?

Yes, it works. I actually used this formula for my code sequences. I just forgot to update the corresponding lambda function (now corrected). The equivalent function works for Or: \a \b a a b. It is longer than the one I used in BLC though.

Haskell, 50 - 6 = 44 bytes
-1 byte thanks to Khuldraeseth na'Barya, and -1 byte thanks to Christian Sievers.
t=const
f=n t
n=flip
a=n n f
o=($t)
x=(n>>=)
i=o.n

Try it online!

Side note: you can define Show instances for const and const id and print the church booleans directly. Try it online!.

a can be shortened.

Why is no one using f=n t?

You can save a byte by using t=pure instead of t=const.

@JosephSible I tried that initially.  Unfortunately, t=pure will cause an error when I try to apply a, o, x, or i to it.  Declaring the type of t to fix this costs more bytes than just using t=const.

how about f=seq;t=n f

@H.PWiz I didn't know about that function, but from what I've been able to find online, it would depend on whether I need to handle ⊥ as an input.

Python 2, (-3?)  101  95 bytes
David Beazley eat your heart out!
-6 thanks to Chas Brown (moved the repeated : into the join text >.<)
exec'=lambda x,y=0:'.join('F y;T x;N x(F,T);A x(y,F);O x(T,y);X x(N(y),y);I O(y,N(x))'.split())

Try it online!
I think it might be 95 - 3 because I don't reuse the functions A, X, or I, but I use a single = for assignment (in front of lambda). Maybe I cant remove any; maybe I even get to remove 3.5?

@Ryan Schaefer can I remove three or does my use of exec mean I cannot? I can see going either way - I don't reuse A, X, or I but the code wont work without them. (Maybe I even get to remove 3.5?!)

95 bytes (before the -3)

Thanks @Chas! The colon that slipped through the net :) Good job on the replace for -1 BTW

JavaScript (Node.js), 92 86 83 - 7 = 76 bytes
t=p=>q=>p
f=t(q=>q)
n=p=>p(f)(t)
a=p=>n(p)(f)
o=p=>p(t)
x=p=>p(n)(f())
i=p=>n(p)(t)

Try it online! Link includes basic test cases. Edit: Saved 6 9 bytes thanks to @tsh.

seems you cannot claim this as -7 since t, f, n are used.

@tsh That's not how I understand the scoring system; it explicitly excludes the name in the definition, although the name in the use costs 1 byte.

@Neil you can't claim the byte discount for function names that are called by your code (t, f, and n in your case).

@asgallant no. It’s no bytes for the name and 1 byte when it is used later. ‘T f n a o x i’ are no bytes then 1 byte when used later. I wanted to improve readability but now I realize I should’ve just left it fully golfed and it’s too late to change it now

@RyanSchaefer where is that rule? I've never seen it done like that.

Python 2, 133 - 6 = 127 94 bytes
exec"t!u;f!v;n!u(f,t);a!u(v,f);o!u(t,v);x!u(n(v),v);i!o(v,n(u))".replace('!','=lambda u,v=0:')

Try it online!
Shamelessly stealing the sneaky idea behind Jonathan Allan's answer; no bytes deducted though.

I was going to post an answer to my own question but I was unsure if this was allowed and I think that this is against the spirit of it. So I think I will just guide you along instead. Instead of using lists, is there anyway you can use the functions that are being input themselves and the specific manner in which they return their inputs to shorten the code?

I'd wager that although the answer is yes, it would be considerably longer in Python.

I stand corrected

@Mr.Xcoder you are correct, I had the wrong number of bytes for the example function. They would be allowed to remove 6 bytes though for the names of the functions.

@Mr. Xcoder: Modified as per your observations.

Wolfram Language (Mathematica), 61-7=54 bytes
t=#&
f=#2&
a=#2~#~f&
o=t~#~#2&
n=f~#~t&
x=n@#~#2~#&
i=#2~#~t&

Try it online!
un-golfed: inspired by Wikipedia,
t[x_, y_] := x
f[x_, y_] := y
and[x_, y_] := x[y, f]
or[x_, y_] := x[t, y]
not[x_] := x[f, t]
xor[x_, y_] := y[not[x], x]
imply[x_, y_] := x[y, t]

Pretty sure the newlines are necessary to separate function definitions. Also you reference t f and n in other function definitions so you cannot deduct those ones, so 61-4=57.

@JonathanAllan I've re-read the scoring instructions and agree that the newlines should count, thanks. I disagree with your second part: when I reuse the names, I do indeed count them as "1 byte toward the byte total of that gate", which is implicit here as I use 1-byte names. As my reading of the instructions goes, there is no mention of further counting them as one byte toward the total of the original definition as well. So I'm going with N-7 bytes. Also, another comment by the OP clarifies: "It’s no bytes for the name and 1 byte when it is used later."

I read "1 byte later" to mean usage within another function costs a byte. This aligns with how others have scored too.

@JonathanAllan I'm less interested in exegesis and more in code golfing

Underload, 56 52 bytes
(~!)(!)((~)~*):((!)~^)*(:^)(~(!)~^(~)~*)(()~(~)~^~*)

Try it online! (includes a testsuite and text identifying parts of the program)
This scores surprisingly well for a very low-level esolang. (Church numerals, Church booleans, etc. are very commonly used in Underload for this reason; the language doesn't have numbers and booleans built in, and this is one of the easier ways to simulate them. That said, it's also common to encode booleans as the Church numerals 0 and 1.)
For anyone who's confused: Underload lets you define reusable functions, but doesn't let you name them in the normal way, they just sort of float around on the argument stack (so if you define five functions and then want to call the first one you defined, you need to write a new function that takes five arguments and calls the fifth of them, then call it with insufficiently many arguments so that it looks for spare arguments to use). Calling them destroys them by default but you can modify the call to make it non-destructive (in simple cases, you just need to add a colon to the call, although the complex cases are more common because you need to make sure that the copies on the stack don't get in your way), so Underload's function support has all the requirements we'd need from the question.
Explanation
true
(~!)
(  )  Define function:
 ~      Swap arguments
  !     Delete new first argument (original second argument)

This one's fairly straightforward; we get rid of the argument we don't want and the argument we do want just stays there, serving as the return value.
false
(!)
( )   Define function:
 !      Delete first argument

This one's even more straightforward.
not
((~)~*)
(     )  Define function:
    ~*     Modify first argument by pre-composing it with:
 (~)         Swap arguments

This one's fun: not doesn't call its argument at all, it just uses a function composition. This is a common trick in Underload, in which you don't inspect your data at all, you just change how it functions by pre- and post-composing things with it. In this case, we modify the function to swap its arguments before running, which clearly negates a Church numeral.
and
:((!)~^)*
 (     )   Define function:
     ~^      Execute its first argument with:
  (!)          false
               {and implicitly, our second argument}
        *  Edit the newly defined function by pre-composing it with:
:            {the most recently defined function}, without destroying it

The question permits defining functions in terms of other functions. We define "and" next because the more recently "not" has been defined, the easier it is to use it. (This doesn't subtract from our score, because we aren't naming "not" at all, but it saves bytes over writing the definition out again. This is the only time that one function refers to another, because referring to any function but the most recently defined would cost too many bytes.)
The definition here is and x y = (not x) false y. In other words, if not x, then we return false; otherwise, we return y.
or
(:^)
(  )  Define function:
 :      Copy the first argument
  ^     Execute the copy, with arguments
          {implicitly, the original first argument}
          {and implicitly, our second argument}

@Nitrodon pointed out in the comments that or x y = x x y is normally shorter than or x y = x true y, and that turns out to be correct in Underload as well. A naive implementation of that would be (:~^), but we can golf off an additional byte by noting that it doesn't matter whether we run the original first argument or the copy of it, the result is the same either way.
Underload doesn't actually support currying in the usual sense, but definitions like this make it look like it does! (The trick is that non-consumed arguments just stick around, so the function you call will interpret them as its own arguments.)
implies
(~(!)~^(~)~*)
(           )  Define function:
 ~               Swap arguments
     ~^          Execute the new first (original second) argument, with argument:
  (!)              false
                   {and implicitly, our second argument}
       (~)~*     Run "not" on the result

The definition used here is implies x y = not (y false x). If y is true, this simplifies to not false, i.e. true. If y is false, this simplifies to not x, thus giving us the truth table we want.
In this case, we're using not again, this time by rewriting its code rather than referencing it. It's just written directly as (~)~* without parentheses around it, so it gets called rather than defined.
xor
(()~(~)~^~*)
(          )  Define function:
   ~   ~^       Execute the first argument, with arguments:
    (~)           "swap arguments"
 ()               identity function
         ~*     Precompose the second argument with {the result}

This time, we're evaluating only one of our two arguments, and using it to determine what to compose onto the second argument. Underload lets you play fast and loose with arity, so we're using the first argument to choose between two two-argument two-return functions; the argument swap that returns them both but in the opposite order, and the identity function that returns them both in the same order.
When the first argument is true, we therefore produce an edited version of the second argument that swaps its arguments before running, i.e. precompose with "swap arguments", i.e. not. So a true first argument means we return not the second argument. On the other hand, a false first argument means we compose with the identity function, i.e. do nothing. The result is an implementation of xor.

or x y = x x y saves some bytes over or x y = x true y.

Underload is often counter-intuitive when it comes to replacing literals with reused variables, but in this case, that transformation turns out to save more bytes than expected, rather than fewer. Thanks for the improvement!

J, 67 bytes - 7 = 60
t=.[
f=.]
n=.~
a=.2 :'u v]'
o=.2 :'[u v'
x=.2 :'u~v u'
i=.2 :'v u['

Try it online!
Worth noting:
Higher order functions work differently in J than in a functional language.  To create a new verb from 1 or 2 existing verbs, you need to use either an adverb (in the case of 1) or a conjunction (in the case of 2).
Syntactically, adverbs come after a verb, and conjunctions go between them.  Thus to "not" a verb f you do f n, and to "and" verbs f and g, you f a g.

Ruby, 82 - 4 = 78 bytes
f,t,a,n,i,o,x=%w(y:y x:x f:y t:f t:y y:t y:n[y]).map{|s|eval"->x,y=0{x==f ?#{s}}"}

Try it online!

Java 8, score: 360 358 319 271 233 (240-7) bytes
interface J<O>{O f(O x,O y,J...j);}J t=(x,y,j)->x;J f=(x,y,j)->y;J n=(x,y,j)->j[0].f(y,x);J a=(x,y,j)->j[0].f(j[1].f(x,y),y);J o=(x,y,j)->j[0].f(x,j[1].f(x,y));J x=(x,y,j)->j[0].f(j[1].f(y,x),j[1].f(x,y));J i=(x,y,j)->j[0].f(j[1].f(x,y),x);

This was trickier to accomplish than I thought when I started it.. Especially the implies. Anyway, it works.. Can probably be golfed a bit here and there. EDIT: Ok, not re-using functions but just duplicating the same approach is a lot cheaper in terms of byte-count for Java.. And I get the full -7 bonus for not using any of the functions as well.
Try it online.
Explanation:
// Create an interface J to create lambdas with 2 Object and 0 or more amount of optional
// (varargs) J lambda-interfaces, which returns an Object:
interface J<O>{O f(O x,O y,J...j);}

// True: with parameters `x` and `y`, always return `x`
J t=(x,y,j)->x;
// False: with parameters `x` and `y`, always return `y`
J f=(x,y,j)->y;

// Not: with parameters `x`, `y`, and `j` (either `t` or `f`), return: j(y, x)
J n=(x,y,j)->j[0].f(y,x);

// And: with parameters `x`, `y`, and two times `j` (either `t` or `f`), return:
//      j1(j2(x,y), y);
J a=(x,y,j)->j[0].f(j[1].f(x,y),y);

// Or: with parameters `x`, `y`, and two times `j` (either `t` or `f`), return:
//     j1(x, j2(x,y))
J o=(x,y,j)->j[0].f(x,j[1].f(x,y));

// Xor: with parameters `x`, `y`, and two times `j` (either `t` or `f`), return:
//      j1(j2(y,x), j2(x,y))
J x=(x,y,j)->j[0].f(j[1].f(y,x),j[1].f(x,y));

// Implies: with parameters `x`, `y`, and two times `j` (either `t` or `f`), return:
//          j1(j2(x,y), x)
J i=(x,y,j)->j[0].f(j[1].f(x,y),x);

C++17, 207−49=158 195 − 58 = 137 bytes
The linebreaks are unnecessary (other than the first two).
#define A auto
#define D(v,p)A v=[](A x,A y){return p;};
D(true_,x)
D(false_,y)
A not_=[](A f){return f(false_,true_);};
D(and_,x(y,false_))
D(or_,x(true_,y))
D(xor_,x(not_(y),y))
D(implies,x(y,true_))

Try it online!
Unit-tested with assertions such as:
static_assert('L' == true_('L', 'R'));
static_assert('R' == not_(true_)('L', 'R'));
static_assert('L' == and_(true_, true_)('L', 'R'));
static_assert('L' == or_(true_, true_)('L', 'R'));
static_assert('R' == xor_(true_, true_)('L', 'R'));
static_assert('L' == implies(true_, true_)('L', 'R'));

UPDATED: formerly I'd had
A not_=[](A f){return[f](A x,A y){return f(y,x);};};

but Roman's answer pointed the way to the shorter version. Notice that now not_(std::plus<>) is ill-formed, where formerly it was equivalent to std::plus<>; but since std::plus<> doesn't "represent a Church boolean," I think either behavior is okay by the rules.

Shouldn't "other than the first one" be updated to "other than the first two"?

@L.F.: Absolutely correct. Updated. :)

SKI-calculus + C combinator, 36 33 bytes
true=K
false=SK
not=C
and=SCI
or=SII
xor=C(CIC)I
implies=CCK

I don't actually know of any interpreter that allows you to define additional combinators in terms of previous ones, so I had to test this using http://ski.aditsu.net/ by pasting in the desired combinators e.g. CCKK(SK)pq outputs q, showing that K does not imply SK.
Edit: Saved 3 bytes thanks to @Bubbler.

and can be golfed to SCI (implements \ab. aba). Similar approach for or gives SII.

@Bubbler I no longer remember how I derived these, and I can't find a working online interpreter anyway.

@Bubbler I found an "interpreter": Try it online!

@Bubbler "or" could be written WI in the BCIKSW system I guess.

Forth (gforth), 133  bytes - 7 = 126 122
: j execute ;
: t drop ;
: f nip ;
: n ['] f ['] t rot j ;
: a dup j ;
: o over j ;
: x 2dup a n -rot o a ;
: m over n -rot a o ;

Try it online!
-4 bytes thanks to Quuxplusone
Initially I significantly overthought this, considering things like macros and literals, but then I realized that if I define things in terms of true and false (like I should have done in the first place), it gets much simpler.
Code explanation
\ Helper function to save some bytes
: j        \ define a new word
  execute  \ execute the word at the provided address
;          \ end word definition

\ True
: t        \ define a new word
  drop     \ drop the second argument
;          \ end the word

\ False
: f        \ define a new word
  nip      \ drop the first argument
;          \ end the word

\ Not - The "hardest" one because we have to reference true and false directly
: n        \ define a new word
  ['] f    \ get address of false
  ['] t    \ get the address of true
  rot      \ stick the input boolean back on the top of the stack
  j        \ call the input boolean, which will select the boolean to return
;          \ end the word

\ And
: a        \ define a new word
  dup      \ duplicate the 2nd input value
  j        \ call the 2nd input on the first and second input
;          \ end the word

\ Or
: o        \ define a new word
  over     \ duplicate the 1st input value
  j        \ call the 1st input on the first and second input
;          \ end the word

\ Xor
: x        \ define a new word
  2dup     \ duplicate both of the inputs
  a n      \ call and, then not the result (nand)
  -rot     \ move the result behind the copied inputs
  o a      \ call or on the original inputs, then call and on the two results
;          \ end the word

\ Implies
: m        \ define a new word
  over     \ duplicate the 1st input value
  n        \ call not on the 1st input value
  -rot     \ move results below inputs
  a o      \ call and on the two inputs, then call or on the two results
;          \ end the word

You repeat the long word execute three times. Defining the shorthand : j execute ; would save you 4 bytes.

Perl 6, 120 106 102 101 bytes
-1 byte thanks to Jo King
my (\t,\f,&n,&a,&o,&i,&x)={@_[0]},{@_[1]},|<f,t &^v,f t,&^v &^v,t n(&^v),&v>>>.&{"&\{\&^u($_)}".EVAL}

Try it online!

C++17, 202−49=153 193 − 58 = 135 bytes
Inspired by the comment-discussion of what counts as a 2-ary function anyway, here's a curried version of my previous C++17 solution. It's actually shorter because we can use the same macro to define not_ as to define all the other functions!
#define D(v,p)auto v=[](auto x){return[=](auto y){return p;};};
D(true_,x)
D(false_,y)
D(not_,x(false_)(true_)(y))
D(and_,x(y)(false_))
D(or_,x(true_)(y))
D(xor_,x(not_(y))(y))
D(implies,x(y)(true_))

Try it online!
This one is tested with assertions like
static_assert('R' == and_(true_)(false_)('L')('R'));
static_assert('L' == or_(true_)(false_)('L')('R'));

Notice that or_ is defined as effectively
auto or_=[](auto x){return[=](auto y){return x(true_)(y);};};

We could define or_ more "concisely" as
auto or_=[](auto x){return x(true_);};

but that would cost us because we wouldn't get to use the D macro anymore.

Since C++ is case-sensitive, how about using True and False instead of true_ and false_? And similar for the other operators. That will save 12 bytes.

@G.Sliepen: OP's scoring algorithm already takes into account that identifiers are effectively one character long. Quote: "The total length of all of the code required to make Church true and false in your language and the and not or xor and implies Church gates excluding the function's name. (for example, false=lambda x,y:y in Python would be 13 bytes). You can reuse these names later in your code with them counting 1 byte toward the byte total of that gate."

Ah, I missed that.

APL (dzaima/APL), 47 bytesSBCS
Based on Jonah's J solution.
true and false are infix functions, not is a suffix operator, and the rest are infix operators.
true←⊣
false←⊢
and←{⍺(⍶⍹false)⍵}
not←⍨
or←{⍺(true⍶⍹)⍵}
xor←{⍺(⍶not⍹⍶)⍵}
implies←{⍺(⍹⍶true)⍵}

As per OP, this counts everything from and including ← to the end of each line, and counts each call a previous definition as a single byte.
Try it online!
true and false are the left and right identity functions.
not simply swaps the arguments of its operand function.
The rest implement the decision tree:
and uses the righthand function ⍹ to select the result of the lefthand function ⍶ if true, else the result of the false function.
or uses the lefthand function ⍶ to select the true if true, else the result of the righthand function ⍹.
xor uses the righthand function ⍹ to select the the negated result of the lefthand function ⍶not if true, else the result of the lefthand function.
implies uses the lefthand function ⍶ to select the result of the righthand function ⍹ if true, else the result of the true function.

Julia 1.0, 36 bytes
(b::Bool)(x,y)=b ? x : y;i(x,y)=!x|y

I don't know if that counts, I'm actually just overloading the native Bool type to be callable, so I get most of the logic gates for free. Unfortunately, Julia doesn't have an implies gate, so I had to write my own function.
Try it online!

I think you still need to include the overloaded operators in your submission... but the scoring doesn't count them, since they're just names? So it would be +6 bytes from the newlines? I'm not too sure how the scoring works with this challenge

I'm not 100% sure how it works either, but having to include code that literally does nothing doesn't make any sense to me.

Even if the code is already declared, then you still have to include it, otherwise every other golfing language submission would be zero bytes. You just don't have to assign it to anything

Birb, 23 (or 41?) bytes
true:
false:
not:
and:
or:
xor:
implies:

It works a bit like @Neil's answer, but Birb's alternating associative order changes things a bit. Here are the respective parentheses to indicate the associativity:
true: ()
false: ()
not: (())
and: (((())))
or: (())
xor: (((())))
implies: (())

You may realize that several programs could be significantly shorter (e.g. true: , not: , or: , or and: . However, to have a uniform way of application (due to Birb's alternating associativity), true and false need to have the same length and all other functions need an odd length >2. I also tried to use a variety of birbs :)
Example applications:
not true
~>
~> [] (false)

xor true false
~>
~>  (true)

I'm unsure whether to count the additional .. If not, the sum of the length of all Birb functions is 23 bytes. If yes, 2+l(not) + 4+l(and) + 4+l(or) + 4+l(xor) + 4+l(implies) = 41 bytes.

Stax, 34 bytes
¿S£↓♣└²≡é♫Jíg░EèΩRΦ♂°┤rà╝¶πï╡^O|Θà

Run and debug it at staxlang.xyz!
Pushes a bunch of blocks to the stack. Each block expects its last argument atop the stack, followed in reverse order by the rest.
Unpacked (41 bytes):
{sd}Y{d}{y{d}a!}X{ya!}{b!}{cx!sa!}{sx!b!}

Each pair of { } is a block. I used the two registers X and Y to hold true and not so I could access 'em easily later. Unfortunately, false couldn't simply be a no-op, as that would leave the stack cluttered and mess up a single XOR case.
Test suite, commented
false
{sd}    stack:   x y
 s      swap:    y x
  d     discard: y

true
{d}    stack:   x y
 d     discard: x

not
{y{d}a!}    stack:  p
 y{d}       push:   p f t
     a      rotate: f t p
      !     apply:  p(f,t)

and
{ya!}    stack:  p q
 y       push:   p q f
  a      rotate: q f p
   !     apply:  p(q,f)

or
{b!}    stack:  p q
 b      copies: p q p q
  !     apply:  p q(q,p)

xor
{cx!sa!}    stack:  p q
 c          copy:   p q q
  x!        not:    p q nq
    s       swap:   p nq q
     a      rotate: nq q p
      !     apply:  p(nq,q)

implies
{sx!b!}    stack:  p q
 s         swap:   q p
  x!       not:    q np
    b      copies: q np q np
     !     apply:  q np(np,q)

Befunge-98, 105 77 65 bytes
Playing further with the notion of "function" in languages without functions... here's a Befunge-98 version of Church booleans!
In this constrained dialect of Befunge-98, a program consists of a series of "lines" or "functions," each of which begins with a >(Go Right) instruction in column x=0. Each "function" can be identified with its line number (y-coordinate). Functions can take input via Befunge's stack, as usual.
Line 0 is special, because (0,0) is the starting IP. To make a program that executes line L, just place instructions on line 0 that, when executed, fly the instruction pointer to (x=L, y=0).
The magic happens on line 1. Line 1, when executed, pops a number L from the stack and jumps to line number L. (This line had previously been > >>0{{2u2}2}$-073*-\x, which can "absolute jump" to any line; but I just realized that since I know this line is pegged to line 1, we can "relative jump" L-1 lines in a heck of a lot less code.)
Line 2 represents Church FALSE. When executed, it pops two numbers t and f from the stack and then flies to line number f.
Line 3 represents Church TRUE. When executed, it pops two numbers t and f from the stack and then flies to line number t.
Line 6, representing Church XOR, is innovative. When executed, it pops two numbers a and b from the stack, and then flies to line a with stack input NOT EXEC b. So, if a represents Church TRUE, the result of a NOT EXEC b will be NOT b; and if a represents Church FALSE, the result of a NOT EXEC b will be EXEC b.

Here's the ungolfed version with test harness. On line 0, set up the stack with your input. For example, 338 means IMPLIES TRUE TRUE. Make sure the closing x appears at exactly (x,y)=(0,15) or else nothing will work! Also make sure your stack setup begins with ba, so that the program will actually terminate with some output.
Try it online!
>  ba 334  0f-1x
> >>1-0a-\x             Line 1: EXEC(x)(...) = goto x
> $^< <            <    Line 2: FALSE(t)(f)(...) = EXEC(f)(...)
> \$^                   Line 3: TRUE(t)(f)(...) = EXEC(t)(...)
> 3\^                   Line 4: OR(x)(y)(...) = EXEC(x)(TRUE)(y)(...)
> 3\2\^                 Line 5: NOT(x)(...) = EXEC(x)(FALSE)(TRUE)(...)
> 1\5\^                 Line 6: XOR(x)(y)(...) = EXEC(x)(NOT)(EXEC)(...)
> 2>24{\1u\1u\03-u}^    Line 7: AND(x)(y)(...) = EXEC(x)(y)(FALSE)(...)
> 3^                    Line 8: IMPLIES(x)(y)(...) = EXEC(x)(y)(TRUE)(...)

> "EURT",,,,@
> "ESLAF",,,,,@

Here's the version whose bytes I counted.
>>>1-0a-\x
>$^<< }u-30\<
>\$^
>3\^\
>3\2^
>1\5^
>2>24{\1u\1u^
>3^

Notice that to define a function in this dialect you don't mention its name at all; its "name" is determined by its source location. To call a function, you do mention its "name"; for example, XOR (6) is defined in terms of NOT and EXEC (5 and 1). But all my "function names" already take only one byte to represent. So this solution gets no scoring adjustments.

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
caN it be acrOnymised?
The Typical Way to Make an Acronym Out of a Phrase Is to Take the First Letter of Each Word: TTWMAOPITFLEW. howeveR, sometimEs, you can make an acronym of random leTters In a seNtence such As like this: RETINA. The only condition is that the letters have to be in the correct order. For instance:

LORD can be acronymised from Hello World: heLlO woRlD
LEOD cannot be acronymised from Hello World, as no ls are before e

Your task is to take two strings as input as to determine if one can be acronymised into the other.
The first input, the phrase, will only contain letters (A-Z or a-z) and spaces, and the second input, the acronym, will only contain letters (A-Z or a-z). The acronym will always be shorter, or of equal size, to the phrase, and both the acronym and the phrase will be, at minimum, 1 letter long. You may choose which case (upper or lower) you want the inputs to be.
You may choose any two values to represent true and false, as long as those values are consistent.
This is code-golf so the shortest code in bytes wins
Examples
HELLO WORLD, LORD -> true
CODE GOLF AND CODING CHALLENGES, DANGLE -> true
SANDBOX FOR PROPOSED CHALLENGES, CODE -> false
HELLO WORLD, LLLD -> true
HELLO WORLD, LLDL -> false
NEW YORK POLICE DEPARTMENT, NOODLE -> false
MASSACHUSETTS INSTITUTE OF TECHNOLOGY, MUTTON -> true
BOB, BOB -> true
PRESIDENT OF THE UNITED STATES, I -> true

Deleted Sandbox post

PRESIDENT OF THE UNITED STATES, I -> true , doesn't have to contain at least one letter from every word?

@AZTECCO The only condition is that the letters have to be in the correct order.

Probably a duplicate of this - someone else can hammer closed if I am correct.

Having read through this and the proposed duplicate I am firmly of the opinion answers are transferable in either direction.

@JonathanAllan Agreed, some of the answers are even identical.

This question can be corrected following Wikipedia definitions.. Acronyms result from a word formation process known as blending, in which parts of two or more words are combined to form a new word.   Seems more conforming than the specifications of this question to me. As I said before.

@AZTECCO with 23 answers here it would probably be better to start a new question instead of fixing this one up.

Yes for sure @Jonathan, agreed.

There is no need to downvote this challenge simply for being a duplicate. If the fact that this is a duplicate wasn't caught in the Sandbox, there's nothing I could've done to prevent this being a duplicate.

Brachylog, 1 byte
⊇

Try it online!

Sometimes golfing is simply finding the right language for the job. :)

Java 8, 46 39 38 35 bytes
a->b->a.matches(b.replace("",".*"))

-7 bytes thanks to @tsh.
-1 byte thanks to @NahuelFouilleul.
Try it online.
Explanation:
a->b->         // Method with two String parameters and boolean return-type
  a.matches(   //  Check if the first input matches the regex:
   b           //   The second input,
    .replace("",".*"))
               //   where every character is surrounded with ".*"

For example:
a="HELLO WORLD"
b="LORD"

Will do the check:
"HELLO WORLD".matches("^.*L.*O.*R.*D.*$")

(The ^...$ will add the String#matches builtin implicitly, since it will always try to match the entire String.)

Will replacing "|" by ".*" work?

@tsh I don't think so. "nothing or L or O or R or D or nothing" isn't exactly correct if I do that replacement, whereas the current regex is "any-character(s) L any-character(s) O any-character(s) R any-character(s) D any-character(s)"

I meant a->b->a.matches(b.replaceAll("|",".*"))

@tsh Oh, yes, that indeed works. That's pretty ingenious, thanks! I was a bit confused when I misinterpret your first comment, since you definitely already knew what I was stating. ;)

why not replaceAll("",".*")

@NahuelFouilleul Ah, indeed. Thanks! :)

C (gcc), 47 bytes
f(a,b)char*a,*b;{a=!*b||*a&&f(a+1,b+(*a==*b));}

Try it online!

05AB1E, 3 bytes
æIå

Try it online!
æ              # power set of the first input
 I             # second input
  å            # does a contain b?
               # implicit output

Python 2, 48 bytes
lambda s,a:re.search('.*'.join(a),s)>0
import re

Try it online!

APL (Dyalog Unicode), 17 bytes
Full program. Prompts for phrase, then acronym.
0∊⊃(⍳⍨↓⊢)/⍞,⊂⌽0,⍞

Try it online!
⍞ prompt for phrase
  "HELLO WORLD"
  "HELLO WORLD"
0, prepend a zero
  [0,'H','E','L','L','O',' ','W','O','R','L','D']
  [0,'H','E','L','L','O',' ','W','O','R','L','D']
⌽ reverse
  ['D','L','R','O','W',' ','O','L','L','E','H',0]
  ['D','L','R','O','W',' ','O','L','L','E','H',0]
⊂ enclose (to treat as a whole)
  [['D','L','R','O','W',' ','O','L','L','E','H',0]]
  [['D','L','R','O','W',' ','O','L','L','E','H',0]]
⍞, prepend the prompted-for acronym:
  ['L','L','L','D',['D','L','R','O','W',' ','O','L','L','E','H',0]]
  ['L','L','D','L',['D','L','R','O','W',' ','O','L','L','E','H',0]]
(…)/ reduce that list by the following tacit function:
  ⍳⍨ the ɩndex of the first occurrence in the phrase (will return 1 + phrase length if unfound)
  ↓⊢ drop that many characters from the phrase
We then use the shortened phrase to look for the next letter. If at any point a letter is unfound, we'll drop everything, including the final zero. This means that if our acronym is good, we'll still have a zero left.
  [0]
  []
⊃ disclose (because the reduction reduced the number of dimensions from 1 to 0)
0∊ is zero a member thereof?

Looks like APL does not have the "lists must be homogenous in both type and length" constraint that J has.  Here the list we're reducing appears to mix characters and a list (the final element).  In J you'd need to use boxes for that kind of mixing.

@Jonah That is correct. We also have 0 and characters in the same vector here.

J, 21 bytes
<@[e.]<@#~2#:@i.@^#@]

Try it online!
Note: Some of the longer test cases omitted because they this solution is O(2^n).  They would pass with infinite memory.
Explanation: We create all 2 ^ (length of haystack) possible substrings, and check if the needle is an element of that list.

Gaia, 5 bytes
$z@$Ė

Try it online!
Powerset approach.

JavaScript, 26 bytes
Port of Kevin's Java solution so please +1 him, too.
Takes the string as a string via parameter s and the acronym as a character array via parameter a. Outputs false for true and true for false.
s=>a=>!s.match(a.join`.*`)

Try it online! (Footer reverses output for easier verification)

Python 3, 89 68 bytes
-21 bytes thanks to AdmBorkBork
def a(b,c):
    for i in b:
        if i==c[:1]:
            c=c[1:]
    return len(c)==0

Takes input as a(string, acronym). Try it online!

Welcome to CodeGolf.SE! I'm not an expert in Python, but I think you can use tabs instead of spaces to save a bunch of bytes. Try it online!

AdmBorkBork, I didn't seem to be able to type tabs in the answer box, and I forgot copy and paste.

Japt, 4 bytes
à øV

Try it here

Python 3, 63 bytes
f=lambda s,t:(t[:1]in{*s}and f(s[s.find(t[0]):],t[1:]))**len(t)

Try it online!
Recursive function. Will check for each letter in the acronym t, whether it is found in the string s. If it is, the function is called recursively with the part of the string after the current test character t[0] as the new input string s.
When the test character is not found, the final evaluation result (which at that point is always 0) is raised to the power of the length of the remaining test string t. Since 0**0 == 1 and 0**x == 0 for any x > 0, the function returns 1 when all test characters have been found in order and 0 otherwise.

C#, 152 bytes
public class P{public static void Main(string[]a){int q=0;int e=a[1].Length;foreach(char c in a[0])if(q!=e&&c==a[1][q])q++;System.Console.Write(q==e);}}

Try Online

The "Try Online" link 404s for me. Have you tried the fairly conventional website https://tio.run? I haven't read through your code completely, but you can almost certainly declare q and e together, use var instead of char, use & instead of &&, make the submission a lambda expression ((a,b)=>{...} or even a=>b=>{...}), and use the Visual C# Interactive compiler (that allows you to implicitly use System and some other namespaces, use Print() and multiple similar awesome things).

Whooops fixed the link. And as to the C# interactive compiler: I simply don't want to use it because I just like my code to be full programs.

In the upcoming threads I will use tio.run for simplicity sake.

Stax, 4 bytes
äΦv>

Run and debug it

This breaks the rule that the outputs must be consistent

@cairdcoinheringaahing Updated. Applying !! which will return 1 for true and 0 for false.

Jelly, 4 bytes
eŒP}

Try it online!

Zsh, 35 bytes
[[ $1 = *${~${(j:*:)${(s::)2}}}* ]]

Outputs via exit code. Try it online!
[[ $1 = *${~${(j:*:)${(s::)2}}}* ]]
                    ${     2}        # second parameter
                    ${(s::) }        # split into characters
            ${(j:*:)         }       # join with *
         ${~                  }      # enable globbing
        *${~${(j:*:)${(s::)2}}}*     # *A*C*R*O*N*Y*M*
[[ $1 =                           ]] # does it match the first parameter?

JavaScript, 50 bytes
h=>n=>[...n].reduce((a,l)=>a+1?h.indexOf(l,a):a,0)

Try it online!
take input as f(haystack)(needle)
h=>n=>                                             // inputs
      [...n]                                       // transform n from string to array of char
            .reduce((a,l)=>                    ,0) // for each letter change the value of a, (a starting at 0)
                           a+1?h.indexOf(l,a):a    // if a === -1 keep it else replace it by the position of the letter l in the haystack h starting from position of previous letter

SNOBOL4 (CSNOBOL4), 88 bytes
	T =INPUT
S	T LEN(1) . X REM . T	:F(M)
	M =M ARB X	:(S)
M	INPUT M	:F(END)
	OUTPUT =1
END

Try it online!
Prints 1 for Acronymizable, and does nothing for not.
	T =INPUT			;* read in the Target
S	T LEN(1) . X REM . T	:F(M)	;* extract the first letter of T
					;* and when T is empty, goto M
	M =M ARB X	:(S)		;* create a PATTERN: M, ARBitrary match, X
					;* then goto S
M	INPUT M	:F(END)			;* if M doesn't match the input, end
	OUTPUT =1			;* else print 1
END

Emacs Lisp, 52 bytes
(lambda(a b)(string-match(mapconcat'string b".*")a))

Pyth, 3 bytes
}Ey

Try it online!

Somehow Pyth is still managing to beat Jelly, after all these years

Haskell, 40 bytes
r@(a:c)#(b:d)|a==b=c#d|1>0=r#d
x#y=x==""

Try it online!

Retina 0.8.2, 20 19 bytes
+`(.)(.*¶)\1?
$2
¶$

Try it online! Takes the phrase and acronym on separate lines, but the link includes a header that formats the test suite appropriately. Explanation:
+`

Process all of the letters of the phrase.
(.)(.*¶)\1?
$2

For each letter of the phrase delete the next letter of the acronym if it is the same.
¶$

Check that all of the letters of the acronym were deleted.

Python 3, 85 bytes
def f(s,w):
	for c in s:
		if c==w[0]:
			w.pop(0)
			if len(w)==0:return 1
	return 0

Try it online!

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
Weigh your words!
The challenge
Given two strings, each of length up to 30, consisting of printable ASCII characters (codes \$[32, 126]\$), put them onto a balance scale in the fewest bytes of code! This consists of the following steps:

Calculate and compare the weights of the strings
Choose the appropriately tilted ASCII-art scale
Place the two strings onto the scale

The strings may be passed as an array, two arguments, or any other reasonable method.

The weight of a string is defined as the sum of the weights of that string's characters, where:

Spaces have a weight of 0 ()
Lowercase letters have a weight of 2 (abcdefghijklmnopqrstuvwxyz)
Uppercase letters have a weight of 4 (ABCDEFGHIJKLMNOPQRSTUVWXYZ)
All other symbols have a weight of 3 (!"#$%&'()*+,-./0123456789:;<=>?@[\]^_`{|}~)

The scales look like this:

          .     _
          |  _-*/\
          |-*  /  \
       _-*|   /    \
    _-*   |  /      \
   /\     |  *------*
  /  \    |
 /    \   |
/      \  |
*------*  |
    ______|______

    _     .
   /\*-_  |
  /  \  *-|
 /    \   |*-_
/      \  |   *-_
*------*  |     /\
          |    /  \
          |   /    \
          |  /      \
          |  *------*
    ______|______

          .
          |
    ______|______
   /\     |     /\
  /  \    |    /  \
 /    \   |   /    \
/      \  |  /      \
*------*  |  *------*
          |
          |
    ______|______

If the first string is heavier, use the first drawing as the base of your output; if the second string is heavier, use the second drawing; if the strings have equal weight, use the third. Trailing whitespace is allowed.

I will be using a segment of the third drawing as the base for all of the following examples.
The first string should be placed onto the left pan, and the second string onto the right pan.
Place a string on a pan by placing its non-space characters within the 6x5 area immediately above the dashes, as marked by #s here (you may end up overwriting part of the balance scale - that is fine):

 ######_
 ######
 ######
 ######
/######\
*------*

All of these characters should be "settled" ie. either above a - character or another character from the string:

  WRONG         WRONG        CORRECT
    ____          ____          ____
 f /\            /\            /\
  l  \          /  \          /  \
 /    \        / hov\        / s  \
/oating\      /eri ng\      /ettled\
*------*      *------*      *------*

Additionally, the whole stack should be as flat as possible, meaning that of the six 1-wide columns, the height of the tallest and the height of the shortest must not differ by more than 1:

    WRONG              WRONG             CORRECT            CORRECT
[tallest:  5]      [tallest:  4]      [tallest:  5]      [tallest:  2]
[shortest: 0]      [shortest: 2]      [shortest: 4]      [shortest: 2]
      5__5_               ____              5_5__               ____
     45445             & /\               445454               /\
     45445             $% &$@             445454              /  \
    /45445             &%@%$&             445454             %&$@%&
   / 45445\           /&$@$&%\           /445454\           /$@$%$$\
   *------*           *------*           *------*           *------*

The exact order/arrangement of the characters does not matter. The following are all valid arrangements for the string "Weigh your words!":

    ____          ____          ____          ____
   /\            /\            /\            /\
 ds! \          / owd         oe \u        !Wd \
 ourwor        Wihuos        yoiwgr        eghioo
/Weighy\      /egyrr!\      /Wrhd!s\      /rrsuwy\
*------*      *------*      *------*      *------*

Test cases

INPUT: "CODE GOLF", "coding challenges"
WEIGHTS: 32, 32
EXAMPLE OUTPUT:
          .
          |
    ______|______
   /\     |     /\
  /  \    |    nge\s
 /OO  \   |   challe
/CFGLED\  |  /coding\
*------*  |  *------*
          |
          |
    ______|______

INPUT: "", "$"
WEIGHTS: 0, 3
EXAMPLE OUTPUT:
    _     .
   /\*-_  |
  /  \  *-|
 /    \   |*-_
/      \  |   *-_
*------*  |     /\
          |    /  \
          |   /    \
          |  /    $ \
          |  *------*
    ______|______

INPUT: "YOU KNOW WHAT THEY SAY!", "there's_always_a_relevant_xkcd"
WEIGHTS: 75, 65
EXAMPLE OUTPUT:
          .   tr_a_s
          |  _hekx_y
          |-* elcdta
       _-*|   revanw
    _-*   |  /e's_al\
  T/\     |  *------*
 AUYOHY   |
 A!HWYK   |
/OTSMEW\  |
*------*  |
    ______|______

Is trailing whitespace acceptable?

@Hiatsu Yep, that's fine.

I like this challenge, I really do. However there are 2 points preventing me from giving it my +1. Firstly: if spaces don't "weigh" anything and don't get included in the artwork then why include them at all? It's just unnecessary overhead to first filter them out. Secondly: this feels like a "2-in-1"/chameleon challenge to me - Challenge 1: Determine which string is "heavier", Challenge 2: Generate some ASCII-art.

@Shaggy I think that's a fair assessment. Posting this has taught me to just keep things simple.

Nice., and another Nice.

Charcoal, 110 bytes
ＵＭθ⪫⪪ι ω≔⁰ηＦθ≦⁻ΣＥι⁻⁺³№ακ№βκηＰ-×⁷_↑χ.¶¶≔³ζ¿η«≔∨›⁰η⁵ζＭ±⁶±²_Ｆ⁴⁺¶*-§_|_ι¿›⁰η‖»Ｐ-⁺|×⁶_Ｊ±⁴±ζＦθ«←⁶↑*↗⁴↓↘⁴←↖*←⪪ι⁶Ｊ⁹⁻ζ⁶

Try it online! Link is to verbose version of code. Takes input as an array of two strings. Explanation:
ＵＭθ⪫⪪ι ω

Remove the spaces from both strings.
≔⁰η

Assume the weights balance.
Ｆθ

Loop over both strings.
≦⁻ΣＥι⁻⁺³№ακ№βκη

Subtract the running difference from the weight of the string.
Ｐ-×⁷_↑χ.¶¶

Print the base of the balance scale.
≔³ζ

Assume that both pans are 3 off the ground.
¿η«

If the weights didn't balance...
≔∨›⁰η⁵ζ

... calculate the height of the left pan...
Ｍ±⁶±²_Ｆ⁴⁺¶*-§_|_ι

... draw the balance leaning down to the right...
¿›⁰η‖»

... and reflect if the left pan was heavier.
Ｐ-⁺|×⁶_

Otherwise draw a level balance.
Ｊ±⁴±ζ

Jump to the first scale pan.
Ｆθ«

Loop over the inputs.
←⁶↑*↗⁴↓↘⁴←↖*

Draw the scale pan.
←⪪ι⁶

Slice the input into substrings of length 6 and print them upside-down so that they fill the pan upwards.
Ｊ⁹⁻ζ⁶

Jump to the second scale pan.

Python 2, 1101 1071 855 837 bytes
-216 bytes with string compression
-18 bytes by reducing some repetition
from zlib import decompress as Z
from base64 import b64decode as D
r=range(6)
j="".join
w=lambda a:0if not a else(2+2*(a[0]<'[')if a[0].isalpha()else 3)+w(a[1:])
t=Z(D('eJxT0FKIV1BQ0AWT8SAIJsAcXTCppQAGumBSSx8MYsBAC0kCAiCySAIKEJW4ZHGpxA8AejMemQ=='))
p=lambda k,l,m:j(map(j,[(t[2*l+m::6][:30-len(k)]+k)[i::6]for i in r]))
def A(a,b):
 e=cmp(w(j(a.split())),w(j(b.split())))+1;return Z(D('eJxVUUGuhTAI3HOKWTdBW/U2SHoQ4O6ftvrMb0hLZJgZAYABFZB5KxD4zrZtNJOJMaHWIIoa0D6Ao+jrWRiHEI7kMcQg9VLBCo9O3dCbdanepOvZQztF9rRH2xUlwISehIZ96HltLFqu1IMF2p1QH/S+1Ge7CT5blIVOxqUWFudjqHPSwhitjPbzf7uZ1HaIaG2hShFTfU7Eca6J7MBr1K+3/YbRVLd2VlE5oilp7EG/gV7+DPQuSAsZPm7PZE9HBY2G+ctS/QzR+whSGlPAGz4mkkl5Sf18SMvkyL9iF6aLd2WLUm/KDVzvJu93k2tLZXlwetgLmFH4MzcKCaJnqX1Fz3iOf4//Pi7EwP4BHmyJpg=='))[e::3].format(*map(lambda c:[p(j(([a,b]*3)[c].split()),e,c)[i::5]for i in r],r))

Try it online!
Run as A(string_one, string_two.
w calculates the weight of the string recursively.
t is the compressed and interlaced text of all six possible scales, which happens to compress very nicely.
p takes the string (with spaces removed), the weight of the string, and the side of the balance that string is on, and creates a 5x6 block of characters.
A takes the strings, and builds their blocks with p. The giant string at the bottom is three format strings interlaced and compressed.

JavaScript (ES6),  340  337 bytes
Takes input as an array of 2 arrays of characters. Draws the output character by character.
S=>(s=Math.sign(~(g=i=>(S[i]=S[i].filter(c=>c>' '?i+=/[a-z]/gi.test(c)?c>{}?2:4:3:0),i))(0)+g(1))+1,g=x=>y>10?'':(X=(r=x>9)?20-x:x,Y=(r?2-s:s)*2+y,S[+r][X>0&&X<7&&47-Y*6+X]||`. /\\|-_*
`[~X?x-10?y>9?X>3?6:1:[x+y*3-17,2*y-4,x+~y*3][s]/2|X<4?Y<5|Y>8?Y-9|X>7?1:X%7?5:7:~X+Y?X+Y-8?1:2^r:3^r:[7-x%3,6,5+x%3][s]:y&&4:8])+g(x<21?x+1:!++y))(y=0)

Try it online!
How?
We define a first helper function that removes spaces from the input string \$S[i]\$ and returns its weight:
g = i => (                   // i = string index
  S[i] = S[i].filter(c =>    // for each character c in S[i]:
    c > ' ' ?                //   if c is not a space:
      i +=                   //     update i:
        /[a-z]/gi.test(c) ?  //       if c is a letter:
          c > {} ?           //         if c is in lower case:
            2                //           add 2 to i
          :                  //         else:
            4                //           add 4 to i
        :                    //       else (not a letter):
          3                  //         add 3 to i
    :                        //   else (a space):
      0                      //     remove c from S[i]
  ), i                       // end of filter(); return i
)                            //

NB: Because we re-use \$i\$ to compute the weight, it is off by one for \$S[1]\$.
We compute \$s\$, which is equal to \$0\$ if \$S[0]\$ is heavier, \$2\$ if \$S[1]\$ is heavier, or \$1\$ if both strings have the same weight:
s = Math.sign(~g(0) + g(1)) + 1

We now invoke the second helper function to draw the output:
g = x =>                     // given x:
  y > 10 ?                   //   if we've reached the last row:
    ''                       //     stop recursion
  :                          //   else:
    ( X = (r = x > 9) ?      //     r = true if we're on the right side
        20 - x               //       X = 20 - x on the right side
      :                      //     or:
        x,                   //       X = x on the left side
      Y = (r ? 2 - s : s)    //     Y is the position of the scale tray
          * 2 + y,           //     according to s and the current side
      S[+r][                 //     we try to extract a character from S[0] or S[1]:
        X > 0 && X < 7 &&    //       provided that we're located above the tray
        47 - Y * 6 + X       //       and using an index based on (X, Y)
      ] ||                   //     if this character doesn't exist,
      `. /\\|-_*\n`[INDEX]   //     we need to draw the balance instead
    ) +                      //     (see the next part)
    g(x < 21 ? x + 1 : !++y) //     append the result of a recursive call

Where INDEX is computed as follows:
~X ?                         // if this is not the last character of the current row:
  x - 10 ?                   //   if this is not the central column:
    y > 9 ?                  //     if this is the last row:
      X > 3 ? 6 : 1          //       draw the base ('_' or a space)
    :                        //     else:
      [ x + y * 3 - 17,      //       attempt to draw the beam:
        2 * y - 4,           //         using an equation depending on s
        x + ~y * 3           //         whose result must be -1, 0 or 1
      ][s] / 2 | X < 4 ?     //       if it's invalid or X is less than 4:
        Y < 5 | Y > 8 ?      //         if we're not over the chains:
          Y - 9 | X > 7 ?    //           if we're not over the pan:
            1                //             draw a space
          :                  //           else:
            X % 7 ? 5 : 7    //             draw the pan ('-' or '*')
        :                    //         else:
          ~X + Y ?           //           if this is not an interior chain:
            X + Y - 8 ?      //             if this is not an exterior chain:
              1              //               draw a space
            :                //             else:
              2 ^ r          //               draw the exterior chain ('/' or '\')
          :                  //           else:
            3 ^ r            //             draw the interior chain ('/' or '\')
      :                      //       else:
        [ 7 - x % 3,         //         draw the beam, using either '_' -> '-' -> '*'
          6,                 //         or just '_'
          5 + x % 3          //         or '*' -> '-' -> '_'
        ][s]                 //         depending on s
  :                          //   else:
    y && 4                   //     draw the central pillar ('|' or '.')
:                            // else:
  8                          //   append a line feed

Java 10, 1043 993 988 983 919 914 900 898 bytes
(a,b)->{var r=new char[11][21];for(var A:r)java.util.Arrays.fill(A,' ');int A=s(a=a.replace(" ","")),B=s(b=b.replace(" ","")),i=3,j,z;for(;++i<17;r[3][i]=A==B?'_':32)r[10][i]=95;for(i=11;i-->1;)r[i][10]=i>0?'|':46;if(A==B){for(r[8][0]=r[8][13]=r[8][20]=42;++i<20;)r[8][i<8|i>13?i:1]=45;for(A=B=i=8;i-->4;r[i][7-i]=r[i][20-i]=47)r[i][i]=r[i][i+13]=92;}else{for(r[i=5][z=A<B?0:13]=r[5][z+7]=r[9][13-z]=r[9][20-z]=42;i-->1;r[i][A>B?j+1:j-1]=42)r[i][j=A>B?17-i*3:3+i*3]=45;for(;++i<20;)r[i>13^A>B?9:5][i>13|i<7?i:1]=45;for(i=9;i-->1;r[i][i>4?21-z-i:4+z-i]=47)r[i][i+3+(i>4?9-z:z)]=92;r[0][A<B?i=4:16]=r[1][A>B?13:7]=r[3][A>B?7:13]=r[4][A>B?4:16]=95;A=9-i;B=5+i;}c(r,a,A,7);c(r,b,B,20);return r;};int s(String s){int r=0;for(int i:s.getBytes())r+=i>64&i<91?4:i>96&i<123?2:3;return r;}void c(char[][]r,String s,int p,int q){for(int c=0,i=p,j;i-->p-5;)for(j=q;j-->q-6&c<s.length();)r[i][j]=s.charAt(c++);}

-86 bytes thanks to @ceilingcat.
Input are two Strings, which will result in a character-matrix as result.
Try it online.
Explanation:
// Method with two String parameters and character-matrix return-type:
(a,b)->{
  // Result matrix, with 11 rows and 21 columns:
  var r=new char[11][21];
  // Initially fill the entire matrix with spaces:
  for(var A:r)java.util.Arrays.fill(A,' ');
  // Remove all spaces from the input-Strings,
  // and call a separated method to calculate the scores of both input-Strings:
  int A=s(a=a.replace(" ","")),B=s(b=b.replace(" ","")),

  // Fill the cells for the base with '_',
  // and also fill the cells for the balance-bar with '_' when the scores are equal:
  i=3,j,z;for(;++i<17;r[3][i]=A==B?'_':32)r[10][i]=95;
  // Fill the cells for the stand with '|':
  for(i=11;i-->1;)r[i][10]=i>0?'|'
  // And the top of it with '.':
  :46;

  // If the scores are equal:
  if(A==B){
    // Fill the four appropriate cells for the sides of the scales with '*':
    for(r[8][0]=r[8][7]=r[8][13]=r[8][20]=42;
    // Fill the appropriate cells for the scales themselves with '-':
        ++i<20;)r[8][i<8|i>13?i:1]=45;
    // Set A and B both to 8 to use later on,
    // and fill the appropriate cells of the robes with '/' and '\':
    for(A=B=i=8;i-->4;r[i][7-i]=r[i][20-i]=47)r[i][i]=r[i][i+13]=92;}
  // If the scores aren't equal:
  else{
    // Fill the four appropriate cells for the sides of the scales with '*':
    for(r[i=5][z=A<B?0:13]=r[5][z+7]=r[9][13-z]=r[9][20-z]=42;
    // Fill the appropriate four cells of the balance-bar with '-':
        i-->1;r[i][A>B?j-1:j+1]=42)r[i][j=A>B?17-i*3:3+i*3]=45;
    // Fill the appropriate cells of the scales with '-':
    for(;++i<20;)r[i>13^A>B?9:5][i>13|i<7?i:1]=45;
    // Fill the appropriate cells of the robes with '/' and '\':
    for(i=9;i-->1;r[i][i>4?21-z-i:4+z-i]=47)r[i][i+3+(i>4?9-z:z)]=92;
    // Fill the four appropriate cells of the balance-bar with '_',
    // and set A and B to 9 and 5 depending on which score is higher:
    r[0][A<B?i=4:16]=r[1][A>B?13:7]=r[3][A>B?7:13]=r[4][A>B?4:16]=95;A=9-i;B=5+i;}
  // Call a separated method to fill the cells above the scales with the input-characters:
  c(r,a,A,7);c(r,b,B,20);
  // And finally return the resulting character-matrix:
  return r;}

// Separated method to calculate the score of the given String:
int s(String s){
  // Initially start the score-sum at 0:
  int r=0;
  // Loop over the characters of the given String:
  for(int i:s.getBytes())
    // Increase the sum by:
    r+=
      // 4 for uppercase letters:
      i>64&i<91?4
      // 2 for lowercase letters:
      :i>96&i<123?2
      // 3 for any other character:
      :3;
  // And return the resulting sum:
  return r;}

// Separated method to draw the strings on top of the scales:
void c(char[][]r,String s,int p,int q){
  // Keep a counter so we know when we're done drawing the given String:
  for(int c=0,
  // Loop over the appropriate rows bottom to top:
  i=p,j;i-->p-5;)
    // Inner loop over the appropriate cells of this row left to right,
    for(j=q;j-->q-6
    // as long as we're not done yet with the input-String:
        &c<s.length();)
      // And fill that appropriate cell with the next character in line of the given String:
      r[i][j]=s.charAt(c++);}


text:
Fancy String Replace
let S, a and b each represent a string
Goal: Write a standard string replace function where the you replace all occurrences of a in a string S with b so long as a is not already part of an instance of b
for example, if we have the string S = My oh my that there is a big ol' that
and we wanted to do a fancy replace with a = that and b = that there we would replace every instance of that with that there as long as the instance of that isn't already an instance of that there
So in this case the output would be: My oh my that there is a big ol' that there
The first that is not replaced because it is already part of an instance of that there
Notes

All 3 inputs must be strings containing only printable ascii characters
Input may be given as 3 separate strings or a list of 3 strings
Input will be in the order S, a, b unless otherwise specified in the answer
In order for a to be considered a part of b, all of the instance of a must be part of an instance b

Some Corner Cases Explained
Input:  ["1222", "22", "122"]
Output: "12122"

In the case above example the latter 22 is replaced. Even though part of it is part of an instance of b, the entirety of it is NOT a part of the instance of b. Since the entire instance of a is not part of an instance of b it is replaced.
Input:  ["123 ", "23", "12"]
Output: "112 "

This test case illustrates the same case as above but perhaps in a slightly more clear way. Again the 2 in the middle is both part of an instance of a as well as part of an instance of b, however since all of a is not part of the instance of b it is still replaced.
Input: ["Empty", "", "p"]
Output: "pEpmptpyp"

In the above test case both the empty string before and after the p are not replaced as the can wholly be considered part of the instance of p.
Other Test Cases
Input:  ["aabbaa", "aa", "aabb"]
Output: "aabbaabb"

Input:  ["Hello World!", "o", " no"]
Output: "Hell no W norld!"

Input: ["Wow, oh wow, seriously WOW that's... wow", "wow", "WOW,"]
Output: "Wow, oh WOW,, seriously WOW that's... WOW,"

Input: ["Empty", "", "b"]
Output: "bEbmbpbtbyb"

Input: ["Empty", "b", "br"]
Output: "Empty"

Input: ["Empty", "pty", "Empty"]
Output: "Empty"

Input:  ["aabbaaa", "aa", "PP"]
Output: "PPbbPPa"

Input:  ["121212","1","121"]
Output: "121212"

This is a question for code-golf so the shortest answer in bytes wins.

Let us continue this discussion in chat.

Perl 6, 76 bytes
{$^b;$^a;&{S:g/$a<?{$!=$/;all m:ex/$b/>>.&{$!.to>.to||.from>$!.from}}>/$b/}}

Try it online!
Anonymous code block that takes input curried, like f(a,b)(s).
I'm pretty sure this matches up with the intent of the question. Basically, it only makes the substitution if the position of a is not within any of the overlapping matches of b.

however in tests there's 2p : in pEpmpptpyp instead of pEpmptpyp

@Nahuel Fixed. This should also handle the other test cases (and I think is the first to do so)

@JoKing Unfortunately after rethinking some of the test cases pointed out, I think the last test case will fail [1222, 22, 122] -> 12122. I have updated the question to clarify and apologize that I hadn't made this corner case more clear earlier.

i had a similar issue with s/(?!$b)$a/$b/g, when $a is empty because empty string after p was matching (?!p) i needed (?<!p)(?!p)

@Quinn Fixed I think?

@JoKing It seems fixed to me!

Seems to fail if b is the empty string

Charcoal, 55 bytes
≔⁰εＦ⌕ＡθηＦ‹‹ιε⬤⌕Ａθζ∨‹ικ›⁺ιＬη⁺κＬζ«≔⁺⁺ω✂θει¹ζω≔⁺ιＬηε»⁺ω✂θε

Try it online! Link is to verbose version of code. Explanation:
≔⁰ε

Initialise a variable to show where the last replaced match ended.
Ｆ⌕Ａθη

Find all overlapping matches of a in S.
Ｆ‹‹ιε

If the next match does not overlap the last successful replacement...
⬤⌕Ａθζ∨‹ικ›⁺ιＬη⁺κＬζ«

... and it also overlaps no copy of b in S...
≔⁺⁺ω✂θει¹ζω

... then concatenate the intermediate substring between the last match and this match with b to the output string...
≔⁺ιＬηε

... and update the last match end variable to the end of this new match.
»⁺ω✂θε

At the end, add on any remainder of S and output the result.

@tsh OK this is a complete rewrite, I hope this now covers all possible cases...

@Neil I believe this is also valid !

@Neil I believe this is valid now.

@Quinn Ooh, does that make me first to make their answer valid? Neat!

@Neil I believe JoKing also has a valid answer

Wolfram Language (Mathematica), 43 122 96 88 bytes
##2~StringReplacePart~Cases[#2~P~#,{a_,b_}/;And@@(#2<b||#>a&@@@P@##2)]&
P=StringPosition

Try it online!
+79: should be fixed.
Call as f[a,S,b].
                                                                      & (* a function which finds *)
                            #2~P~#,                                     (* the positions {start,end} where a occurs in S *)
                      Cases[       {a_,b_}/;And@@(#2<b||#>a&@@@     )]  (* which are not a subrange of any of the *)
                                                               P@##2    (* positions of b in S, *)
##2~StringReplacePart~                                                  (* and replaces those parts of the string with b *)
P=StringPosition

Fails for 121212, 1, 121 - should output 121212

@attinat Seems fixed to me!

Perl 5 (-lpF/;/), 41 bytes
($_,$a,$b)=@F;s/(?<!(?=$b).)(?!$b)$a/$b/g

TIO

[1222, 22, 122] should output 12122, but yours outputs 11222

ok didn't understand that, maybe fixed, and shorter

Oh no actually the last test case has one too many 12s, turns out the question I made was much harder than I originally thought!

@Quinn, it seems to me that it's not consistent : 123,23,12 -> 112 but 1212,1,121->1212 (? why it shouldn't be 121212)

it seems to be what should be clarified is which positions in S should not match with b or which part to skip before looking for next match

I'm not sure I understand what's inconsistent. 123,23,12 -> 112 is because in this case a is 23 and b is 12, 23 is not wholly part of 12 (there are parts of a. that are not in b). 1212,1,121->1212 because a is 1 and b is 121 so each instance of a is fully contained in an instance of b. I hope that clears it up a bit.