g | x | w | all
Bytes Lang Time Link
089Swift 6230712T011843ZmacOSist
040Arturo240523T153015Zchunes
050Scala 3240305T211711Zmovatica
009Uiua SBCS240305T174303Zchunes
006Vyxal 3240305T155928Zpacman25
196Go230711T041850Zbigyihsu
072C gcc230711T160432Zc--
072C gcc230711T064636Zl4m2
115Racket –230711T145425ZEd The &
047x8664 machine code230710T223341Zengineer
005Thunno 2230710T164006ZThe Thon
008MATL190621T102254ZSuever
072AWK210606T014735Zcnamejj
044Factor + spelling210605T232131Zchunes
091Emacs Lisp190820T152508ZJordon B
008MathGolf190820T144619Zmaxb
158C# .NET190820T141528Zcanttalk
nanjq R190812T112243Zuser344
009Pyth190812T103925Zar4093
007Ohm v2190805T083821ZCinaski
052Haskell190805T065202Zxnor
059Wolfram Language Mathematica190621T193636ZRoman
039Wolfram Language Mathematica190621T130709Zatt
086Haskell190804T201617Zunivalen
049Python 3190623T172644Zruohola
199Oracle190707T131623ZAndrei O
034Julia 1.0190703T200850ZTimD
008Stax 1.1.4 online interpreter190702T205153ZKhuldrae
045JavaScript Node.js190624T044237Ztsh
047R190621T132231ZRobin Ry
053MATLAB190621T185916Zcostrom
052PowerShell190621T141856ZSinusoid
051JavaScript ES6190621T112146ZHuntro
059Java 8190621T110418ZKevin Cr
035Retina190621T114708ZKevin Cr
008APL Dyalog Extended190623T120951Zngn
013K4190623T084643Zmkst
015K oK190621T205322Zmkst
095C190622T232729ZAnonymou
042Python 3190621T103312ZArBo
033Octave / MATLAB190621T103804ZLuis Men
008Jelly190621T115540ZNick Ken
019K oK190621T110136ZGalen Iv
138Pepe190622T033426Zu-ndefin
042Bash and Gnu utils190621T105100ZGrzegorz
055EXCEL190622T021917Zremoel
034Ruby n190621T194010ZValue In
029V190621T202819ZDJMcMayh
057Python 2190621T134232ZElPedro
009Stax190621T140517Zrecursiv
024Perl 6190621T120918ZJo King
009Japt190621T122431ZShaggy
024Perl 5 MListUtil=uniq p190621T132006ZXcali
096C190621T130232ZSteadybo
197Batch190621T125155ZNeil
011Charcoal190621T124130ZNeil
045Retina 0.8.2190621T123436ZNeil
049C# Visual C# Interactive Compiler190621T102452ZExpired
00605AB1E190621T103814ZKevin Cr
010APL Dyalog Extended190621T103735ZAdá

Swift 6, 105 100 89 bytes

let p={Float((65...90).filter(($0+"").uppercased().map(\.asciiValue).contains).count)/26}

Kinda proud of this one — it's my most point-free golf yet.

Using Float instead of Double saved a byte.

Arturo, 40 bytes

$=>[//size unique match lower&{[a-z]}26]

Try it!

Scala 3, 50 bytes

_.filter(_.isLetter).toLowerCase.distinct.size/26f

Attempt This Online!

Uiua SBCS, 9 bytes

÷26⧻◴▽±.⌵

Try it!

÷26⧻◴▽±.⌵
        ⌵  # uppercase
       .   # duplicate
      ±    # mask of cases (-1 for lower, 1 for upper, 0 for neither)
     ▽     # keep (only the letters)
    ◴      # remove duplicates
   ⧻       # length
÷26        # divided by 26

Vyxal 3, 6 bytes

ʀuȦL₂÷

Try it Online!

length of unique lowercase letters divided by 26

Go, 210 196 bytes

import(."strings";U"unicode")
func f(s string)float64{s=Map(func(r rune)rune{if!U.IsLetter(r){r=-1};return r},ToLower(s))
m:=make(map[rune]int)
for _,r:=range s{m[r]++}
return float64(len(m))/26.}

Attempt This Online!

Returns a float in [0,1].

C (gcc), 72 bytes

Outputs via exit code

r;a[];main(c){return~c?main(getchar(r+=a[c&=95]++<c/65-c/91)):r/.26+.5;}

Try it online!

Commented

r;                // int r is zero-initialized
a[];              // same for int array a[]; it has size 1 (we'll pretend it's 96)
main(c){          // function main returns int and takes an int `c`
 return
  ~c?             // if c != -1:
   main(          //  call main() recursively with
    getchar(      //   next character from stdin or EOF(-1) (ignores argument)
     r+=          //    add the following to r:
      a[c&=95]++  //     uppercase `c`, increment the value at it's index in a[]
       <c/65-c/91 //     if (old value of a[c]) < (c/'A' - c/'[') add 1, else 0
    )             //   end call to getchar()
   )              //  end call to main()
  :               // else (we're at the end):
   r/.26+.5;      //  return the accumulated result as a % of 26, rounded
}                 // end main() function

Explanation

Alphabetic characters are in the ranges \$1000001_2..1011010_2\$ (uppercase) and \$1100001_2..1111010_2\$ (lowercase), and \$95_{10} = 1011111_2\$, so c &= 95 makes characters uppercase and changes symbols in some way we don't care as they will not land in the same range.

For \$0 \le c \le 95\$ the equation \$\frac{c}{65} - \frac{c}{91}\$ returns 1 if \$65 \le c \le 90\$ (c is uppercase) and 0 otherwise.

So a[c &= 95]++ < c/65 - c/91 checks that isapha(c) and that this is the first time we see c in uppercase or lowercase (by incrementing the value we make sure subsequent occurrences of c will not match the expression).

C (gcc), 72 bytes

i;j;f(char*s){for(i=j=0;i++<26;)j+=index(s,i+64)!=index(s,i+96);j/=.26;}

Try it online!

-9B from c--

x86 opcode, 35 bytes

00000180: 575e 31ff ac2c 4172 030f abc7 0441 75f4  W^1..,Ar.....Au.
00000190: c1e7 06f3 0fb8 c750 df04 2458 6a1a de34  .......P..$Xj..4
000001a0: 2458 c3

Try it online!

Racket – 115 bytes

(~r(*(/(set-count(apply set(filter char-alphabetic?(string->list(string-upcase(read-line))))))26)100)#:precision 2)

Try it online!


Explanation

First, we read user input and transform it into upper case. We then turn the string into a list of characters and remove any characters that aren't alphabetic. Once done, we transform the list into a set. A Set is a data structure that can only contain unique values. That's cool because it allows us to simply count the number of elements in the set and calculate the percentage of unique letters that are used. Once all is done, we return the result as a decimal string with the precision of 2.

(~r (* (/ (set-count (apply set
                            (filter char-alphabetic?
                                    (string->list (string-upcase (read-line))))))
           26)
       100)
    #:precision 2)

Some cool things to note that I just found out is that Racket uses fractions by default to calculate large arbitrary precision. If you were to remove ~r you'd see a fraction that looks like x/y.

x86-64 machine code, 47 bytes

Standard x64 System V ABI, signature long double get_acr(char* str). The string is modified by the function, so it cannot be read-only.

57 5e 31 c9 ac ff c1 80 66 ff df 84 c0 75 f5 6a 1a df 04 24 5a d9 ee 6a 41 58 57 51 f2 ae 75 04 d9 e8 de c1 59 5f ff c0 ff ca 75 ee de f1 c3 

Try it online!

Explanation

; long double get_acr(char* str)
; follows x64 SysV ABI
; input RDI: null-delimited writable string (gets modified)
; output ST0: percentage in range [0, 1]
get_acr:
    ; Get string length in rcx and convert characters to uppercase
    push rdi
    pop rsi ; get str reference in rsi
    xor ecx, ecx ; len = 0

__get_acr_convlp:
    lodsb ; get byte into rsi

    ; non-zero char: increment length and handle conversion
    ; if it is zero, we increment, do (effectively) no conversions, and store 
    ; back. this +1 in ecx doesn't matter though, since it's okay if we search
    ; for letters in the zero byte later on.
    inc ecx

    ; convert by removing bit for 32 to force lowercase letters uppercase
    ; in other words, and al by ~32 (0b1101 1111, 0xdf).
    and byte [rsi-1], 0xdf
    
    ; loop back up if al != 0
    test al, al
    jnz __get_acr_convlp

    ; init counter rdx: do 26 times
    ; also get 26 into st1 for division later
    push 26
    fild word [rsp]
    pop rdx

    fldz ; sum starts at 0.0

    ; We only have uppercase letters now to look for
    ; Initial letter: 'A'
    push 65
    pop rax

__get_acr_loop:
    push rdi ; save rdi
    push rcx ; save rcx

    ; rcx times: search for al
    repne scasb ; go until rcx = 0 or found al (zf = 1)

    ; add 1 if zf, do nothing otherwise
    jnz __get_acr_dno

    fld1
    faddp

__get_acr_dno:
    pop rcx ; restore rcx
    pop rdi ; restore rdi

    inc eax ; next letter

    dec edx
    jnz __get_acr_loop ; loop back to top edx times

    ; Divide st0 by st1 and pop to get the fraction to return
    fdivrp st1, st0

    ret

Thunno 2, 5 bytes

LẠ€Ƈm

Try it online!

Thunno 2, 7 bytes

LỊUl26/

Try it online!

Explanations

LẠ€Ƈm  # Implicit input
L      # Lowercase
 Ạ     # Lowercase alphabet
  €    # Single function map:
   Ƈ   #  Contains
    m  # Mean
       # Implicit output
LỊUl26/  # Implicit input
L        # Lowercase
 Ị       # Only alphabetic
  U      # Uniquify
   l     # Length
    26/  # Divide by 26
         # Implicit output

MATL, 8 bytes

2Y2jkmYm

Try it at MATL Online

Explanation

2Y2    % Predefined literal for 'abcdefghijklmnopqrstuvwxyz'
j      % Explicitly grab input as a string
k      % Convert to lower-case
m      % Check for membership of the alphabet characters in the string. 
       % Results in a 26-element array with a 1 where a given character in 
       % the alphabet string was present in the input and a 0 otherwise
Ym     % Compute the mean of this array to yield the percentage as a decimal
       % Implicitly display the result

AWK, 72 bytes

gsub("[^a-zA-Z]",z)+gsub(z," "){for(;$++a;)b+=!c[tolower($a)]++}$0=b/.26

Try it online!

The first bit in this code is a test that's always truthy, so the associated code block will always run no matter what the input string contains. The purpose of the gsub calls is to remove all the non-alphabetic characters and then to split the input string into space separated characters. That re-evaluates the positional parameters, making the input a list of individual a-zA-Z characters.

gsub("[^a-zA-Z]",z)+gsub(z," "){                               }

The codeblock can then iterate over each positional parameters to process all the alphabetic characters in the input string.

                                for(;$++a;)

The body of the loop is one AWK statement that does all the real work. It counts the number of times each unique (lowercase) character is seen. And anytime the current counter c[...char...] is 0 it increments the tally of unique characters.

                                           b+=!c[tolower($a)]++

Once all the characters have been scanned, the final answer is the tally divided by the number of characters in the alphabet divided by 100. Assigning that value to $0 wipes out all the other positional parameters and prints the percentage by default.

                                                                $0=b/.26

Factor + spelling, 44 bytes

[ >lower ALPHABET within cardinality 26 /f ]

Try it online!

Emacs Lisp, 91 bytes

(lambda(a)(load"cl")(/(count-if(lambda(x)(< ?` x ?z))(remove-duplicates(downcase a)))26.0))

Try it online!

MathGolf, 8 bytes

▄æl!\╧]▓

Try it online!

Based on the 05AB1E solution, so be sure to upvote that. I noticed a bug in the "contains" operator, which if resolved would remove the need of the swap.

Explanation

▄          lowercase alphabet as string
 æ         start block of length 4
  l!       push input lowercased
    \      swap top elements
     ╧     pop a, b, a.contains(b)
           loop ends here
      ]    end array / wrap stack in array
       ▓   get average of list

C# .NET, 158 bytes

public class P{public static void Main(string[]z){var i=0;for(int q=65;q<91;q++)if(z[0].ToUpper().IndexOf((char)(q))>-1)i++;System.Console.Write(100D/26*i);}}

Try Online

jq -R, 36 + 3 = 39 bytes

1/length*([scan("[a-zA-Z]")]|length)

The -R flag is required, otherwise stdin needs to be a quoted string.

Pyth, 9 bytes

cl@rw0G26

Try it online!

c      26 # Float division by 26 (alternative: replace 26 by lG)
 l        #   Length of
  @       #     intersection of
   r 0    #       lowercase
    w     #         input
      G   #       and the lowercase alphabet

Ohm v2, 7 bytes

ÁαA}εÆm

Try it online!

Haskell, 52 bytes

f s=sum[1|n<-[0..25],or[elem([c..]!!n)s|c<-"aA"]]/26

Try it online!

Avoids case conversion (which base Haskell lacks) and ASCII-code conversions (which are lengthy) in favor of writing [c..] to enumerate characters. For example, ['A'..] is a very long list that starts with ABCDEFGHI....

Wolfram Language (Mathematica), 71 70 59 bytes

Count[Union@ToCharacterCode@ToUpperCase@#,x_/;64<x<91]/26.&

Try it online!

Thanks to attinat for suggesting Union to replace DeleteDuplicates.

Wolfram Language (Mathematica), 39 bytes

Length[Alphabet[]⋂ToLowerCase@#]/26.&

Try it online!

Haskell, 86 Bytes

Still golfable, probably.

import Data.Char
import Data.List
((/26).toEnum.length.nub.filter isLower.(toLower<$>))

Is there any better way to convert an Int to a Float?

Python 3, 51 49 bytes

51 -> 49 bytes, thanks to alexz02

lambda s:len({*filter(str.isalpha,s.lower())})/26

Try it online!

Oracle, 199 bytes

CREATE FUNCTION f(s LONG)RETURN FLOAT IS
r FLOAT;BEGIN
SELECT COUNT(DISTINCT c)/26 INTO r
FROM(SELECT LOWER(SUBSTR(s,LEVEL,1))c
FROM dual
CONNECT BY LEVEL<=LENGTH(s))WHERE
c>'`'AND'{'>c;RETURN r;END;

More readable version:

CREATE FUNCTION f(s LONG) RETURN FLOAT IS
    r FLOAT;
  BEGIN
    SELECT COUNT(DISTINCT c) / 26 INTO r
    FROM (
      SELECT
        LOWER(SUBSTR(s, LEVEL, 1)) AS c
      FROM dual
      CONNECT BY LEVEL <= LENGTH(s)
    )
    WHERE c > '`' AND '{' > c;
    RETURN r;
  END;

Try it on SQL Fiddle!

Julia 1.0, 34 bytes

s->sum('a':'z'.∈lowercase(s))/26

Uses the vectorized version of the ∈ operator, checking containment in the string for all characters in the range from a to z. Then sums over the resulting BitArray and divides by total number of possible letters.

Try it online!

Stax 1.1.4 online interpreter, 8 bytes, noncompeting

äQæ╟r◘Oñ

Run and debug it at staxlang.xyz!

Unpacked (9 bytes) and explanation:

Va%26!/vN
Va           Push the lowercase alphabet
  %          Length...?! Shouldn't this always be 26?
   26!       Push 26.0
      /      Divide
       vN    Subtract from one (decrement and negate)

That shouldn't work. Looking at it, you would expect an output of 0 always. Heck, it doesn't even take input! There's a bug in the online interpreter, however, which I have exploited for this answer.

Now, I've marked this answer noncompeting for a reason. As far as I can tell, this exploit requires some human interaction to set up. Here's what you gotta do:

Now you have an 8-byte program that will give the correct output each time you run it! At least until you change the input field or reload the page.

What in the seven hells is going on:

Va%26!/vN
Va           Push the lowercase alphabet, EXCLUDING characters that existed in the input field in either case any time the vVa|b version was run
  %26!/vN    Everything else works as expected

That little bug handles case checking and filtering for free, at the expense of leaving me with the wrong set of letters (wasting two bytes on the vN). I think this can be improved rather easily, but I'm at work right now.

JavaScript (Node.js), 45 bytes

s=>~-s.match(/$|([a-z])(?!.*\1)/ig).length/26

Try it online!


JavaScript (Node.js), 47 bytes

s=>(s.match(/([a-z])(?!.*\1)/ig)||[]).length/26

Try it online!

R, 47 bytes

function(x)mean(65:90%in%utf8ToInt(toupper(x)))

Try it online!

Converts to upper case then to ASCII code-points, and checks for values 65:90 corresponding to A:Z.

MATLAB, 53 bytes

Anonymous function taking a string:

@(a)length(unique(upper(a(isstrprop(a,'alpha')))))/26

PowerShell, 55 52 bytes

($args|% *per|% t*y|sort|gu|?{$_-in65..90}).count/26

Try it online!

First attempt, still trying random ideas

EDIT: @Veskah pointed out ToUpper saves a byte due to the number range, also removed extra () and a space

Expansion:
($args|% ToUpper|% ToCharArray|sort|get-unique|where{$_-in 65..90}).count/26

Changes string to all loweruppercase, expands to an array, sorts the elements and selects the unique letters (gu needs sorted input), keep only characters of ascii value 97 to 122 (a to z) 65 to 90 (A to Z), count the total and divide by 26 for the decimal output

JavaScript (ES6), 61 54 51 bytes

s=>new Set(s.toLowerCase().match(/[a-z]/g)).size/26

Java 8, 62 59 bytes

s->s.map(c->c&95).distinct().filter(c->c%91>64).count()/26.

-3 bytes thanks to @OlivierGrégoire.

Try it online.

Explanation:

s->                     // Method with IntStream as parameter and double return-type
  s.map(c->c&95)        //  Convert all letters to uppercase
   .distinct()          //  Uniquify it
   .filter(c->c%91>64)  //  Only leave letters (unicode value range [65,90])
   .count()             //  Count the amount of unique letters left
    /26.                //  Divide it by 26.0

Retina, 57 46 35 bytes

.
$L
[^a-z]

D`.
.
100*
^
13*
_{26}

-11 bytes taking inspiration from @Neil's trick of adding unary 13 before dividing.
Another -11 bytes thanks to @Neil directly.
Rounds (correctly) to a whole integer.

Try it online.

57 46 40 bytes version which works with decimal output:

.
$L
[^a-z]

D`.
.
1000*
C`_{26}
-1`\B
.

Same -11 bytes as well as an additional -6 bytes thanks to @Neil.

Outputs with one truncated decimal after the comma ( i.e. \$0.1538\$ (\$\frac{4}{26}\$) is output as 15.3 instead of 15.4). This is done by calculating \$\lfloor{\frac{1000 × \text{unique_letters}}{26}\rfloor}\$ and then inserting the decimal dot manually.

Try it online.

Explanation:

Convert all letters to lowercase:

.
$L

Remove all non-letters:

[^a-z]

Uniquify all letters:

D`.

Replace every unique letter with 1000 underscores:

.
1000*

Count the amount of times 26 adjacent underscores fit into it:

C`_{26}

Insert a dot at the correct place:

-1`\B
.

APL (Dyalog Extended), 8 bytes

⌹∘≤⍨⎕A∊⌈

Try it online!

loosely based on Adám's answer

 uppercase

⎕A∊ boolean (0 or 1) vector of length 26 indicating which letters of the English Alphabet are in the string

⌹∘≤⍨ arithmetic mean, i.e. matrix division of the argument and an all-1 vector of the same length

K4, 14 13 bytes

Solution:

avg .Q.a in _

Explanation:

Rather stolen from inspired by Luis Mendo's Octave solution...

avg .Q.a in _ / the solution
            _ / lowercase the input
         in   / 'in' function
    .Q.a      / "abcdefghijklmnopqrstuvwxyz"
avg           / average (mean)

K (oK), 19 15 bytes

Solution:

1%26%+/26>?97!_

Try it online!

Explanation:

Convert input to lowercase, modulo 97 ("a-z" is 97-122 in ASCII, modulo 97 gives 0-25), take unique, sum up results that are lower than 26, and convert to the percentage of 26.

1%26%+/26>?97!_ / the solution
              _ / lowercase
           97!  / modulo (!) 97
          ?     / distinct
       26>      / is 26 greater than this?
     +/         / sum (+) over (/)
  26%           / 26 divided by ...
1%              / 1 divided by ...

Notes:

C, 95 bytes

f(char*s){int a[256]={},z;while(*s)a[*s++|32]=1;for(z=97;z<'z';*a+=a[z++]);return(*a*100)/26;}

(note: rounds down)

Alternate decimal-returning version (95 bytes):

float f(char*s){int a[256]={},z;while(*s&&a[*s++|32]=1);for(z=97;z<'z';*a+=a[z++]);return*a/26.;}

This borrows some from @Steadybox' answer.

Python 3, 42 bytes

lambda s:len({*s.upper()}-{*s.lower()})/26

Try it online!

We filter all the non-alphabetic characters out of the string by taking the (set) difference of the uppercase and lowercase representations. Then, we take the length and divide by 26.

Python 3, 46 bytes

lambda s:sum(map(str.isalpha,{*s.lower()}))/26

Try it online!

Count the unique alphabetic (lowercase) characters, and divide by 26. In Python 2 it would require 3 more characters; two for changing {*...} to set(...), and one for making 26 a float: 26., to avoid floor division.

Python 3, 46 bytes

lambda s:sum('`'<c<'{'for c in{*s.lower()})/26

Try it online!

Same length, essentially the same as the previous one, but without "built-in" string method.

Octave / MATLAB, 33 bytes

@(s)mean(any(65:90==upper(s)',1))

Try it online!

Explanation

@(s)                               % Anonymous function with input s: row vector of chars
             65:90                 % Row vector with ASCII codes of uppercase letters
                    upper(s)       % Input converted to uppercase
                            '      % Transform into column vector
                  ==               % Equality test, element-wise with broadcast. Gives a
                                   % matrix containing true and false
         any(                ,1)   % Row vector containing true for columns that have at
                                   % least one entry with value true
    mean(                       )  % Mean

Jelly, 8 bytes

ŒuØAe€Æm

Try it online!

Explanation

Œu       | Convert to upper case
  ØAe€   | Check whether each capital letter is present, returning a list of 26 0s and 1s
      Æm | Mean

K (oK), 19 bytes

1%26%26-#(!26)^97!_

Try it online!

J, 30 bytes

26%~26-u:@(97+i.26)#@-.tolower

Try it online!

Pepe, 155 138 bytes

rEeEeeeeeEREeEeEEeEeREERrEEEEErEEEeReeReRrEeeEeeeeerEEEEREEeRERrErEErerREEEEEeREEeeRrEreerererEEEEeeerERrEeeeREEEERREeeeEEeEerRrEEEEeereEE

Try it online! Output is in decimal form.

Explanation:

rEeEeeeeeE REeEeEEeEe # Push 65 -> (r), 90 -> (R)
REE # Create loop labeled 90 // creates [65,66,...,89,90]
  RrEEEEE # Increment (R flag: preserve the number) in (r)
  rEEEe # ...then move the pointer to the last
Ree # Do this while (r) != 90

Re # Pop 90 -> (R)
RrEeeEeeeee rEEEE # Push 32 and go to first item -> (r)
REEe # Push input -> (R)
RE RrE # Push 0 on both stacks, (r) prepend 0
rEE # Create loop labeled 0 // makes input minus 32, so the
    # lowercase can be accepted, since of rEEEEeee (below)
  re # Pop 0 -> (r)
  rREEEEEe REEee # Push item of (R) minus 32, then go to next item 
  RrE # Push 0 -> (R)
ree # Do while (R) != 0

rere # Pop 0 & 32 -> (r)
rEEEEeee # Remove items from (r) that don't occur in (R)
         # Remove everything from (r) except the unique letters
rE # Push 0 -> (r)
RrEeee # Push reverse pointer pos -> (r)
REEEE # Move pointer to first position -> (R)
RREeeeEEeEe # Push 26 -> (R)
rRrEEEEee reEE # Divide it and output it

Bash and Gnu utils (81 78 68 60 42 bytes)

bc -l<<<`grep -io [a-z]|sort -fu|wc -l`/26

-8 bytes thanks to @wastl

-18 bytes thanks to Nahuel using some tricks I didn't know:

EXCEL, 55 bytes

Cell A1 as input. Place in any cell by doing Ctrl+Shift+Enter . +2 bytes if {} is included in the count.

=SUM(--ISNUMBER(FIND(CHAR(ROW(A65:A91)),UPPER(A1))))/26

Ruby -n, 38 34 bytes

-4 bytes from @historcrat!

p (?A..?Z).count{|c|~/#{c}/i}/26.0

Try it online!

V, 30, 29 bytes

ÓÁ
òó㈁“±òAÝ/26.0|Óá
C="

Try it online!

Python 2, 57 bytes

lambda i:len(set(o for o in i.lower()if o.isalpha()))/26.

Try it online!

A bit longer than the Python 3 answer from ArBo but posted as a different approach in Python 2 anyway.

Stax, 9 bytes

░║üy$}╙+C

Run and debug it

Perl 6, 27 24 bytes

-3 bytes thanks to nwellnhof

*.uc.comb(/<:L>/).Set/26

Try it online!

Japt, 9 bytes

;CoU Ê/26

Try it

;CoU Ê/26     :Implicit input of string U
;C            :Lowercase alphabet
  oU          :Remove the characters not included in U, case insensitive
     Ê        :Length
      /26     :Divide by 26

Perl 5 -MList::Util=uniq -p, 24 bytes

$_=uniq(lc=~/[a-z]/g)/26

Try it online!

C, 96 bytes

float f(char*s){int i=66,l[256]={};for(;*s;)l[1+*s++&~32]=1;for(;i<92;*l+=l[i++]);return*l/26.;}

Try it online!

Batch, 197 bytes

@set/ps=
@set s=%s:"=%
@set n=13
@for %%c in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)do @call set t="%%s:%%c=%%"&call:c
@cmd/cset/an/26
@exit/b
:c
@if not "%s%"==%t% set/an+=100

Takes input on STDIN and outputs a rounded percentage. Explanation:

@set/ps=

Input the string.

@set s=%s:"=%

Strip quotes, because they're a headache to deal with in Batch.

@set n=13

Start with half a letter for rounding purposes.

@for %%c in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)do @call set t="%%s:%%c=%%"&call:c

Delete each letter in turn from the string. Invoke the subroutine to check whether anything changed, because of the way Batch parses variables.

@cmd/cset/an/26

Calculate the result as a percentage.

@exit/b
:c

Start of subroutine.

@if not "%s%"=="%t%" set/an+=100

If deleting a letter changed the string then increment the letter count.

Charcoal, 11 bytes

I∕LΦβ№↧θι²⁶

Try it online! Link is to verbose version of code. Output is as a decimal (or 1 for pangrams). Explanation:

  L         Length of
    β       Lowercase alphabet
   Φ        Filtered on
     №      Count of
        ι   Current letter in
      ↧     Lowercased
       θ    Input
 ∕          Divided by
         ²⁶ Literal 26
I           Cast to string
            Implicitly printed

Retina 0.8.2, 45 bytes

T`Llp`ll_
+`(.)(.*\1)
$2
.
100$*
^
13$*
.{26}

Try it online! Link includes test cases. Explanation:

T`Llp`ll_

Lowercase letters and delete punctuation.

+`(.)(.*\1)
$2

Deduplicate.

.
100$*

Multiply by 100.

^
13$*

Add 13.

.{26}

Integer divide by 26 and convert to decimal.

C# (Visual C# Interactive Compiler), 56 49 bytes

a=>a.ToUpper().Distinct().Count(x=>x>64&x<91)/26f

Try it online!

-6 bytes thanks to innat3

05AB1E, 8 7 6 bytes

lASåÅA

-1 byte thanks to @LuisMendo.

Try it online or verify a few more test cases.

6 bytes alternative provided by @Grimy:

láÙg₂/

Try it online or verify a few more test cases.

Both programs output as decimal.

Explanation:

l       # Convert the (implicit) input-string to lowercase
 AS     # Push the lowercase alphabet as character-list
   å    # Check for each if it's in the lowercase input-string
        # (1 if truthy; 0 if falsey)
    ÅA  # Get the arithmetic mean of this list
        # (and output the result implicitly)

l       # Convert the (implicit) input-string to lowercase
 á      # Only leave the letters in this lowercase string
  Ù     # Uniquify it
   g    # Get the amount of the unique lowercase letters by taking the length
    ₂/  # Divide this by 26
        # (and output the result implicitly)

APL (Dyalog Extended), 10 bytesSBCS

Anonymous tacit prefix function. Returns decimal fraction.

26÷⍨∘≢⎕A∩⌈

Try it online!

 uppercase

⎕A∩ intersection with the uppercase Alphabet

 tally length

 then

26÷⍨ divide by twenty-six