text:
String Shenanigans
Challenge
In this challenge, you are to code in any language a program or function that will take a string and replace certain characters within it with different characters.
Input
The input is the same for both functions and full programs:
[string] [char1] [char2]

string will be an indefinite line of characters surrounded by quotation mars, such as "Hello, World!" or "1 plus 2 = 3".
char1 will be a single character within string.
char2 will be a single character not necessarily in string.

Output
[modified string]

Your output will take string and replace all instances of char1 with char2, then output the result as modified string. Case should be ignored, so the input "yolO" o u should output yulu.
Examples
Input
"Hello, World!" l r

Output
Herro, Worrd!

Input
"Slithery snakes slurp Smoothies through Silly Straws" s z

Output
zlithery znakez zlurp zmoothiez through zilly ztrawz

Input
"Grant Bowtie: Only the best future bass artist ever" : -

Output
Grant Bowtie- Only the best future bass artist ever

Input
"019 + 532 * 281 / ? = waht/?" / !

Output
019 + 532 * 281 ! ? = waht!?

Other details
This is code golf, so the shortest answer (in bytes) at the end of the week (the 14th of September) wins. Also, anything not specified in this challenge is fair game, meaning that stuff I don't explain is up to you.

I figure the two characters can be upper case as well? And if the first of the two is upper case, it would still match both lower and upper case characters in the string?

Are functions allowed?

To add to vihan's comment, note that per our defaults, functions or full programs are both okay.

@AlexA. Isn't that only if it's not specified? In this case, it says "a program". In the past, that meant that you had to provide a full program.

@RetoKoradi - unfortunately, different people use the term "program" differently. So "in the past" is only relevant if it was the same person (the_basset_hound).

What about the quotes in the input? I guess they have to be removed, haven't they?

@RetoKoradi All replaced characters should be lowercase, regardless of the case of the two characters.

@vihan Functions are allowed.

@Cabbie407 The quotes will need to be accounted for, yes.

So the second character can be upper case, and the replaced character is lower case? That doesn't make much sense to me. So if functions are allowed, but it specifically says that the input string has quotes, will the function receive a string that has quotes inside the string? Well, frankly, I'm probably done with this challenge anyway. Changing about 3 rules after there are already 10 answers is very unfortunate.

That part about all replacements needing to be lowercase is new. The original statement said, that case should be ignored. For me this means, that lower and upper case letters should be replaced, but not that I should change the replacement letter...

Does input have to come from stdin or from command line arguments? If stdin, do the three items have to be separated by a single space each, or are other delimiters acceptable?

@RetoKoradi How about this (and I'll put this and other info in the question): Anything not specified about the challenge is fair game.

Pyth, 10 bytes
XQr*2w4*2w

Try in online: Demonstration or Test Suite
Explanation:
 Q             read a line and evaluates (reads a string with quotes)
     w         reads a char: a (actually reads a line)
   *2          make it twice as long: aa (repeat the char)
  r   4        capitalize this string: Aa
       *2w     read another char and repeat it: bb
X              replace the letters Aa by bb in Q

Vim, 18 keystrokes
$bD:s/<C-R>"<Left><BS>/<Right>/i<CR>x$x

Assuming the cursor is on the first column of the first line, and the open file contains this:
"yolO" o u

The file will end up containing:
"yulu"

+1 for Vim ... not something oft-seen :)

Your ending file shouldn't contain the quotation marks

@NathanMerrill Fixed.

JavaScript ES6, 28 bytes
(s,a,b)=>s.replace(a,b,'gi')

Firefox only as it uses a mozilla-specific feature.

That was quick. I appear to have made this too easy again...

Is it correct to use 3 arguments instead of 1 string?

Retina, 29 bytes
i`(.)(?=.*\1 (.)$)|"|....$
$2

For scoring purposes each line goes in a separate file, but for convenience you can run the above from a single file with the -s flag.
As this is just a single regex replacement, you can test it here.
The regex consists of three parts, one to do the substitution and two to clean up the rest of the input. This is the substitution part:
(.)       # Match a character and capture it in group 1.
(?=       # Lookahead to ensure that this is the character we're searching for.
  .*      # Consume arbitrary characters to move to the end of the string.
  \1 (.)$ # Ensure we can match the captured character, then a space, then
          # another character and then the end of input. That other character
          # is captured in group 2.
)

This match is replaced by $2, i.e. the character to be substituted in.
The other two possibilities are either to match a ", or to match the last four characters of the input. In either case group two is empty, so the replacement string $2 evaluates to an empty string and the match is simply removed from the input. This cleans up the quotes and the characters at the end.
i` simply activates case insensitive matching.

How does this work?

@mbomb007 Edited. Let me know if you have further questions.

gawk - 48
IGNORECASE=gsub(/"/,_),gsub($(NF-1),$NF)+(NF-=2)

That IGNORECASE hurts...
How to use
In bash enter: awk 'IGNORECASE=gsub(/"/,_),gsub($(NF-1),$NF)+(NF-=2)'
Then enter a string in quotes and the two characters. In front of some characters ("[" and "(" I know of) you have to enter a backslash, because awk would try to interpret them as regular expression instead.

This doesn't work.

Hmm... it works with gawk and mawk...

Doesn't work with my Gawk, what version are you using? Why is there a comma between the 2 gsubs ? Nvm, didn't work properly with STDIN because i didn't escape the quotes... Still don't need that comma though or the + as they are doing nothing.

Few less characters awk 'IGNORECASE=gsub(/"/,x)gsub($(NF-1),$NF)(NF-=2)'

I use gawk 4.1.1, but since this works with the mawk that comes with ubuntu I figured it would work with any awk. The comma is normally used to specify a range pattern. http://www.math.utah.edu/docs/info/gawk_9.html#SEC92 I use it here just because it works. ;)

Oh, great, thanks. :) This does not set IGNORECASE for the first input. But I got fooled by the syntax highlighting in my editor for that quote regexp ;)

Yep, just realised it would be set a value of 267 and probably wrap :(

Octave, 28
An anonymous function using built in functions.
@(W,T,F)strrep(lower(W),T,F)

Assuming it is stored in f we can call it as follows:
f('Slithery snakes slurp Smoothies through Silly Straws','s','z')

Word list, Template, Fill-in?

PowerShell, 33 30 Bytes
param($a,$b,$c)$a-replace$b,$c

Expects input via command-line argument. PowerShell has many built-in case-insensitive operators that just tack on an i in front of the usual operator -- here as -ireplace instead of -replace -- so the case-insensitive matching was actually pretty easy.
PS C:\Tools\Scripts\golfing> .\string-shenanigans.ps1 "Hello, World!" l r
Herro, Worrd!

PS C:\Tools\Scripts\golfing> .\string-shenanigans.ps1 "Slithery snakes slurp Smoothies through Silly Straws" s z
zlithery znakez zlurp zmoothiez through zilly ztrawz

PS C:\Tools\Scripts\golfing> .\string-shenanigans.ps1 "019 + 532 * 281 / ? = waht/?" / !
019 + 532 * 281 ! ? = waht!?

Saved 3 bytes thanks to briantist

You can make this shorter: param($a,$b,$c)$a-replace$b,$c . Powershell is case insensitive by default, no need to be explicit with -ireplace here, saves 1 byte, and by removing () from the replace you can save 2 more bytes.

@briantist That's a good point. One of the test cases I came up with yesterday broke without the i, but now I can't seem to duplicate that. And good call on removing the parens, too. I miss those more often than not. Regarding the regex ... the input requirements explicitly list "single character" so unless $b is a ., we'll be fine.

You're correct; I've removed my comments about the regex, it's not an issue.

Scala, 59 bytes
(s:String,a:Char,b:Char)=>(s"(?i)$a"r).replaceAllIn(s,""+b)

An anonymous function that uses s"" alongwith ""r to dynamically build a case-insensitive regex.

Ruby, 17 bytes
f=->s,*r{s.tr *r}

For example:
> f["Hello there!", ?e, ?a]
=> Hallo thara!

R, 28
function(s,c,r)gsub(c,r,s,T)

Had the order of the arguments been (c,r,s), I thought of doing
functional::Curry(gsub,i=T)

functional is a 3rd-party package whose Curry functional allows redefining function arguments: here, returns a function like gsub but with the modified ignore.case = TRUE.

You can save two bytes using positional parameters rather than named parameters with partial matching. That is, you can use gsub(c,r,s,T) since ignore.case is the fourth positional argument.

Also this is 30 bytes, not 29.

For the same length function(s,c,r)chartr(c,r,s)

@MickyT, but chartr is case-sensitive.

My bad sorry.  I didn't think it through properly.

CJam, 18 17 bytes
Kind of awkward handling the quotes and upper vs. lower case. But I believe it works for all cases:
l'"%~S%(eu_el+\er

Try it online
Thanks to @Dennis for golfing 1 byte.
Note that this is a full program that takes the input exactly as specified in the question. I can make this shorter if the input requirements are interpreted more flexibly.
Explanation:
l     Get input.
'"%   Split at quotes. This separates the string from the remaining arguments,
      and gets rid of the quotes.
~     Unwrap the list. We now have two strings on the stack, the input text
      and a string containing the two letters.
S%    Split the string containing the two letters.
(     Pop off the first ("source") letter.
eu    Convert it to upper case.
_el   Copy and convert to lower case.
+     Concatenate the two, giving us a string with upper and lower case.
\     Swap the second ("target") letter to top.
er    Transliterate.

You don't need the last ~. The result won't be a string, but the output won't look different.

C#, 93 120 124 123 bytes
class A{static void Main(string[]a){System.Console.Write(a[0].Replace(a[1].ToLower(),a[2]).Replace(a[1].ToUpper(),a[2]));}}

Not sure if I can golf this much better than this, but surprisingly low byte count for C# =D
EDIT: Thanks, Reto Koradi for pointing out the case sensitivity.
EDIT 2: More stuff I missed out on. Maybe doing this during a break in work isn't the best time.

Does this replace both upper and lower case letters? I don't know C# at all, but I would be surprised if a simple Replace() method replaces in a case insensitive way.

Why do you assume that the char to replace in in lower case? 2. Why are you writing the full program if you can write a function? 3. You don't need using if use string and System.Console. Anyway, I think, it can be ignored in case of a function.

Thanks for the tip regarding the using @Qwertiy. Dunno what I was thinking there. In terms of writing a program, the question is asking for a program.

"a program or function" in current question text.

string with lowercase first letter. With uppercase one it requires System. And you can remove space after [].

By the way - great idea to allow command line to parse the string.

Bash 4.0+, 21 bytes
Command-line arguments.
tr ${2^}${2,} $3<<<$1

C++ 11, Stand-alone: 213 202 198 bytes
Since I haven't seen a solution on C++ yet, I decided to try something myself.
This is my first version and I will try to optimize it later.
Source code running:
Live Version: 213
202
198 bytes
#include <algorithm>
#include <iostream>
using namespace std;int main(){string a;getline(cin,a);char b,c;cin.get(b);cin.get(c);replace_if(begin(a),end(a),[b](char d){return!((d-b)%32);},c);cout<<a;}

.
Only the replace function: 121 110 107 bytes
getline(cin,a);cin.get(b);cin.get(c);replace_if(begin(a),end(a),[b](char d){return!((d-b)%32);},c);cout<<a;

.
Feedback is welcome.

Shell 15 bytes:
sed s/$1/$2/gi

Save as submission.sh and run as:
$ echo "Hello, World" | ./submission.sh h e
eello, World

Explanation:
sed (stream editor) has a substitute command, which parses standard input and substitutes string $1 for string $2. The g modifier substitutes globally in the input string, and i modifier produces a case-insensitive match.
Old Solution:
Shell, 14 bytes submission_1.sh
tr $2 $3<<<$1

Call with
$ ./submission_1.sh 'hello there!lgge lfewf lger3%#@ %@#T @EG' l r
herro there!rgge rfewf rger3%#@ %@#T @EG

Alternate, Shell 9 bytes: submission_2.sh (May be too rule-bendy)
tr $1 $2

Call with
$ ./submission_2.sh l r <<<'hello there!lgge lfewf lger3%#@ %@#T @EG'
herro there!rgge rfewf rger3%#@ %@#T @EG

Explanation
tr by default (without any flags) replaces all chars in the first set with the chars in the second set, completing the operation with the data on standard input.
I'm using this to my advantage by calling TR with the arguments in the correct order, and (in the alternate submission) taking advantage of the handling of standard input by Bourne Shell (sh) to pass standard input to tr without any additional code.

This doesn't seem to comply with “Case should be ignored, so the input "yolO" o u should output yulu.”

WRT your new solution, does the input not all have to be a single list of args ?

@User112638726 It accepts three args, two presented on the command line, and one presented on standard input. Does this answer your question?

Pyth, 7 19? / 15 bytes
jwcjrz1cwrz0rz1

Example Input
(My second Pyth program, ever). Any tips on golfing are welcome. A lot of the bytes are going to the repeated rz1/rz0. I could chop some of these I could be guaranteed the case.

If quotes are required, a slightly larger 19-byte program handles that:
jwcjrz1c:w1_1rz0rz1

Explanation:
This basically. Takes a string:
Slithery snaKEs

Then, chops all lowercase instances of the the character to replace.
['Slithery ','naKE','']

Then joins with the uppercase instance:
Slithery SnaKES

Then chops on the uppercase instance:
['','lithery ','naKE']

Then joins with the new character:
qlithery qnaKEq

no it doesn't. It lower cases the entire thing.

@Maltysen fixed

This does not take the specified input format. All 3 inputs are on a single line, in the given order. More importantly, the input string is in quotes, while the output string is not. Just try copying and pasting the sample inputs to see if your solutions work or not.

@RetoKoradi I don't think input is that strict. If that were true majority of the answers would work.

The order might be flexible, not sure how the rules would handle that. But it clearly says "an indefinite line of characters surrounded by quotation marks". So that part is definitely not optional.

@RetoKoradi Hm, I justified myself from this answer but I'll modify the code to work with that

Pyth - 11 bytes
A simple regexp solution with case insensitive. Will try to translate to Retina if I get it to compile.
:Q+"(?i)"ww

Test Suite.

I don't think this meets the input requirements. It says that "an indefinite line of characters surrounded by quotation marks", while the output does not have quotation marks. If I run your code with quotation marks, they also show up in the output.

@RetoKoradi sorry, fixing.

It looks like we don't have consensus on the input requirements. Some people interpret them differently.

mSL, 68 bytes
$replace($gettok($1-,-3-1,32),$gettok($1-,-2,32),$gettok($1-,-1,32))

Sed, 43 Chars
:;s/(.)(.*\1 (.))$/\3\2/I;t;s/(. .$|")//g

Invoked with the -r flag for extended regex.

The flag actually costs 3 bytes (one of the surrounding spaces is counted as well). That is, unless you would invoke with sed with something like -e anyway and adding the flag would turn this into -re in which case you'd only count 1 byte. See here, section "Special invocations" for the official consensus.

@MartinBüttner Ok thanks,updated :)

@MartinBüttner Would using a flag to indicate that it should be run as a script file be counted? What about c++ compiler flags etc?

I think flags to run the code from the file would be considered standard and not counted. Compiler flags on the other hand generally are counted (except stuff that you need anyway like linker flags).

Python, 58 bytes
Uses case-insensitive regex for substitution.
from re import*
lambda s,t,u:compile(escape(t),I).sub(u,s)

PHP, 44 Bytes
<?=str_ireplace($argv[2],$argv[3],$argv[1]);

Called from the command line via php golf.php "Grant Bowtie: Only the best future bass artist ever" : -

Python 2.7, 117 bytes
def r(s): print ''.join([list(s)[-1]  if x.lower() == list(s)[-3] else x if x != '\"' else '' for x in list(s)][:-4])

Python certainly won't compare to other golfing languages for this challenge, but nothing beats it for list (in)comprehensions.
If you want it to be a 'standalone' program it increases the size to about 120
import sys
if __name__ == "__main__":
  l, y, z = sys.argv[1:]
  print ''.join([z  if x.lower() == y else x for x in l])

Hey, welcome to PPCG! Your code can be shortened a bunch by dropping whitespace and converting it to a lambda. I also believe you can take the input as 3 separate arguments, which would shorten your code again. Happy golfing! :)

Shell, 34 27 35 bytes
#!/bin/sh
echo $1|sed "s/$2/$3/gi"

Lua, 36 bytes
a=arg[1]:gsub(arg[2],arg[3])print(a)

This doesn't seem to comply with “Case should be ignored, so the input "yolO" o u should output yulu.”

Javascript ES6, 54 chars
f=s=>s.replace(/(.)(?=.* \1 (.)$)/ig,"$2").slice(1,-5)

Gema, 40 characters
"*" ? ?=@subst{\\C@quote{?}=@quote{?};*}

Sample run:
bash-4.3$ gema '"*" ? ?=@subst{\\C@quote{?}=@quote{?};*}' <<< '"Hello, World!" l r'
Herro, Worrd!

O, 31 bytes
i`' /l3-{' \++}d`'"-"(?i)"@+@%p

Perl, 33 chars (without !#) 48 (including !#)
#!/usr/bin/perl
($_,$b,$c)=@ARGV;
s/$b/$c/i;
print;

My first golf, one of my first perl programs. Probably could be golfed a little more


text:
Radiation Hardened Quine
As you should (hopefully) know, a radiation hardened quine is a quine that you can remove any one character from and still print its original, pre-modified source. The thing is, with most of these you can only remove one character; otherwise everything breaks down. This is where this comes in; your goal is to build a radiation-hardened quine that can take as many character removals as possible. Any language that complies with the rules is fine.
Rules

The program must be at least one character long
The language used must be turing complete (So languages like HQ9+ don't qualify)
All other rules that apply to normal quines also apply here.
The solution with the least program_length^(2/n) in which any set of exactly n characters can be removed while still printing the original source code wins.

I'm trying to come up with a solution in Subleq. I think it would be ideal for this kind of challenge!

Related.

Maybe change the name, given this isn't the same as a radiation hardened quine? Perhaps "radiation-proof quine"?

@Cyoce The only difference I can tell is that this challenge is for any number of removals, while most (if not all) other radiation-hardened quines only allow for one.

Ruby solution from the famous "mame". https://github.com/mame/radiation-hardened-quine

IMO It's a bit too easy in GolfScript: 1

Perl, 1116 1124 bytes, n=3, score=1124^(2/3) or approximately 108.1
Update: I've now verified that this works with n=3 via brute force (which took a couple of days); with a program this complex, it's hard to check for radiation-resistance by hand (and I made one mistake in a previous version, which is why the byte count increased). End update
I recommend redirecting stderr somewhere that you won't see it; this program produces a ton of warnings about dubious syntax even when you aren't deleting characters from it.
It's possible that the program can be shortened. Working on this is fairly painful, making it easy to miss possible micro-optimizations. I was mostly aiming to get the number of deletable characters as high as possible (because that's the really challenging part of the program), and treated the code-golf tiebreak as something that was nice to aim for but as something I wouldn't put ridiculous effort into optimizing (on the basis that it's very easy to break radiation resistance by accident).
The program
Note: there's a literal Control-_ character (ASCII 31) immediately before each of the four occurrences of -+. I don't think it copy-and-pasted onto StackOverflow correctly, so you'll have to re-add it before running the program.
eval+<eval+<eval+<eval+(q(FoPqOlengthFoBBPP181XXVVVVJJJKKKNdoWchopJFtPDevalMODx4KNFrPIPA-MN-TUV-ZPINFsPIFoPqOI.Fo.IQNevalFoINevalIFsPZyI.Fr.IT-UPINsayDFtJqJFsKPZyPT-UFWrYrKD.DEEEEQDx6NsayDNDforB1..4YforB1..4NexitQNevalFo)=~y=A-Z=-+;-AZz-~=r)####>####>####>####>####>####>
;
;
;
;
eval+<eval+<eval+<eval+(q(FoPqOlengthFoBBPP181XXVVVVJJJKKKNdoWchopJFtPDevalMODx4KNFrPIPA-MN-TUV-ZPINFsPIFoPqOI.Fo.IQNevalFoINevalIFsPZyI.Fr.IT-UPINsayDFtJqJFsKPZyPT-UFWrYrKD.DEEEEQDx6NsayDNDforB1..4YforB1..4NexitQNevalFo)=~y=A-Z=-+;-AZz-~=r)####>####>####>####>####>####>
;
;
;
;
eval+<eval+<eval+<eval+(q(FoPqOlengthFoBBPP181XXVVVVJJJKKKNdoWchopJFtPDevalMODx4KNFrPIPA-MN-TUV-ZPINFsPIFoPqOI.Fo.IQNevalFoINevalIFsPZyI.Fr.IT-UPINsayDFtJqJFsKPZyPT-UFWrYrKD.DEEEEQDx6NsayDNDforB1..4YforB1..4NexitQNevalFo)=~y=A-Z=-+;-AZz-~=r)####>####>####>####>####>####>
;
;
;
;
eval+<eval+<eval+<eval+(q(FoPqOlengthFoBBPP181XXVVVVJJJKKKNdoWchopJFtPDevalMODx4KNFrPIPA-MN-TUV-ZPINFsPIFoPqOI.Fo.IQNevalFoINevalIFsPZyI.Fr.IT-UPINsayDFtJqJFsKPZyPT-UFWrYrKD.DEEEEQDx6NsayDNDforB1..4YforB1..4NexitQNevalFo)=~y=A-Z=-+;-AZz-~=r)####>####>####>####>####>####>
;
;
;
;

The explanation
This program is, quite clearly, made out of four identical smaller programs concatenated together. The basic idea is that each copy of the program will verify whether it's been damaged too badly to run or not; if it has been, it will do nothing (other than possibly spew warnings) and let the next copy run; if it hasn't been (i.e. no deletions, or the character that got deleted was one that makes no difference to the program's operation), it will do its quiny thing (printing out the full program's source code; this is a proper quine, with each part containing an encoding of the entire source code) and then exit (preventing any other undamaged copies from printing the source code out again and thus ruining the quine by printing too much text).
Each part is in turn made of two parts which are effectively functionally independent; an outside wrapper and some internal code. As such, we can consider them separately.
Outside wrapper
The outside wrapper is, basically, eval<+eval<+eval< ... >####>####...>### (plus a bunch of semicolons and newlines whose purpose should be pretty obvious; it's to ensure that the parts of the program will remain separated regardless of if some of the semicolons, or the newlines before them, get deleted). This might look fairly simple, but it's subtle in a number of ways, and the reason I picked Perl for this challenge.
First, let's look at how the wrapper functions in an undamaged copy of the program. eval parses as a built-in function, which takes one argument. Because an argument is expected, + here is a unary + (which will be very familiar to Perl golfers by now; they come in useful surprisingly often). We're still expecting an argument (we just saw a unary operator), so the < that comes next is interpreted as the start of the <> operator (which takes no prefix or postfix arguments, and thus can be used in operand position).
<> is a fairly weird operator. Its usual purpose is to read filehandles, and you place the filehandle name inside the angle brackets. Alternatively, if the expression isn't valid as a filehandle name, it does globbing (basically, the same process that UNIX shells use to translate text entered by the user to a sequence of command-line arguments; much older versions of Perl actually used the shell for this, but nowadays Perl handles the globbing internally). The intended use, therefore, is along the lines of <*.c>, which would typically return a list like ("foo.c", "bar.c"). In a scalar context (such as the argument to eval), it just returns the first entry it finds the first time it's run (the equivalent of the first argument), and would return other entries on hypothetical future runs that never happen.
Now, shells often handle command-line arguments; if you give something like -r with no arguments, it'll just be passed to the program verbatim, regardless of whether there's a file with that name or not. Perl acts the same way, so as long as we ensure that there are no characters that are special to the shell or to Perl between the < and the matching >, we can effectively use this like a really awkward form of string literal. Even better, Perl's parser for quote-like operators has a compulsive tendency to match brackets even in contexts like this one where it makes no sense, so we can nest <> safely (which is the discovery needed for this program to be possible). The major downside of all these nested <> is that escaping the contents of the <> is almost impossible; there seem to be two layers of unescaping with each <>, so to escape something on the inside of all three, it needs to be preceded with 63 backslashes. I decided that even though code size is only a secondary consideration in this problem, it almost certainly wasn't worth paying this sort of penalty to my score, so I just decided to write the rest of the program without using the offending characters.
So what happens if parts of the wrapper get deleted?

Deletions in the word eval cause it to turn into a bareword, a string with no meaning. Perl doesn't like these, but it treats them as though they were surrounded with quotes; thus eal<+eval<+... is interpreted as "eal" < +eval<+.... This has no effect on the program's operation, because it's basically just taking the result from the heavily nested evals (which we don't use anyway), casting it to an integer, and doing some pointless comparisons on it. (This sort of thing causes a lot of warning spam as it's clearly not a useful thing to do under normal circumstances; we're just using it to absorb deletions.) This changes the number of closing angle brackets we need (because the opening bracket is now being interpreted as a comparison operator instead), but the chain of comments at the end ensures the string will end safely no matter how many times it's nested. (There are more # signs than strictly needed here; I wrote it like I did in order to make the program more compressible, letting me use less data to store the quine.)
If a < gets deleted, the code now parses as eval(eval<...>). The secondary, outside eval has no effect, because the programs we're evaluating don't return anything that has any real effects as a program (if they return normally at all, it's normally a null string or a bareword; more commonly they return via exception, which causes eval to return a null string, or use exit to avoid returning at all).
If a + gets deleted, this has no immediate effect if the adjacent code is intact; unary + has no effect on the program. (The reason the original +s are there is to help repair damage; they increase the number of situations in which < is interpreted as a unary <> rather than as a relational operator, meaning you need more deletions to produce an invalid program.)

The wrapper can be damaged with enough deletions, but you need to do a series of deletions in order to produce something that doesn't parse. With four deletions, you can do this:
eal<evl<eval+<...

and in Perl, the relational operator < is nonassociative, and thus you get a syntax error (the same one you'd get with 1<2<3). As such, the cap for the program as written is n=3. Adding more unary +s seems like a promising way to increase it, but as that'd make it increasingly likely that the inside of the wrapper could break too, verifying that the new version of the program works could be very difficult.
The reason the wrapper is so valuable is that eval in Perl catches exceptions, such as (for example) the exception that you get when you try to compile a syntax error. Because this eval is of a string literal, the compile of the string happens at runtime, and if the literal fails to compile, the resulting exception gets caught. This causes eval to return a null string and set the error indicator $@, but we never check either (except by occasionally executing the returned null string in a few mutated versions of the program). Crucially, this means that if something should happen to the code inside the wrapper, causing a syntax error, then the wrapper will just cause the code to do nothing instead (and the program will keep executing in an attempt to find an undamaged copy of itself). Therefore, the inside code doesn't have to be nearly as radiation-proof as the wrapper; all that we care about is that if damaged, it'll either act identically to the nondamaged version of the program, or else it'll crash (allowing eval to catch the exception and continue) or exit normally without printing anything.
Inside the wrapper
The code inside the wrapper, fundamentally, looks like this (again, there's a Control-_ that Stack Exchange won't show immediately before the -+):
eval+(q(...)=~y=A-Z=-+;-AZz-~=r)

This code is written entirely with glob-safe characters, and its purpose is to add a new alphabet of punctuation marks that make it possible to write a real program, via transliterating and evaluating a string literal (we can't use ' or " as our quote marks, but q(…) is also a valid way to form a string in Perl). (The reason for the unprintable character is that we need to transliterate something into the space character without a literal space character in the program; thus we form a range starting at ASCII 31, and catch the space as the second element of the range.) Obviously, if we're producing some characters via transliteration, we have to sacrifice characters to transliterate them from, but uppercase letters aren't very useful and it's much easier to write without access to those than without access to punctuation marks.
Here's the alphabet of punctuation marks that become available as a result of the glob (the upper line shows the encoding, the lower line the character it encodes):

BCDEFGHIJKLMNOPQRSTUVWXYZ
 !"#$%&'()*+;<=>?@AZz{|}~

Most notably, we have a bunch of punctuation marks that aren't glob-safe but are useful in writing Perl programs, together with the space character. I also saved two uppercase letters, the literal A and Z (which encode not to themselves, but to T and U, because A was needed as an upper as well as a lower range endpoint); this allows us to write the transliteration instruction itself using the new encoded character set (although uppercase letters aren't that useful, they're useful in specifying changes to the uppercase letters). The most notable characters that we don't have available are [, \, and ], but none are needed (when I needed a newline in the output, I produced it using the implicit newline from say rather than needing to write \n; chr 10 would also have worked but is more verbose).
As usual, we need to worry about what happens if the inside of the wrapper gets damaged outside the string literal. A corrupted eval will prevent anything running; we're fine with that. If the quote marks get damaged, the inside of the string isn't valid Perl, and thus the wrapper will catch it (and the numerous subtractions on strings mean that even if you could make it valid Perl, it'd do nothing, which is an acceptable outcome). Damage to the transliteration, if it isn't a syntax error, will mangle the string being evaluated, typically causing it to become a syntax error; I'm not 100% sure there are no cases in which this breaks, but I'm brute-forcing it at the moment to make sure, and it should be easy enough to fix if there are.
The encoded program
Looking inside the string literal, reversing the encoding I used, and adding whitespace to make it more readable, we get this (again, imagine a control-underscore before the -+, which is encoded as A):
$o=q<
  length$o  ==181 || zzzz((()));
  do {
    chop ($t = "eval+<"x4);
    $r = '=-+;-AZz-~=';
    $s = '$o=q<' . $o . '>;eval$o';
    eval '$s=~y' . $r . 'A-Z=';
    say "$t(q($s)=~y=A-Z${r}r)" . "####>"x6;
    say ";" for 1..4
  } for 1..4;
  exit>;
eval $o

People who are used to quines will recognise this general structure. The most crucial part is at the start, where we verify that $o is undamaged; if characters have been deleted, its length won't match 181, so we run zzzz((())) which, if it isn't a syntax error due to unmatched brackets, will be a runtime error even if you delete any three characters, because none of zzzz, zzz, zz, and z is a function, and there's no way to prevent it parsing as a function other than deleting ((( and causing an obvous syntax error. The check itself is also immune to damage; the || can be damaged to | but that will cause the zzzz((())) call to run unconditionally; damaging variables or constants will cause a mismatch because you're comparing one of 0, 180, 179, 178 for equality to some subset of the digits of 181; and removing one = will cause a parse failure, and two = to inevitably cause the LHS to evaluate to either integer 0 or a null string, both of which are falsey.
Update: This check was slightly wrong in a preceding version of the program, so I had to edit it to fix the issue. The previous version looked like this after the decode:
length$o==179||zzzz((()))

and it was possible to delete the first three punctuation marks to get this:
lengtho179||zzz((()))

lengtho179, being a bareword, is truthy and thus breaks the check. I fixed this by adding an extra two B characters (which encode space characters), meaning the latest version of the quine does this:
length$o  ==181||zzzz((()))

Now it's impossible to hide both the = signs and the $ sign without producing a syntax error. (I had to add two spaces rather than one because a length of 180 would put a literal 0 character into the source, which could be abused in this context to integer-compare zero with a bareword, which succeeds.) End update
Once the length check passes, we know the copy is undamaged, at least in terms of character deletions from it, so it's all just straightforward quining from there (substitutions of punctuation marks due to a corrupted decoding table wouldn't be caught with this check, but I've already verified via brute-forcing that no three deletions from only the decoding table break the quine; presumably most of them cause syntax errors). We have $o in a variable already, so all we need to do is hardcode the outside wrappers (with some small degree of compression; I didn't skip out the code-golf part of the question entirely). One trick is that we store the bulk of the encoding table in $r; we can either print it literally in order to generate the encoding table section of the inside wrapper, or concatenate some code around it and eval it in order to run the decoding process in reverse (allowing us to figure out what the encoded version of $o is, having only the decoded version available at this point).
Finally, if we were an intact copy and thus could output the entire original program, we call exit in order to prevent the other copies also trying to print the program out.
Verification script
Not very pretty, but posting it because someone asked. I ran this several times with a variety of settings (typically changing $min and $max to check for various areas of interest); it wasn't a fully automated process. It has a tendency to stop running due to heavy CPU load elsewhere; when this happened, I just changed $min to the first value of $x that wasn't fully checked and continued running the script (thus ensuring that all the programs in the range got checked eventually). I only checked deletions from the first copy of the program, because it's fairly obvious that deletions from the other copies can't do more.
use 5.010;
use IPC::Run qw/run/;
undef $/;
my $program = <>;
my $min = 1;
my $max = (length $program) / 4 - 3;
for my $x ($min .. $max) {
    for my $y ($x .. $max) {
        for my $z ($y .. $max) {
            print "$x, $y, $z\n";
            my $p = $program;
            substr $p, $x, 1, "";
            substr $p, $y, 1, "";
            substr $p, $z, 1, "";
            alarm 4;
            run [$^X, '-M5.010'], '<', \$p, '>', \my $out, '2>', \my $err;
            if ($out ne $program) {
                print "Failed deleting at $x, $y, $z\n";
                print "Output: {{{\n$out}}}\n";
                exit;
            }
        }
    }
}

say "All OK!";

The OP is a little ambiguous; but I thought the score would be (1116*1116)/3.

@GregMartin: (1116*1116)/3 is 415152, so this entry would still be winning under those circumstances. However, I don't think the OP can mean that because it'd give very little incentive to be able to handle the removal of multiple characters. This quine can be less than half the length if you only need it to handle one character removal; that would give me an effective ÷ 4 on the score if we interpret it like that, which would outweigh the ÷ 3 that I get from n=3, and thus mean that the less interesting n=1 entries are actually better scoring.

I made the scoring clearer. Anyways, this is absolutely incredible; didn't think anyone would get n > 1.

It says something about Perl that it's easier to write a program without letters than without punctuation

Befunge-98, 884, n = 14, score ≈ 2.636
f00f00f00f00f00f00f00f00f00f00f00f00f00f00f0xxxxxxxxxxxxxxx"""""""""""""""fffffffffffffff'''''''''''''''000000000000000\\\\\\\\\\\\\\\'''''''''''''''000000000000000\\\\\\\\\\\\\\\'''''''''''''''fffffffffffffff\\\\\\\\\\\\\\\111111111111111---------------:::::::::::::::!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!000000000000000aaaaaaaaaaaaaaa---------------bbbbbbbbbbbbbbb---------------***************jjjjjjjjjjjjjjj$$$$$$$$$$$$$$$'''''''''''''''+++++++++++++++kkkkkkkkkkkkkkk,,,,,,,,,,,,,,,333333333333333kkkkkkkkkkkkkkk$$$$$$$$$$$$$$$000000000000000{{{{{{{{{{{{{{{'''''''''''''''888888888888888uuuuuuuuuuuuuuu'''''''''''''''!!!!!!!!!!!!!!!111111111111111+++++++++++++++'''''''''''''''xxxxxxxxxxxxxxx###############;;;;;;;;;;;;;;;:::::::::::::::!!!!!!!!!!!!!!!kkkkkkkkkkkkkkk@@@@@@@@@@@@@@@dddddddddddddddkkkkkkkkkkkkkkk:::::::::::::::eeeeeeeeeeeeeeekkkkkkkkkkkkkkk,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;

Try it online!
This doesn't just work when you remove exactly 14 characters, but even when you remove any amount up to 14 characters.
n = 14 may seem like a very arbitrary choice, but the technique I used can in fact only be used for radiation-hardening orders from 1 to 14, but not easily beyond that (it might be possible but I have no clue how). The order-1 quine is merely 73 bytes (although it employs some golfing tricks that don't apply to larger n):
200 20 xx""''ÈÈ..aa22**..33kk$$00{{''!!uu''!!11++''xx##;;::!!kk@@::,,,,;;

Explanation
When I was working on this answer I found that it's possible to set the instruction pointer's delta to (2,0) under radiation-hardened conditions with the following snippet:
20020xx

See that answer for why this works. I found this just with a bit of fiddling by hand, but this raised the question whether there are similar patterns which are robust under removal of multiple characters. So I wrote a short Mathematica script to search for these by brute force:
n = 14;
m = 4;
Print @ FromDigits @ {
      m + 1, 0,
      ## & @@ ((m + 1) IntegerDigits[#, 2, n - 4]),
      m + 1, 0
} & /@ Select[
   Range[0, 2^(n - 4) - 1],
   AllTrue[
     Subsets[{
         m + 1, 0,
         ## & @@ ((m + 1) IntegerDigits[#, 2, n - 4]),
         m + 1, 0
       },
       {n - m, n - 1}
     ] //. {a___, _, m + 1} | {a___, 0, _} :> {a},
     MatchQ@{___, m + 1, 0}
  ] &
];

This very quickly revealed a pattern. To get a corresponding snippet which works for removal of up to n characters, you can use (m0x){n}m0 where m is n+1 and x is either m or 0. So all of the following would work for removal of up to two characters:
30030030
30030330
30330030
30330330

I'm sure it's possible to prove this, but I've simply verified for n up to 7. Of course, this only works as long as we can represent n+1 as a single digit, and the largest such digit in Befunge 98 is f which represents 15. That's why my approach is limited to n = 14. If someone finds a way to reliably set the delta to larger n+1, it would likely be possible to increase the order of this radiation-hardened quine indefinitely.
Let's look at the actual code. There are basically two parts to it. First we set the delta to (15,0) as I just mentioned:
f00f00f00f00f00f00f00f00f00f00f00f00f00f00f0xxxxxxxxxxxxxxx

And the remainder of the code has each command repeated 15 times and prints the source. If we remove the repetition, it looks like this:
"f'0\'0\'f\1-:!!0a-b-*j$'+k,3k$0{'8u'!1+'x#;:!k@dk:ek,;

The " is a standard 2D quining technique: it starts string mode, pushes all the characters (except itself) onto the stack and ends string mode again after wrapping around. This helps us get all the code points of the second half, but it will fail to get us anything useful from the first half, because throughout the f00f00...f0 bit, it will only record two characters (which may be either f or 0 depending on which characters are deleted). But since that part isn't made up of characters being repeated 15 times, we'll need to print it separately anyway.
More conveniently, in the unmodified quine, the length of the string before the " is -1 (mod 15). This guarantees that no matter how many characters (up to 14) we remove, that the number of characters recorded there is always 3 (one x and two of f and 0). This is actually true for any radiation order up to 14.
We now start by printing the f00f00...f0 part:
f'0\'0\'f\1-:!!0a-b-*j$'+k,

f          Push 15, a loop counter.
'0\'0\'f\  Put "00f" underneath the loop counter.
1-         Decrement the loop counter.
:!!        Copy it, and turn it into a 1 if it's positive.
0a-b-      Push -21.
*          Multiply by 0 if the loop counter is zero, or by 1 otherwise.
j          Jump that many steps. If the value was 0, this is a no-op and
           the loop ends. Otherwise, this brings us back after the f.
$          Pop the loop counter (which is now 0).
'+k,       Print the top of the stack 43 times, which gives us all of
           the "f00f00...f0" and leaves one "0" on top of the stack.

The next 3k$ simply discards that 0 as well as the three characters that were pushed by " from the beginning of the program. The stack now contains only the characters after the " as well as some junk underneath from the original f00f00...f0 depending on which characters were deleted.
Now we just need to reverse the top of the stack (containing the remaining characters) and print each one of them 15 times.
0{     Start a new, empty stack. This pushes two zeros onto the original stack.
'8u    Move the top 56 values from the original stack to the new one, which
       is the 54 characters after the " as well as those two zeros. This is
       implemented as pop-push loop, so it reverses the order of those elements.
'!1+   Push a " by incrementing a !.
'x     Push an x. Now we've got all the characters that are repeated 15 times.
#;     Enter a loop. This is a standard technique for Befunge-98: the ; is
       a bit like a comment character, that ignores everything until the next
       ;, but we jump over the first one with #, so that from now on only
       the code inside will be executed (over and over).
  :!     Copy the top of the stack, and compute logical NOT (1 if 0, 0 otherwise).
  k@     Terminate the program that many times (i.e. when the top of the
         stack is zero).
  dk:    Make 14 copies of the top of the stack.
  ek,    Print 15 characters from the top of the stack.
;

And that's it. :)

JavaScript (ES6), 927 bytes, n=1, score=859329
note: don't use a REPL (like a browser console) to run this.
This was written before code length was a factor, so it isn't golfed yet.
This was very difficult, and deserves a thorough explanation. Which I will write later, after I explore this challenge a little more!
etTimeout=stTimeout=seTimeout=setimeout=setTmeout=setTieout=setTimout=setTimeut=setTimeot=setTimeou=unescape=>42;
setTimeout
`c="function f(){x=String.fromCharCode(96);n=String.fromCharCode(10);q=String.fromCharCode(34);y='etTimeout=stTimeout=seTimeout=setimeout=setTmeout=setTieout=setTimout=setTimeut=setTimeot=setTimeou=unescape=>42;'+n;z='setTimeout'+n+x+'c='+q+f+';f();_=1'+q+';if(window._);else if(c.length>339)eval(c)//'+x+'///'+x+n+n;console.log(y+z+z)};f();_=1";if(window._);else if(c.length>339)eval(c)//`///`

setTimeout
`c="function f(){x=String.fromCharCode(96);n=String.fromCharCode(10);q=String.fromCharCode(34);y='etTimeout=stTimeout=seTimeout=setimeout=setTmeout=setTieout=setTimout=setTimeut=setTimeot=setTimeou=unescape=>42;'+n;z='setTimeout'+n+x+'c='+q+f+';f();_=1'+q+';if(window._);else if(c.length>339)eval(c)//'+x+'///'+x+n+n;console.log(y+z+z)};f();_=1";if(window._);else if(c.length>339)eval(c)//`///`

note: there is a trailing newline
Basically, the first line is carefully constructed to rename all 'mispellings' of setTimeout to valid functions, so that if a character is removed from one of the setTimeouts the code will not error out and the unscathed version can run. It is also written so that if any one character is removed from the first line, there will be no error and the rest of the code can run unaffected.
The second and third blocks are exactly equivalent. If one runs to completion, it sets the _ variable so that the other knows not to duplicate the quine. If one of these blocks errors out, it does not affect the other block because it was called asynchronously using setTimeout. The error will cause _ not to be set, so the other block will quine successfully. The main code is in a string, which is checked for length in each block to make sure that there were no removals.
Template strings on the next line with some comments at the end of the template strings protects the code from erroring out if one of the backticks forming the template string is removed. If the ending backtick is removed, the template string is ended by the backtick in the comment. If the starting backtick is removed, setTimeout is evaluated as an unassigned function (a no-op) and the code runs as normal, without a setTimeout. The ending backtick is nullified by another comment.

What's that you say? You want to try it out? Say no more!
Full page mode recommended.
Ignore the input box, this snippet takes no input.
Try removing any one character from the code!
Don't believe it? Normal code will still work (but it won't quine...) Try something like console.log(5)!
note: the snippet had to be modified slightly to disable the REPL feature, so I removed multiple output capabilities for this answer only.

etTimeout=stTimeout=seTimeout=setimeout=setTmeout=setTieout=setTimout=setTimeut=setTimeot=setTimeou=unescape=>42;
setTimeout
`c="function f(){x=String.fromCharCode(96);n=String.fromCharCode(10);q=String.fromCharCode(34);y='etTimeout=stTimeout=seTimeout=setimeout=setTmeout=setTieout=setTimout=setTimeut=setTimeot=setTimeou=unescape=>42;'+n;z='setTimeout'+n+x+'c='+q+f+';f();_=1'+q+';if(window._);else if(c.length>339)eval(c)//'+x+'///'+x+n+n;console.log(y+z+z)};f();_=1";if(window._);else if(c.length>339)eval(c)//`///`

setTimeout
`c="function f(){x=String.fromCharCode(96);n=String.fromCharCode(10);q=String.fromCharCode(34);y='etTimeout=stTimeout=seTimeout=setimeout=setTmeout=setTieout=setTimout=setTimeut=setTimeot=setTimeou=unescape=>42;'+n;z='setTimeout'+n+x+'c='+q+f+';f();_=1'+q+';if(window._);else if(c.length>339)eval(c)//'+x+'///'+x+n+n;console.log(y+z+z)};f();_=1";if(window._);else if(c.length>339)eval(c)//`///`
<!--                               Try the test suite below!                              --><strong id="bytecount" style="display:inline; font-size:32px; font-family:Helvetica"></strong><strong id="bytediff" style="display:inline; margin-left:10px; font-size:32px; font-family:Helvetica; color:lightgray"></strong><br><br><pre style="margin:0">Code:</pre><textarea id="textbox" style="margin-top:5px; margin-bottom:5px"></textarea><br><pre style="margin:0">Input:</pre><textarea id="inputbox" style="margin-top:5px; margin-bottom:5px"></textarea><br><button id="testbtn">Test!</button><button id="resetbtn">Reset</button><br><p><strong id="origheader" style="font-family:Helvetica; display:none">Original Code Output:</strong><p><div id="origoutput" style="margin-left:15px"></div><p><strong id="newheader" style="font-family:Helvetica; display:none">New Code Output:</strong><p><div id="newoutput" style="margin-left:15px"></div><script type="text/javascript" id="golfsnippet">var bytecount=document.getElementById("bytecount");var bytediff=document.getElementById("bytediff");var textbox=document.getElementById("textbox");var inputbox=document.getElementById("inputbox");var testbtn=document.getElementById("testbtn");var resetbtn=document.getElementById("resetbtn");var origheader=document.getElementById("origheader");var newheader=document.getElementById("newheader");var origoutput=document.getElementById("origoutput");var newoutput=document.getElementById("newoutput");textbox.style.width=inputbox.style.width=window.innerWidth-50+"px";var _originalCode=null;function getOriginalCode(){if(_originalCode!=null)return _originalCode;var allScripts=document.getElementsByTagName("script");for(var i=0;i<allScripts.length;i++){var script=allScripts[i];if(script.id!="golfsnippet"){originalCode=script.textContent.trim();return originalCode}}}function getNewCode(){return textbox.value.trim()}function getInput(){try{var inputText=inputbox.value.trim();var input=eval("["+inputText+"]");return input}catch(e){return null}}function setTextbox(s){textbox.value=s;onTextboxChange()}function setOutput(output,s){output.innerHTML=s}function addOutput(output,data){output.innerHTML='<pre style="background-color:'+(data.type=="err"?"lightcoral":"lightgray")+'">'+escape(data.content)+"</pre>"}function getByteCount(s){return(new Blob([s],{encoding:"UTF-8",type:"text/plain;charset=UTF-8"})).size}function onTextboxChange(){var newLength=getByteCount(getNewCode());var oldLength=getByteCount(getOriginalCode());bytecount.innerHTML=newLength+" bytes";var diff=newLength-oldLength;if(diff>0){bytediff.innerHTML="(+"+diff+")";bytediff.style.color="lightcoral"}else if(diff<0){bytediff.innerHTML="("+diff+")";bytediff.style.color="lightgreen"}else{bytediff.innerHTML="("+diff+")";bytediff.style.color="lightgray"}}function onTestBtn(evt){origheader.style.display="inline";newheader.style.display="inline";setOutput(newoutput,"");setOutput(origoutput,"");var input=getInput();if(input===null){addOutput(origoutput,{type:"err",content:"Input is malformed. Using no input."});addOutput(newoutput,{type:"err",content:"Input is malformed. Using no input."});input=[]}doInterpret(getNewCode(),input,function(data){addOutput(newoutput,data)});doInterpret(getOriginalCode(),input,function(data){addOutput(origoutput,data)});evt.stopPropagation();return false}function onResetBtn(evt){setTextbox(getOriginalCode());origheader.style.display="none";newheader.style.display="none";setOutput(origoutput,"");setOutput(newoutput,"")}function escape(s){return s.toString().replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}window.alert=function(){};window.prompt=function(){};function doInterpret(code,input,cb){var workerCode=interpret.toString()+";function stdout(s){ self.postMessage( {'type': 'out', 'content': s} ); }"+" function stderr(s){ self.postMessage( {'type': 'err', 'content': s} ); }"+" function kill(){ self.close(); }"+" self.addEventListener('message', function(msg){ interpret(msg.data.code, msg.data.input); });";var interpreter=new Worker(URL.createObjectURL(new Blob([workerCode])));interpreter.addEventListener("message",function(msg){cb(msg.data)});interpreter.postMessage({"code":code,"input":input});setTimeout(function(){interpreter.terminate()},1E4)}setTimeout(function(){getOriginalCode();textbox.addEventListener("input",onTextboxChange);testbtn.addEventListener("click",onTestBtn);resetbtn.addEventListener("click",onResetBtn);setTextbox(getOriginalCode())},100);function interpret(code,input){_=undefined;window={};alert=function(s){stdout(s)};window.alert=alert;console.log=alert;prompt=function(s){if(input.length<1)stderr("not enough input");else{var nextInput=input[0];input=input.slice(1);return nextInput.toString()}};window.prompt=prompt;(function(){try{_=undefined;eval(code);if(typeof evalResult=="disabled_function_evaluation"){var callResult=evalResult.apply(this,input);if(typeof callResult!="undefined")stdout(callResult)}}catch(e){stderr(e.message)}})()};</script>

A better explanation is forthcoming. In the meantime feel free to ping me in chat @jrich with any comments/questions/criticisms!

ah okay, whoops :|

Use this instead of window.

+1 for including the meaning of life in your source code

source: Stack Exchange

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

sort: votes


text:
Dynamic ASCII Encoder!
Introduction
Some ASCII characters are just so expensive these days...
To save money you've decided to write a program that encodes expensive characters using inexpensive ones.
However, character prices change frequently and you don't want to modify your program every time you need to encode or decode a different character!
You'll need a more dynamic solution.
Challenge
Your task is to write two programs: an encoder and a decoder.
The encoder should accept a list of five inexpensive characters, and a single expensive character.
It should output a single string made up of the inexpensive characters, that encodes the expensive character.
This string may not be longer than 4 characters, to remain inexpensive. However, it does not have to use all of the inexpensive characters in the encoding and encodings may be of different lengths.

The decoder should accept the string outputted by the encoder, and output the expensive character.
The decoder shall accept no input other than the encoded string. It must work, unmodified, from the encoder's output for any (valid) combination of inputs. In other words, your decoder program doesn't know which characters are expensive or inexpensive.
Scoring
Shortest combined code wins!
Notes

All characters will be either uppercase letters [A-Z], lowercase letters [a-z], or numbers [0-9].
The list of inexpensive characters won't contain duplicates. No character will be both inexpensive and expensive.
The encoder and decoder don't have to be written in the same language, but they can be. You may write a program or a function.
Input and output may be in any reasonable format for your language.
The two programs may not share any variables or data.

Summary

Input of some inexpensive characters and an expensive character is given to encoder.
Encoder outputs a string of inexpensive characters, encoding the expensive character.
Decoder is given the encoder's output, and outputs the expensive character.

Examples
Input:     a, b, c, d, e     f
Encoder Possibilities:     a     eeee     caec
Decoder:     f

Input:     a, b, c, d, e     h
Encoder Possibilities:     bc     cea     eeaa
Decoder:     h

Input:     q, P, G, 7, C     f
Encoder Possibilities:     777     P7     PPCG
Decoder:     f

This really just could be me, and I apologize for this question if it is, but how exactly are you supposed to encode your message with the inexpensive characters? Addition of the ASCII codes for the 5 inexpensive characters?
Actually, this question only has a basis if your decoder must decode for all encoding possibilities generated.

To be clear: The Encoder Possibilities are just examples and we can encode each character as we want, yes?

@Dennis Yes, those are just examples.

@Cole Without giving away an actual algorithm, as that is the main challenge here, I believe that it is possible. There are only 62 possible expensive letters to encode, and with these 4 ascii characters up to 92 can be encoded, according to A239914. (huge thanks to PhiNotPi's sandbox comment for this one - I didn't calculate exactly how many could be encoded)

@UndefinedFunction I realize now what you've intended: Dennis's question answered what I was confused about.

For those that are struggling here's a tip: create an enumeration of the weak orderings of 4 elements.

Can encoder and decoder be the in same program?

@Cabbie407 No, the encoder and decoder must be separate programs or functions.

Trying to figure out what the specifications for the encoder should be is extremely frustrating. I know it's possible because there's enough weak ordered combinations (I think) but I'm finding that coming up with a systematic way of mapping each of them to a unique number is difficult for me personally.

@PatrickRoberts Here's a really basic (and untested) version of my encoding idea. jsfiddle link If I've missed anything obvious, let me know. I wrote this after I wrote the challenge, and I'll admit it was pretty difficult... (The explanation's pretty bad, I'd recommend just trying it)

Hah, that's really cool. I think my issue was I was using 1 character just as a reference point.. I'll have to see if I can come up with my own encoding.

Wow, that's genius! So that's what the 5th inexpensive is for. ;) I love that it can encode exactly the 62 ways needed :)

@Cabbie407 thanks! I had a couple other ideas to encode, but this one seemed to work nicely - actually, it wasn't my original idea when I wrote the challenge!

Pyth, 46 bytes
Encoder, 22 bytes
@smfql{Td^<Szd4S4-Cw48

Decoder, 24 bytes
C+48xsmfql{Td^<sS{zd4S4z

Wow, that fits perfectly. 75 different char-combinations and a char-range of 75.

I think you can replace S4 with T and save each one byte in both programs.

CJam, 55 50 48 47 bytes
Encoder, 24 22 21 bytes
l$:L4m*{$L|L=},rc'0-=

Try it online.
Decoder, 31 28 27 26 bytes
4_m*{$4,|4,=},l_$_|f#a#'0+

Try it online.

Is there a CJam syntax sheet out there you use? The one on sourceforge and that other pdf cheat sheet don't contain all the characters you use like '

' is not an operator. You can find it on the syntax page.

gawk, 163 + 165 = 328
Tested with gawk 4.1.1, but should work in older gawk versions as well. Needs to be slightly modified (lengthened) to work with mawk.
encoder (163):
{for(gsub(", ",_);sprintf("%c",++r)!=$NF;asort(a))split($1,a,_);r-=r>64?53:46;for(k=4^5;r-=_~i;j=_)for(i=++k;gsub(++j,_,i);)split(k,b,_);for(j in b)printf a[b[j]]}

decoder (165):
{split($1,a,_);for(i in a)d[a[i]]=a[i];asort(d);for(k=4^5;c!~$1;x+=_~i){i=++k;for(c=j=_;gsub(++j,_,i);split(k,b,_));for(g in b)c=c d[b[g]]}printf"%c",x+(x>10?54:47)}

Well, it works, but I'm aware that this might not be the best approach for this. I have no idea what the fifth inexpensive letter is for, because I use only four.
These are for single use only. If you want to enter a second code you have to restart them. The spaces after the commas are required in the input to encode.
What I thought about
My first question was "What could a decoder get from these 4 characters?" (I'll call them a, b, c and d), and my initial idea was to get 6 bits of Information from following relations:
a>b
a>c
a>d
b>c
b>d
c>d

Wow, 6 bit, that's perfect! I thought it was genius, but testing showed this would not work. There are only 24 possible combinations. Damn.
The next step was trying to count, based on what I already knew. So the first letter appearing in the string would become 0, then the second letter introduced in the string would become 1 and so on. But it wouldn't bring me all the way to the 62 combinations needed.
0000
0001
0010
0011
0012
0100
0101
0102
0110
0111
0112
0120
0121
0122
0123

But I like the idea anyhow.
Well, then it struck me, that I could combine these two, because the characters in the input already have relations, and I wouldn't have to wait until they were introduced to give them a value.
How it works
Note: This is no longer exactly how the golfed versions work, but the principle stayed the same.
For the decoder:
An array is constructed, whose index contains all the four digit numbers whose largest digit isn't greater than the number of distinct digits in that number. There are 75 different four digit numbers meeting that condition. I brute force them, because so far I couldn't figure out a way to construct them, and I'm not sure this would be shorter to do in awk anyway. While I find these I assign them the expensive characters in asciibetical order.
Then I replace every character from the input string with a digit. The smallest (for instance is 'B' smaller than 'a') becomes 1, the second smallest becomes 2, and so on up to 4. Of course it depends on how many different characters are in the input, what the highest digit in the resulting string will be.
Then I simply print the array element, which has that string as an index.
The encoder works accordingly.
How to use
Either copy the code directly in an awk bash line command or make two files "encode.awk" and "decode.awk" and paste the code accordingly. Or even better use the following code, which exits automatically after en/decoding, or can be used multiple times by removing the exit command at the end.
encode.awk
{
    if(!x) # only do first time
        for(i=1e3;i++<5e3;delete a)
        {
            for(m=j=0;p=substr(i,++j,1);p>m?m=p:0)++a[p];
            length(a)>=m&&i!~0?c[(x>9?55:48)+x++]=i:_
        }
    r=u=_; # clear reused variables
    for(gsub(",",FS);sprintf("%c",++r)!=$NF;); # more flexible concerning
    --NF;                                      # spaces in input
    split($0,b);
    asort(b);
    split(c[r],a,_);
    for(j in a)u=u b[a[j]]; # prettier printing than golfed version
    print u
    exit # <=== remove to encode input file
}

decode.awk
{
    if(!x) # only do first time
        for(i=1e3;i++<5e3;delete a)
        {
            for(m=j=0;p=substr(i,++j,1);p>m?m=p:_)++a[p];
            length(a)>=m&&i!~0?c[i]=sprintf("%c",(x>9?55:48)+x++):_
        }
    delete t; delete d; o=_; # clear reused variables
    split($1,a,_);
    for(i in a)t[a[i]]=1;
    for(i in t)d[++y]=i;
    asort(d);
    for(i in a)for(j in d)if(d[j]~a[i])o=o j;
    print c[o]
    exit # <=== remove to encode input file
}

Here is a usage example:
me@home:~/$ awk -f encode.awk
w, 0, R, 1, d X
10R1
me@home:~/$ awk -f decode.awk
10R1
X

Remember that the space after each comma is required, if you use the golfed versions.
If you want, you can use this short and dirty script to generate some sample data
BEGIN{
    for(srand();i++<1000;)
    {
        erg="";
        for(j=0;j++<5;)
        {
            while(erg~(a[j]=substr(c="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",rand()*62+1,1)));
            erg=erg a[j]
        }
        print a[1]", "a[2]", "a[3]", "a[4]", "a[5](rand()>.5?" ":rand()>.5?"  ":"   ")substr(c,rand()*62+1,1)
    }
}

and do something funny like
me@home:~/$ awk -f gen.awk|awk -f encode.awk|awk -f decode.awk|sort -u|wc -l
62

I've seen this more as a programming puzzle. I think it's a little sad, that almost everything on here is golfed, because you can learn a lot more from well documented, readable code, but that's just my opinion. And I golfed it like requested ;)

how to test it? please share some examples.

+1 for the great explanation! Seems there are many different ways to approach this problem :)

This was very similar to my thought process except I didn't realize brute-forcing the unique weak combinations (where you described the largest digit not being greater than the amount of digits) was a viable approach. Kudos for following through.

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


text:
Composite Number Sequences
Inspired by this question
Given a positive integer \$n\$, your code must output the first \$n\$ composite numbers.
Input / Output
You may write a program or a function. Input is through STDIN or function argument and output is to STDOUT, or function return value.
Output can be a List, Array, or String.
Examples
 0 ->
 1 -> 4
 2 -> 4, 6
 3 -> 4, 6, 8
13 -> 4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 22

Rules

As always standard loopholes are disallowed.

Built-ins that generate prime or composite numbers are not allowed.

Built-ins relating to prime or composite numbers are not allowed.

Of course, it's on OEIS: A002808

Pyth - 10 bytes
A valid answer. Uses Wilson's Theorem.
.f%h.!tZZQ

Try it online here.

Old answer
Pyth - 6 chars
Uses builtin for prime factorization, not prime checking.
.ftPZQ

Try it online here.
.f  Q         First n that passes filter of lambda Z, uses input for how many
 t            Tail. This makes all that have len-one prime factorization become empty list, and thus falsey.
  P           Prime factorization - primes have a len-one factorization.
   Z          Lambda var

Hm, should of thought about that :/

The rules have changed and thus this answer is no longer valid.

@orlp updated answer.

@Maltysen Isn't this 10 bytes?

@kirbyfan64sos :/ I apparently can't read the length counter. Fixing.

Pyth, 11 bytes
<S{*M^tSQ2Q

Generates overly large list of products of all combinations of [2, n] and truncates.

It does not work if the input is 1 or 2.

TeX, 382 bytes
Because you can.
\newcount\a\newcount\b\newcount\c\newcount\n\newcount\p\newcount\q\let\v\advance\let\e\else\let\z\ifnum
\def\d#1:#2:#3:{\z#1>#2\v#1 by-#2\d#1:#2:#3:\e\z#1=#2#3=1\e#3=0\fi\fi}
\def\i#1:#2:#3:{#3=0\z#1>#2\a=#1\d\a:#2:\c:
\z\c=0\b=#2\v\b by 1\i#1:\the\b:#3:\e#1\par\fi\e#3=1\fi}
\def\l#1:#2:#3:#4:{\i\the#1:2:#4:
\z#4=0\v#2 by 1\fi\z#2<#3\v#1 by 1\l#1:#2:#3:#4:\fi}
\l\p:\n:10:\q:\end

The number in the last line is the number of composite numbers you want to have.
This is a simple divisor tester. \d checks if #2 divides #1. \i calls  \d for all possible dividers (i.e. < #1). \l lists the first #2 numbers for which \i returns 0.
Ungolfed (well, half-golfed) version:
\newcount\a
\newcount\b
\newcount\c
\newcount\n
\newcount\p
\newcount\q

\def\div#1:#2:#3:{%
  \ifnum#1>#2 %
    \advance#1 by-#2 %
    \div#1:#2:#3:%
  \else%
    \ifnum#1=#2 %
      #3=1%
    \else%
      #3=0%
    \fi%
  \fi%
}

\long\def\isprime#1:#2:#3:{%
  #3=0%
  \ifnum#1>#2 %
    \a=#1 %
    \div\a:#2:\c: %
    \ifnum\c=0 %
      \b=#2 %
      \advance\b by 1 %
      \isprime#1:\the\b:#3:%
    \else
      #1\par%
    \fi%
  \else%
    #3=1%
  \fi%
}

\def\listprimes#1:#2:#3:#4:{%
  \isprime\the#1:2:#4: %
  \ifnum#4=0 %
    \advance#2 by 1 %
  \fi
  \ifnum#2<#3 %
    \advance#1 by 1 %
    \listprimes#1:#2:#3:#4: %
  \fi
}

\listprimes\p:\n:11:\q:

\end

Welcome to Programming Puzzles and Code Golf! Great first answer in a language nobody thought would be suitable for the challenge. Although it is pretty long, it is unique and neat answering in TeX and we certainly appreciate such answers.

@TanMath thanks for the warm welcome, I realize this is too long to compete, but it was fun :)

Python, 57
lambda n:sorted({(k/n+2)*(k%n+2)for k in range(n*n)})[:n]

Less golfed:
def f(n):
 R=range(n)
 return sorted({(a+2)*(b+2)for a in R for b in R})[:n]

The idea is to generate the set of composite numbers by multiplying all pairs of natural numbers except 0 and 1. Then, sort this set, and take the first n elements. It suffices to take the Cartesian product of the set {2, 3, ..., n+2} with itself, which we can get by shifting range(n) up by 2.
To golf this, we do a classic golfing trick of storing two values (a,b) in range(n) as a single value k in range(n*n), and extract them as a=k/n, b=k%n.

Java 8, 98 97 bytes
i->{int a[]=new int[i],c=3,k=0,d;for(;k<i;c++)for(d=c;d-->2;)if(c%d<1){a[k++]=c;break;}return a;}

Expanded, with boilerplate:
public class C {
    public static void main(String[] args) {
        Function<Integer, int[]> f = i -> {
            int a[] = new int[i], c = 3;
            for (int k = 0; k < i; c++) {
                for (int d = c; d --> 2;) {
                    if (c % d < 1) {
                        a[k++] = c;
                        break;
                    }
                }
            }
            return a;
        };
        System.out.println(Arrays.toString(f.apply(5)));
    }
}

R, 53 bytes
n=scan();t=1:(n*n+3);t[factorial(t-1)%%t!=(t-1)][1:n]

How it works
This is also based on Wilson's theorem and all it does is to run over a range of 1:n*n and extract the composite numbers according to the above mentioned theorem. I've added +3 because n*n isn't big enough range for n < 3 integers

The only problem with this solution is that (sadly) R loses precision for a big enough factorial, thus, this won't work properly for n > 19

Javascript ES6, 88 chars
n=>{r=[];for(q=2;r.length!=n;++q)if(/^(..+)\1+$/.test("-".repeat(q)))r.push(q);return r}

I believe removing the variable assignment f= is legal.

@DankMemes, seems yes. http://meta.codegolf.stackexchange.com/q/6915/32091

This is 83: n=>eval('for(r=[],q=2;r.length-n;/^(..+)\\1+$/.test("-".repeat(++q))&&r.push(q))r')

@DankMemes, cool :)

@DankMemes, seems like eval doesn't work in this way inside of lambda.

This fiddle works in the latest FF dev edition

@Qwertiy You can replace r.length!=n with n&!r[n-1]. It saves 2 characters.

@toothbrush, your version is correct only if n is odd.

@Qwertiy Sorry, I meant n&&!r[n-1] :'| It is the same length as r.length<n – one character shorter than r.length!=n – but this is supposed to be Code Golf, right? :-]

CJam, 20 18 bytes
li_5*{_,2>f%0&},<`

Try it online
Does not use any built in prime or factorization operators. Fairly brute force check for numbers being composite.
One observation that is used here is that we can easily calculate a safe upper bound for the numbers we have to test. Since every second number larger than 4 is composite, 4 + n * 2 is an upper bound for the n-th composite number.
Based on a suggestion by @Dennis, the latest implementation actually uses n * 5 as the upper limit, which is much less efficient, but 2 bytes shorter.
Explanation:
li    Get and convert input.
_     Copy, will need the value to trim the list at the end.
5*    Calculate upper bound.
{     Start of filter.
  _     Copy value.
  ,     Create list [0 .. value-1].
  2>    Slice off the first two, leaving candidate factors [2 .. value-1].
  f%    Apply modulo with all candidate factors to value.
  0&    Check if one of the modulo results is 0.
},    End of filter.
<     Trim output to n values.
`     Convert list to string.

Haskell, 49 46 bytes
(`take`[x|x<-[4..],or[mod x y<1|y<-[2..x-1]]])

Usage example:
*Main> (`take`[x|x<-[4..],or[mod x y<1|y<-[2..x-1]]]) 13
[4,6,8,9,10,12,14,15,16,18,20,21,22]

How it works
  [x|x<-[4..]    ]           -- keep all x from the integers starting with 4 where
      ,or                    -- where at least one element of the following list is "True"
    [mod x y<1|y<-[2..x-1]]  -- "x mod y < 1" for all y from [2,3,...x-1]
(`take`[   ])                -- take the first n elements from the xes
                             -- where n is the parameter supplied when calling the function

F#, 78 bytes
fun n->(Array.filter(fun i->Seq.exists((%)i>>(=)0)[2..i-1])[|2..n*n|]).[..n-1]

Explained:
fun n->
                                                           [|2..n*n|]          // Generate an array of integers from 2 to n * n
        Array.filter(fun i->                              )                    // Filter it using the following function on each element
                                                  [2..i-1]                        // Generate a list of possible divisors (from 2 to i-1)
                            Seq.exists(          )                                // Check if at least one of the divisors is valid, that is
                                       (%)i>>(=)0                                    // That i % it is equal to 0. This is equivalent to (fun d -> i % d = 0)
       (                                                             ).[..n-1] // Take the n first elements of the resulting, filtered array

This is a great answer, however it is a bit confusing that you use the variable i twice. I'm not too familiar with F#, but couldn't you perhaps use j?

Right, that does make it clearer. It did work due to shadowing, but I guess I forgot about readability while golfing the thing. ^_^'

I don't ever make that sort of mistake. Probably why I'm not good at golfing d:-D

Julia, 103 bytes
n->(n>0&&println(4);n>1&&(i=0;c=big(6);while i<n-1 mod(factorial(c-1),c)<1&&(i+=1;println(c));c+=1end))

This uses Wilson's Theorem.
Ungolfed:
function f(n::Int)
    # Always start with 4
    n > 0 && println(4)

    # Loop until we encounter n composites
    if n > 1
        i = 0
        c = big(6)
        while i < n-1
            if mod(factorial(c-1), c) == 0
                i += 1
                println(c)
            end
            c += 1
        end
    end
end

ECMAScript 6 – 107 91 84 bytes
n=>eval('for(a=[],x=4;n&&!a[~-n];x++)for(y=2;y*2<=x;)if(x%y++<1){a.push(x);break}a')

The function returns an array of the first n composite numbers.

 ~-n is a fancy way of writing n-1; same length, but much more fun, right?
 The only reason I use eval is that the template n=>eval('...returnValue') is 1 character shorter than n=>{...return returnValue}.

Old versions
n=>eval('for(a=[],x=4;n&&!a[~-n];x++){for(z=0,y=2;y*2<=x;)if(x%y++<1)z=1;if(z)a.push(x)}a')

n=>eval('for(a=[],i=4;a.length<n;i++)if((x=>{for(y=2,z=1;y*2<=x;)if(x%y++<1)z=0;return!z})(i))a.push(i);a')

Output
 0 -> []
 1 -> [4]
 2 -> [4, 6]
 3 -> [4, 6, 8]
13 -> [4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 22]

C++ 109
int main(){int n,i,x=4;cin>>n;while(n){for(i=2;i<x-1;i++){if(x%i==0){cout<<x<<' ';n--;break;}}x++;}return 0;}

Ungolfed
int main(){
int n,i,x=4;cin>>n;
while(n)
{
for(i=2;i<x-1;i++)
{
if(x%i==0){cout<<x<<' ';n--;break;}
}
x++;
}
return 0;
}

Why not make a nice formatting for ungolfed version? 2. Seems like you have extra braces in both codes. 3. You can replace while by for.

Haskell, 44 bytes
Heavily inspired by Nimi's earlier answer, replacing the predicate with a 2-byte shorter one based on any with a pointfree lambda instead of a nested list comprehension.
(`take`[x|x<-[4..],any((<)1.gcd x)[2..x-1]])

Try it online!
(thanks to Laikoni for the accurate TIO link)
Explanation:
[x|x<-[4..],       -- consider all integers x >=4
[2..x-1]           -- consider all integers smaller than x
any((<)1.gcd x)    -- if for any of them
    (<)1           -- 1 is smaller than
        .gcd x     -- the gcd of x and the lambda input
                   -- then we found a non-trivial factor and thus the number is composite
(`take`[  ])       -- take the first <argument> entries

Husk, 14 12 bytes
↑fṠöV¬thM%ḣN

Try it online!
-2 bytes from Jo King.
Husk, 8 bytes
↑fȯ≠2LḊN

Try it online!
Uses the Ḋivisors function, if that is okay.

Japt, 9 bytes
Èâ Ê¨3}jU

Try it

Vyxal, 7 bytes
∞'KḢḢ;Ẏ

Try it Online!
∞       # The set of all positive integers
 '   ;  # Filtered by...
  K     # The list of factors of n
   ḢḢ   # Has length > 2
      Ẏ # Get first n

Using a isprime builtin doesn't actually save any bytes as 1 and 0 are considered nonprime.

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