28
\$\begingroup\$

Overview

The sharpness of a word is the sum of the sharpness of each of its letters, using the following rules:

Sharp letters

  • A, and V each have a sharpness of 1

  • N and Z each have a sharpness of 2

  • M and W each have a sharpness of 3

Dull letters

  • C and U each have a sharpness of -1

  • S has a sharpness of -2

  • O has a sharpness of -3

All other letters have a sharpness of 0.

Example

The word SAUCE has a sharpness of -3 since the A contributes 1, the U and C each contribute -1 and the S contributes -2.

The word MAZE has a sharpness of 6 since the M contributes 3, the Z contributes 2, and the A contributes 1.

Task

Given as input a string containing only uppercase letters*, determine the sharpness of that string.

*If you wish, you may instead take the input as a string containing only lowercase letters. Other common input formats are also acceptable (eg. a list of characters, a list of codepoints, etc.)

Scoring

This is !

Test Cases

CODE => -4
GOLF => -3
SAUCE => -3
CATS => -2
MOON => -1
NONSENSE => -1
ZUCKERBERG => 0
STRING => 0
CHALLENGE => 2
NAIL => 3
CARNIVAL => 4
COMPLIMENT => 4
WAVE => 5
UNKNOWN => 5
MAZE => 6

Extra test cases (Provided by @Surculose Sputum)

MIZZENMASTMAN => 17
PNEUMONOULTRAMICROSCOPICSILICOVOLCANOCONIOSIS => -26
MANAGEMENT => 12
CONSCIOUSNESS => -13
\$\endgroup\$
0

29 Answers 29

13
\$\begingroup\$

Python 2, 53 bytes

lambda s:sum(3-"MWCUNZS_AVO".find(c)/2*4%7for c in s)

Try it online!

\$\endgroup\$
2
  • 3
    \$\begingroup\$ -1 byte if you interleave the string instead of /2. Try it online! \$\endgroup\$
    – David
    Jun 3 '20 at 15:43
  • 4
    \$\begingroup\$ @David Nice improvement! I suggest you post it as an answer which would qualify for my outgolfing bounty. \$\endgroup\$
    – xnor
    Jun 3 '20 at 18:32
9
\$\begingroup\$

Jelly, 21 bytes

“CSO“ANM“U“VZX”iⱮ€§ḅ-

A monadic Link accepting a list of characters which yields an integer.

Try it online!

How?

“CSO“ANM“U“VZX”iⱮ€§ḅ- - Link: list of characters, W
“CSO“ANM“U“VZX”       - list of lists of characters = [['C','S','O'],['A','N','M'],['U'],['V','Z','X']]
                 €    - for each (L in those four lists):
                Ɱ     -   map across (c in W) with:
               i      -     first (1-based) index (of c in L) or 0 if not found
                  §   - sum each resulting list
                    - - literal minus one
                   ḅ  - convert (the list of four sums) from base (-1)
\$\endgroup\$
1
  • 1
    \$\begingroup\$ I'm abysmal at coding but I gotta say, this one's quite particularly beautiful! \$\endgroup\$ Jun 3 '20 at 12:47
9
+150
\$\begingroup\$

Python 2, 52 bytes

lambda s:sum(3-"MCNSAO_WUZ_V".find(c)*4%7for c in s)

Try it online!

Improvement on @xnor's answer.

M C N S A O _ W U Z _ V ?  c
0 1 2 3 4 5 6 0 1 2 3 4 6  "...".find mod 7
0 4 1 5 2 6 3 0 4 1 5 2 3  "...".find*4 mod 7
3-1 2-2 1-3 0 3-1 2-2 1 0  (3-"...".find*4 mod 7)

*4 is to map -1 (failed find) onto 0

\$\endgroup\$
0
9
\$\begingroup\$

JavaScript (Node.js),  61  53 bytes

A lookup table based on the ASCII code of each letter.

Takes input as a list of codepoints.

a=>a.map(c=>t+='50363133463254'[(c^98)%22]-3|0,t=0)|t

Try it online!

How?

By XOR'ing the ASCII code with 98 and applying a modulo 22, we gather the characters with a non-zero sharpness into the range [0..13]. This results in a lookup table of 14 entries.

If the result of the formula is out of range, we get undefined - 3 | 0, which is 0.

 char. | code | XOR 98 | MOD 22 | sharpness
-------+------+--------+--------+-----------
  'A'  |  65  |   35   |   13   |    +1
  'B'  |  66  |   32   |   10   | 
  'C'  |  67  |   33   |   11   |    -1
  'D'  |  68  |   38   |   16   | 
  'E'  |  69  |   39   |   17   | 
  'F'  |  70  |   36   |   14   | 
  'G'  |  71  |   37   |   15   | 
  'H'  |  72  |   42   |   20   | 
  'I'  |  73  |   43   |   21   | 
  'J'  |  74  |   40   |   18   | 
  'K'  |  75  |   41   |   19   | 
  'L'  |  76  |   46   |    2   | 
  'M'  |  77  |   47   |    3   |    +3
  'N'  |  78  |   44   |    0   |    +2
  'O'  |  79  |   45   |    1   |    -3
  'P'  |  80  |   50   |    6   | 
  'Q'  |  81  |   51   |    7   | 
  'R'  |  82  |   48   |    4   | 
  'S'  |  83  |   49   |    5   |    -2
  'T'  |  84  |   54   |   10   | 
  'U'  |  85  |   55   |   11   |    -1
  'V'  |  86  |   52   |    8   |    +1
  'W'  |  87  |   53   |    9   |    +3
  'X'  |  88  |   58   |   14   | 
  'Y'  |  89  |   59   |   15   | 
  'Z'  |  90  |   56   |   12   |    +2
\$\endgroup\$
2
  • \$\begingroup\$ Arguably, you don't even need the Buffer(s) bit, because "a list of codepoints" is acceptable as input. \$\endgroup\$ Jun 4 '20 at 12:14
  • \$\begingroup\$ @SteveBennett I didn't notice it was explicitly allowed. Thanks! \$\endgroup\$
    – Arnauld
    Jun 4 '20 at 12:19
5
\$\begingroup\$

APL+WIN, 42 38 bytes.

Prompts for string:

   +/(2/¯3+⍎¨'4562103')['AVNZMWCUS O '⍳⎕]

Try it online! Courtesy of Dyalog Classic

Explanation:

⍎¨'4562103' Split number as a string into individual digits and convert to integers

2/¯3+ Subtract 3 to give the non-zero letter values and double up each value 

['AVNZMWCUS O '⍳⎕] Find the index position of non-zero letters that occur in the input. 
If a letter is not in list it is given an index of length of list + 1

+/ Sum the values corresponding to the indices of non-zero letters in string
\$\endgroup\$
2
  • \$\begingroup\$ does the ⍎¨'<string>' trick work with negative numbers as well? \$\endgroup\$
    – Razetime
    Aug 26 '20 at 14:27
  • 1
    \$\begingroup\$ @Razetime No because ⍎¨ attempts to execute each element of the string which works fine if each element is an positive integer but in the case of the leading minus sign of a negative number ⍎ throws a syntax error as the minus sign needs at least a right argument to be a valid expression. \$\endgroup\$
    – Graham
    Aug 26 '20 at 19:23
5
\$\begingroup\$

APL (Dyalog Unicode), 31 bytes

-/1⊥¨4|(↓4 3⍴'ANMCSOVZWU  ')⍳¨⊂

Try it online!

Tacit function.

How it works

-/1⊥¨4|(↓4 3⍴'ANMCSOVZWU  ')⍳¨⊂  ⍝ Input: string S
       (↓4 3⍴'ANMCSOVZWU  ')     ⍝ 'ANM' 'CSO' 'VZW' 'U  '
                            ⍳¨⊂  ⍝ Find the index of each char in S in each of above
                                 ⍝ Index is 1-based, not found gives 4
     4|  ⍝ Modulo 4; convert 4 to 0
  1⊥¨    ⍝ Sum of each row
-/       ⍝ Alternating sum; (ANM score)-(CSO score)+(VZW score)-(U score)
\$\endgroup\$
5
\$\begingroup\$

C(GCC) 84 73 72 bytes

-11 bytes thanks to ceilingcat

t;f(char*s){for(t=0;*s;t+=""[*s++-65]-4);s=t;}

(note that StackExchange strips some non-printing characters)

Try it online!

\$\endgroup\$
0
4
\$\begingroup\$

Python 2, 62 60 bytes

-2 bytes thanks to @Neil!

lambda w:sum('AVNZMW'.find(c)/2-'CUS_O'.find(c)/2for c in w)

Try it online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ 'AVNZMW'.find(c)/2-'CUS_O'.find(c)/2 saves 2 bytes, but I like the /2 idea, it saves my a byte on my Charcoal answer! \$\endgroup\$
    – Neil
    Jun 3 '20 at 19:04
  • \$\begingroup\$ @Neil thanks a lot, this really looks like it shouldn't work ;) \$\endgroup\$
    – ovs
    Jun 3 '20 at 19:16
3
\$\begingroup\$

Python 3, 61 bytes

Input is taken as a byte-string \$ s \$.

lambda s:sum(b''[c-65]-4for c in s)

Try it online!

We use a lookup table, where each element maps to the sharpness of a given letter. Note the -4, to display the negative sharpness.

\$\endgroup\$
3
\$\begingroup\$

Retina 0.8.2, 61 60 bytes

M|W
N#
N|Z
##
O
S-
S
--
T`VAUC`##-
+`\w|-#|#-

^(-)?.*
$1$.&

Try it online! Link includes test cases. Edit: Saved 1 byte thanks to @mathjunkie. Explanation:

M|W
N#
N|Z
##
O
S-
S
--
T`VAUC`##-

Turn sharp letters into the appropriate number of # (sharp... geddit? any non-word non-magic non-- character would have worked) signs and dull letters into the appropriate number of - (because they have negative sharpness) signs.

+`\w|-#|#-

Delete other letters and all matching pairs of # and - signs.

^(-)?.*
$1$.&

Output the number of signs remaining, prefixed by the first one if it's a -. Since the regex matches a zero-length string, I have to ensure it only matches once.

\$\endgroup\$
2
  • \$\begingroup\$ Using a transliteration stage saves a byte: Try it online! \$\endgroup\$ Jun 2 '20 at 19:58
  • \$\begingroup\$ @mathjunkie I had tried transliteration stages but not in that exact combination, thanks! \$\endgroup\$
    – Neil
    Jun 2 '20 at 21:50
3
\$\begingroup\$

Javascript (Node.js), 115 bytes

let s=0;for(let b='w'+w,c=a=>Math.ceil(10*3**(4/~'OSCUAVNZMW'.indexOf(a[0])))-4||-1;b=b.slice(1);s+=9>c(b)?c(b):0);

Try it online!

This puts all the characters in a string, 'OSCUAVNZMW', and uses a formula to map the character index to the "sharpness" of each letter. The formula is:

\$f\left(x\right)=ceil\left(10\cdot3^{\frac{4}{x}}-4\right)\$

Where \$f(x)\$ is the sharpness, and \$x\$ is the negative index of the character + 1. Sounds convoluted, but there's a reason: the index is modified to make Javascript's string.indexOf() return 0 instead of -1.

This formula does result in 0 instead of -1 for U. However, using Javascript's || functionality in variable assignment, we can just default zero values to -1 instead.

Also, this is my first code golf, advice appreciated!

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Hey welcome. You can also generally use ~ instead of Math.ceil, since it also rounds out decimal numbers, with a bit of tweaking. \$\endgroup\$ Jun 3 '20 at 8:38
  • \$\begingroup\$ @SteveBennett Hi, I heard that but couldn't seem to get the right values using -~, even when only using floats. \$\endgroup\$
    – mrprgr
    Jun 3 '20 at 20:11
  • \$\begingroup\$ ~~ is equivalent to Math.floor for positive numbers \$\endgroup\$ Jun 4 '20 at 12:16
3
\$\begingroup\$

Java (JDK), 56 bytes

s->s.map(c->("XXAVNZMWOOSSCU".indexOf(c)/2+3)%7-3).sum()

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Javascript (Babel Node), 131 bytes

d=>(s=0,[...d].map(c=>{s+=/[AV]/.test(c)?1:(/[NZ]/.test(c)?2:(/[MW]/.test(c)?3:(/[CU]/.test(c)?-1:(c=='S'?-2:(c=='O'?-3:0)))))}),s)

Try it online!

This is my first code golfing. I hope I'm doing it right.

I'll be glad to get some js golfing tips (before exploring new golfing languages) and overall golfing tips.

\$\endgroup\$
9
  • 1
    \$\begingroup\$ I'd recommend checking these tips out if you haven't already :) \$\endgroup\$ Jun 2 '20 at 22:11
  • \$\begingroup\$ @mathjunkie Hi :) thanks! well.. Most of it I already know. But there is one thing I didn't get actually that may help. It is that answer: codegolf.stackexchange.com/a/35872/95505 Do you familiar with this? \$\endgroup\$
    – SomoKRoceS
    Jun 2 '20 at 22:41
  • \$\begingroup\$ By the way... I saw people using Header and Footer in TIO, what is it exactly? \$\endgroup\$
    – SomoKRoceS
    Jun 2 '20 at 22:42
  • 1
    \$\begingroup\$ To your first question: I'm not too experienced with golfing in JS, but there are many others on the site who are, perhaps try asking on the nineteenth byte. To your 2nd question: The header & footer on TIO are usually used for things like a test harness -- extra snippets that illustrate how your code works, but shouldn't be included in the byte count \$\endgroup\$ Jun 2 '20 at 22:51
  • 1
    \$\begingroup\$ Yeah. On this site, function submissions are generally allowed as an alternative to a full program \$\endgroup\$ Jun 2 '20 at 23:13
3
\$\begingroup\$

Javascript (ES6), 65 characters

x=>x.map(l=>s-=~(z='RosLucyEvanzmw'.indexOf(l))?~(z/2)+4:0,s=0)|s

Javascript (ES6), 67 characters

x=>x.reduce((s,l)=>~(z='RosLucyEvanzmw'.indexOf(l))?s-~(z/2)-4:s,0)

Takes an array of lowercase characters as input.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ save 2 bytes by converting reduce to map: x=>x.map(l=>s-=~(z='RosLucyEvanzmw'.indexOf(l))?~(z/2)+4:0,s=0)|s \$\endgroup\$ Jun 3 '20 at 15:13
  • \$\begingroup\$ Ah, thanks - I did try that, but couldn't find a result that was actually shorter. \$\endgroup\$ Jun 4 '20 at 12:02
  • \$\begingroup\$ Two useful tricks in there for me: passing nonsense args to map as a convenient place to initialise something, and realising that array|integer returns the value of the integer. \$\endgroup\$ Jun 4 '20 at 12:07
2
\$\begingroup\$

Stax, 20 19 bytes

ô≈X╙R┤╠Φyf∙H¡»₧ßc≡╡

Run and debug it

\$\endgroup\$
2
\$\begingroup\$

Keg, 42 bytes

?⑷¦A1|V1|N2|Z2|M3|W3|C1±|U1±|S2±|O3±║_0™⑸⅀

Unfortunately, TIO doesn't have the latest version of the interpreter on its servers, so y'all can't try it online.

Quite literally, this maps over each character in the input, assigns it a value based on the sharpness table, and sums the stack.

\$\endgroup\$
2
\$\begingroup\$

Zsh, 73 bytes

a=(O S CU : AV NZ MW)
for c (${(s[])1})(((x=a[(I)*$c*])&&(r+=x-4)))
<<<$r

Try it online!

Get the last (I)ndex of the glob *$char* (with (I), it is zero if not found). If it is non-zero, add to $r.

\$\endgroup\$
2
\$\begingroup\$

Perl 5 -p, 48 bytes

$_=y/AV//+2*y/NZ//+3*y/MW//-y/CUSO//-y/SO//-y;O;

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Charcoal, 25 24 bytes

IΣES⁻÷⌕AVNZMWι²÷⌕UCSSOι²

Try it online! Link is to verbose version of code. Edit: Saved 1 byte by porting @ovs' answer. Explanation:

   S                        Input string
  E                         Map over characters
             ι              Current character
      ⌕                     Find position in
       AVNZMW               Literal string `AVNZMW`
     ÷        ²             Integer divide by literal `2`
    ⁻                       Minus
                      ι     Current character
                ⌕           Find position in
                 UCSSO      Literal string `UCSSO`
               ÷       ²    Integer divide by literal `2`
 Σ                          Take the sum
I                           Cast to string
                            Implicitly print

The halved Find results in one less than the sharpness/dullness, but the other find returns -1 in that case, thus correcting the value.

\$\endgroup\$
2
\$\begingroup\$

05AB1E, 39 38 36 34 33 28 bytes

lε.•3и½:∍äaŠ•sk>4%„ݧuyåi(]O

Try it online! or Verify all test cases (as arranged by @sporeball)

-5 thanks to @Kevin

Explained

Original: lε.•3и½:∍äaŠ•sk>4%„ݧuyåi(]O
Uncompressed: lε"anm vzw cso u"sk>4%"cosu"yåi(]O

l               | Take the implicit input and lowercase it.
ε               | Map the following to this input to find the sharpness of each letter:
"anm vzw cso u" |   Push the string "anm vzw cso u", representing the sharpness of each
                |   letter. They are arranged in a way such the index of the character
                |   is retrivable via mathematical caluclation.
                |
sk              |   Swap this string, and the mapping item, and find the index of the
                |   item within the big string
                |
>4%             |   Increment the value, and then modulo 4 it in order to find the "raw"
                |   sharpness of the string. The result will be in the range [0, 3]
                |
"cosu"          |   Now comes the part where we determine if the sharpness needs to be
                |   negated or not. First, we push a string containing all letters that
                |   have negative sharpness
                |
yå              |   We now push the letter being mapped, and test to see if it is in the
                |   aforementioned string
                |
i(]             |   If it is in the string, negate the sharpness value. After that,
                |   close the if-statement and the loop
                |
O               | Summate the stack and implicitly output the total sharpness.

05AB1E, 22 bytes

.•7ùZ9£nDн•#εXlSk>}O®β

Try it online!

A port of the Jelly answer suggested by @Kevin.

\$\endgroup\$
3
1
\$\begingroup\$

Pyth, 28 bytes

J"MNA CSOWZV U"sm-3%xJd7@#JQ

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Ruby, 70 bytes

->s{'OAVNZMWCUS'.chars.zip(1226655440.digits).sum{s.count(_1)*(_2-3)}}

Try it online! (3 bytes longer because TIO doesn't suppoort ruby 2.7 _1 syntax)

\$\endgroup\$
1
\$\begingroup\$

C (gcc), 88 87 bytes

Saved a byte thanks to ceilingcat!!!

char*t="O_S_CU__AVNZMW",*i;v;f(char*s){for(v=0;*s;v+=i?i-t-6>>1:0)i=index(t,*s++);v=v;}

Try it online!

\$\endgroup\$
0
1
\$\begingroup\$

Bash + GNU utilities, 100 \$\cdots\$ 92 91 bytes

sed 's/[AV]/+1/g
s/[NZ]/+2/g
s/[MW]/+3/g
s/[CU]/-1/g
s/S/-2/g
s/O/-3/g
s/[A-Z]//g'<<<0$1|bc

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Java (OpenJDK 8), 205 bytes

int u(String s){if(s.length()>0){int n=0;switch(s.charAt(0)){case'M':case'W':n++;case'N':case'Z':n++;case'A':case'V':n+=4;case'O':n--;case'S':n--;case'C':case'U':n--;}return n+u(s.substring(1));}return 0;}

Try it online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ If you switch to Java 14, you can spare a lot of bytes: int u(String s){return s.isEmpty()?0:u(s.substring(1))+switch(s.charAt(0)){case'M','W'->3;case'N','Z'->2;case'A','V'->1;case'C','U'->-1;case'S'->-2;case'O'->-3;default->0;}} (173 bytes) which can still be further golfed. \$\endgroup\$ Jun 3 '20 at 14:46
  • 1
    \$\begingroup\$ 156 bytes \$\endgroup\$
    – ceilingcat
    Nov 18 '20 at 4:39
1
\$\begingroup\$

T-SQL, 133 bytes

Added some line changes to make it readable

SELECT
SUM(iif('P'=type,nullif(substring(
translate(@,'AVNZMWCUSO','4455662210'),
number,1),substring(@,number,1))-3,0))
FROM spt_values

Try it online

\$\endgroup\$
1
  • 1
    \$\begingroup\$ @KevinCruijssen I finally had the time to rewrite my answer for the related question. Thank you very much for pointing this out, the related question is worded differently. So I was able to shave off a few bytes and make some other improvements which should have been included my first answer. And yes, I did spend some hours on it \$\endgroup\$ Jun 8 '20 at 13:00
1
\$\begingroup\$

Add++, 49 bytes

D,k,@,"MCNSAO_WUZ_V"$€=12Rz€¦*bM-1+4*7%3$_
L,€kBs

Try it online!

An implementation of xnor's formula, go upvote that.

How it works

The second line defines the main function which runs the helper function k over ach character in the input, then sums the result.

k works as follows:

D,k,@,"MCNSAO_WUZ_V"$€=12Rz€¦*bM-1+4*7%3$_ ; Monadic function, takes a single character s
					   ;    and returns the sharpness of s
					   ; For example, s = 'C'		 		STACK = ['C']
      "MCNSAO_WUZ_V"			   ; Push this string 			 		STACK = ['C' 'MCNSAO_WUZ_V']
                    $€=			   ; Check each character for equality with s		STACK = [[0 1 0 0 0 0 0 0 0 0 0 0]]
		       12R		   ; Push [1 2 3 4 5 6 7 8 9 10 11 12]			STACK = [[0 1 0 0 0 0 0 0 0 0 0 0] [1 2 3 4 5 6 7 8 9 10 11 12]]
			  z		   ; Zip arrays						STACK = [[[0 1] [1 2] [0 3] [0 4] [0 5] [0 6] [0 7] [0 8] [0 9] [0 10] [0 11] [0 12]]]
			   €¦*		   ; Product of each					STACK = [[0 2 0 0 0 0 0 0 0 0 0 0]]
			      bM	   ; Maximum (call the result r)			STACK = [2]
				-1+4*7%3$_ ; Push 3 - ((r - 1) * 4 % 7)				STACK = [-1]
\$\endgroup\$
0
\$\begingroup\$

Perl 5 + -pF, 39 bytes

$\+=y/OSUBANMCBVZW/0-62-6/&&$_-3for@F}{

Try it online!

Explanation

For each character in the input (stored in @F via -F) we add to $\ (defaults to '', implicitly output as the last argument for calls to print, which is triggered as part of -p) the value of $_-3, if we have translated (y/// is a synonym for tr///) any char in $_ (the current char taken from for@F) using OSUBANM to 0-6 and CBVZW to 2-6.

\$\endgroup\$
0
\$\begingroup\$

SimpleTemplate, 118 bytes

Yes, not short at all. :(
My language has absolutely no way what-so-ever of creating an array with keys and values defined, so, everything has to be generated.

{@setA 1,1,2,2,3,3,-1,-1,-2,-3}{@setL"AVNZMWCUSO"}{@eachL}{@setA.[_]A.[__]}{@/}{@eachargv.0}{@incbyA.[_]R}{@/}{@echoR}

This simply outputs the sharpness of the word.


Ungolfed

The code above is just a mess! Here's a readable version:

{@set rates 1,1,2,2,3,3,-1,-1,-2,-3}
{@set letters "AVNZMWCUSO"}
{@each letters as letter key i}
    {@set rates.[letter] rates.[i]}
{@/}

{@set result 0}

{@each argv.0 as char}
    {@inc by rates.[char] result}
{@/}
{@echo result}

Should be fairly easy to understand.

The {@inc by rates.[char] result} will increment the result by rates.[char] (similar to result += rates[char] on other languages).


You can try this on http://sandbox.onlinephpfunctions.com/code/54adfe0b61fe1a12f3be085d0e058123a7842627
There you have the golfed version, ungolfed and a function implementation (the {@echo result} is replaced with {@return result}).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.