# Alphabet completion rate

## Introduction

How much of the English alphabet does a given string use? The previous sentence uses 77%. It has 20 unique letters (howmucftenglisapbdvr), and 20/26 ≃ 0.77.

## Challenge

For an input string, return the percentage of letters of the English alphabet present in the string.

• The answer can be in percentage or in decimal form.

• The input string can have upper and lower case, as well as punctuation. However you can assume they have no diacritics or accentuated characters.

## Test cases

Input

"Did you put your name in the Goblet of Fire, Harry?" he asked calmly.


Some valid outputs

77%, 76.9, 0.7692


Input:

The quick brown fox jumps over the lazy dog


All valid outputs:

100%, 100, 1


The expected output for "@#$%^&*?!" and "" is 0. • Suggested test cases: "@#$%^&*?!", "" – Adám Jun 21 '19 at 10:35
• If 77% and 76.9 is accepted, is 77 accepted too? – Grzegorz Oledzki Jun 21 '19 at 10:43
• Percentages can have decimal parts too... – Jo King Jun 21 '19 at 11:54
• @Shaggy Last edit for OP was 16 hours ago, your answer was at 15 and your comment at 14. I mean, you're right but ??? – Veskah Jun 22 '19 at 4:16
• If 20/26 may be rounded to 0.7692, 0.769 or 0.77, can I also round it to 0.8, 1 or 0? ;-) – Noiralef Jun 22 '19 at 22:42

# 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)


# 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:

• Put your input in the input field
• Unpack
• Insert v at the start of the code and |b immediately after Va
• Run
• Remove the characters you added to the code
• Repack

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.

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....

# Ohm v2, 7 bytes

ÁαA}εÆm


Try it online!

# 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


# Emacs Lisp, 91 bytes

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


Try it online!

# V, 30, 29 bytes

ÓÁ
òóãˆ“±òAÝ/26.0|Óá
C="


Try it online!

# 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


# JavaScript (ES6), 6154 51 bytes

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

• 57 bytes – Arnauld Jun 21 '19 at 11:36
• You can't just do replace(/[^a-z]/g) because matched characters will be replaced with 'undefined' (as a string). For instance, "*abc" will create the set Set { 'u', 'n', 'd', 'e', 'f', 'i', 'a', 'b', 'c' }. – Arnauld Jun 21 '19 at 12:34
• Was just about to post this myself: 51 bytes – Shaggy Jun 21 '19 at 14:04

# MATLAB, 53 bytes

Anonymous function taking a string:

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


# 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;


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!

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? • map toLower is shorter than (toLower<$>) – Laikoni Aug 10 '19 at 8:23

# Wolfram Language (Mathematica), 39 bytes

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


Try it online!

# Wolfram Language (Mathematica), 7170 59 bytes

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


Try it online!

Thanks to attinat for suggesting Union to replace DeleteDuplicates.

• Union is 11 bytes shorter than DeleteDuplicates. – attinat Aug 5 '19 at 5:02

# 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.

# 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

# 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
`