26
\$\begingroup\$

Introduction

A pure word (or perfect word), as defined by me, is a word where the sum of the position in the alphabet of each letter in the word is perfectly divisible by the total length of the word. For example, abcb is a perfect word because 1 + 2 + 3 + 2 = 8, and 8 / 4 = 2.

Your task

Given a word as input, output whether or not it is a perfect word. The word may always be assumed to be lowercase.

Scoring

This is code-golf, so shortest program in bytes wins.

Examples

abcb: truthy
ccc: truthy
aaa: truthy
pure: truthy
word: truthy
bed: falsy
code: falsy
bode: falsy
\$\endgroup\$
7
  • \$\begingroup\$ What type of outputs are allowed? For example, 0 for truthy and a non-consistent nonzero number for falsy? Any two values? Truthy and falsy swapped? @All: you may want to vote here \$\endgroup\$
    – Luis Mendo
    Jan 15, 2022 at 11:21
  • \$\begingroup\$ @LuisMendo check the related meta post \$\endgroup\$
    – Ginger
    Jan 15, 2022 at 17:18
  • 3
    \$\begingroup\$ I know what "truthy" and "falsy" mean. I'm asking if the outputs can be non-consistent values (i.e. more than two values), or for example two distinct truthy values. You need to specify the output options allowed by the challenge. Voting to close as unclear until resolved \$\endgroup\$
    – Luis Mendo
    Jan 15, 2022 at 17:33
  • 8
    \$\begingroup\$ @taRadvylfsriksushilani The consensus appears not to be. However I would really like it if something as basic as output specifications were put in the challenge itself instead of hidden away somewhere on meta. It's not very beginner friendly seeing as experienced users don't seem to always recall the exact state of the meta. \$\endgroup\$
    – Wheat Wizard
    Jan 15, 2022 at 20:23
  • 1
    \$\begingroup\$ you may be interested to know that "word" itself is a perfect word, as is "pure". "perfect" itself is not one, so perhaps they should be known as pure words? \$\endgroup\$
    – Rugnir
    Jan 15, 2022 at 21:21

58 Answers 58

1
2
3
\$\begingroup\$

Zsh, 31 bytes

a=(+\#\#${(s::)^1})
(((a)%$#1))

Try it online!

In Zsh, ##x in arithmetic mode returns the codepoint of 'x'.

        ${(s::) 1}    # split $1 into characters
   +\#\#${(s::)^1}    # append `+##` to each element
a=(+\#\#${(s::)^1})   # save as $a
(((a)%$#1))           # join $a on spaces, evaluate (+##a +##b ...) % $#1
                      # arithmetically
\$\endgroup\$
3
\$\begingroup\$

Python, 125 bytes

Wow I feel like an idiot after reading all these other amazing answers.

j=[ord(k)-96 for k in str(input(""))]
l=len(j)
while len(j)>1:j[0]+=j[1];del j[1]
print("%sy"%("truth"if j[0]%l<1else"fals"))

I think how this works is pretty trivial.

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

Pyth, 7 bytes

!%sCMQl

Test suite

Explanation:
!%sCMQl  | Full code
!%sCMQlQ | with implicit variables filled
---------+-------------------------------------------------------
   CMQ   | Replace each character in the input with its codepoint
  s      | Sum the resulting list
 %    lQ | Mod the sum with the length of the input
!        | Boolean negate (i.e. 0 -> True, other -> False)
\$\endgroup\$
3
\$\begingroup\$

MathGolf, 5 bytes

$Σ\£÷

Input as a list of characters. Could be 1 byte less by taking the input as a list of codepoints.

Try it online.

Explanation:

$     # Map each character in the (implicit) input-list to a codepoint integer
 Σ    # Sum this list
  \   # Swap so the (implicit) input-list is at the top again
   £  # Pop and push its length
    ÷ # Check if the earlier sum is divisible by this length
      # (after which the entire stack is output implicitly as result)
\$\endgroup\$
3
\$\begingroup\$

Whitespace, 113 bytes

[S S S N
_Push_0][S N
S _Duplicate_0][S N
S _Duplicate_0][N
S S N
_Create_Label_LOOP][S N
S _Duplicate][S N
S _Duplicate][T N
T   S _Read_STDIN_as_char][T    T   T   _Retrieve_input][S N
S _Duplicate][S S S T   S T S N
_Push_10][T S S T   _Subtract][N
T   S S N
_If_0_jump_to_Label_PRINT_RESULT][T S S S _Add][S N
T   _Swap_top_two][S S S T  N
_Push_1][T  S S S _Add][S N
T   _Swap_top_two][N
S N
N
_Jump_to_Label_LOOP][N
S S S N
_Create_Label_PRINT_RESULT][S N
N
_Discard_top][S N
T   _Swap_top_two][T    S T T   _Modulo][N
T   S T N
_If_0_Jump_to_Label_TRUTHY][S S T   T   N
_Push_-1][N
S S T   N
_Create_Label_TRUTHY][S S S T   N
_Push_1][T  S S S _Add][T   N
S T _Print_as_integer]

Letters S (space), T (tab), and N (new-line) added as highlighting only.
[..._some_action] added as explanation only.

Since Whitespace can only read input one character at a time, the input must contain a trailing newline so we'll know when we're done reading characters.
Whitespace also lacks truthy/falsey values, so this program will output 1 for truthy and 0 for falsey (could be 28 bytes less with 0 as truthy and a positive integer as falsey).

Try it online (with raw spaces, tabs and new-lines only).

Explanation in pseudo-code:

Integer length = 0
Integer sum = 0
Start LOOP:
  Integer input = STDIN as character
  If(input == '\n'):
    Jump to PRINT_RESULT
  sum = sum + input
  length = length + 1
  Go to next iteration of LOOP

PRINT_RESULT:
  Integer result = 0
  Integer mod = sum modulo length
  If(mod == 0):
    Skip to TRUTHY
  Else:
    result = -1
  TRUTHY:
  result = result + 1
  Print result as integer to STDOUT
\$\endgroup\$
3
\$\begingroup\$

C (clang), 49 bytes

i,l;f(*a){for(i=l=0;*a;i+=*a++)l++;return!(i%l);}

Try it online!

Takes input as a wide string; returns 1 for pure words and 0 for others.

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

Fig, \$4\log_{256}(96)\approx\$ 3.292 bytes

%LxS

Try it online!

Port of K answer. Prints 0 for truthy and a positive number for falsey.

%LxS
   S # Sum of charcodes
%    # Modulo
 Lx  # Length of input
\$\endgroup\$
3
\$\begingroup\$

K (ngn/k), 11 10 bytes

{(#x)!+/x}

Try it online!

Saves a byte by not using the Not operator (~)

Quick and simple. Return 0 for true and any other value for false.

Explanation:

{(#x)!+/x}    Main function. Takes x as input
      +/x     Sum of all charcodes in x
     !        Modulo
 (#x)         Length of x
\$\endgroup\$
3
\$\begingroup\$

Arturo, 41 bytes

$=>[=floor<=average map&=>[to :integer&]]

Try it

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

><> (Fish), 26 24 23 20 19 17 bytes

l&v
v+>l1-?!
>&%n

Try it

Exits with error, which is allowed by default.

This is my first answer in this language, so it can probably be golfed.

Input is assumed to be on the stack. Output is any non-zero number for falsy, 0 for truthy.

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

Trilangle, 28 bytes

'0|2_~<.+!>S/>i,..<.@2\)/(%S

Prints "0" if the word is pure.

Try it on the online interpreter!

Roughly equivalent to this C code:

#include <stdio.h>

int main() {
    int total = 0, len = 0;
    int c;
    while ((c = getchar()) != EOF) {
        total += c;
        ++len;
    }
    if (total % len == 0) puts("0");
}

The code unfolds to this triangle:

      '
     0 |
    2 _ ~
   < . + !
  > S / > i
 , . . < . @
2 \ ) / ( % S

Control flow starts at the north corner heading southwest, on the red path:

  • '0: push a zero to the stack
  • 2: duplicate the top of the stack, so it now contains two zeroes
  • <: redirect control flow
  • i: read a single character in and push it to the stack
  • >: branch

If EOF was read, control flow continues on the blue path; otherwise, control flow continues on the green path.

The green path performs the necessary additions before looping:

  • +: add the top two values on the stack
  • _: redirect control flow
  • .: no-op
  • S: swap the top two values in the stack
  • .: no-op
  • \: redirect control flow
  • ): increment the top of the stack
  • /: redirect control flow
  • .: no-op again
  • S: swap the values back
  • <: redirect control flow, merging with the red path

On the blue path (after EOF is read), the following instructions are seen:

  • <: redirect control flow
  • ..: more no-ops
  • ,: pop the EOF off the stack
  • S: swap the two values on the top of the stack
  • %: pop two values off the stack and push a % b
  • (: decrement the top of the stack
  • /: redirect control flow
  • 2: duplicate the top of the stack
  • .: another no-op
  • /: redirect control flow
  • S: "swap" the two values in the stack (effectively a no-op, since they're the same value)
  • >: branch

If the word is pure, the stack contains two -1's, and the interpreter takes the magenta path. If the word is not pure, the stack contains two copies of some non-negative number, and the interpreter takes the yellow path.

On the magenta path, it prints a 0 before exiting:

  • ,: pop a value off the top of the stack
  • 2: duplicate the top of the stack (not necessary on this code path, but harmless)
  • |: redirect control flow
  • ~: bitwise complement, changes -1 to 0
  • !: print the top of the stack as a decimal integer
  • i: attempt to read more input (always sees EOF)
  • @: end program

The yellow path has a rather convoluted no-op before it exits:

  • \: no-op when traversed in this direction
  • ,: pop from the stack
  • 2: duplicate the value on the stack (cancels out the ,)
  • S: "swap" the two identical values
  • @: end program.
\$\endgroup\$
2
\$\begingroup\$

Python 3, 55 bytes

lambda s:(sum(ord(c)-95for c in s)/len(s)).is_integer()

Try it online!

\$\endgroup\$
3
  • 2
    \$\begingroup\$ By the looks of it the code divides by 2. Shouldn't it divide by len(s), or am I overlooking something? \$\endgroup\$ Jan 14, 2022 at 23:19
  • \$\begingroup\$ @dingledooper woops, will fix \$\endgroup\$ Jan 14, 2022 at 23:21
  • \$\begingroup\$ You can get 53 bytes with the walrus operator lambda s:int(b:=(sum(ord(c)-95for c in s)/len(s)))==b (though tio.run doesn't recognize it) \$\endgroup\$ Jan 20, 2022 at 3:30
2
\$\begingroup\$

Kotlin, 85 bytes

fun i(s:String):Int{var a=0;for(i in s)a+=i.code-96;return if(a%s.length==0)1 else 0}

Try it online!

Ungolfed version:

fun isPure(s: String) : Int
{
    var acc = 0
    for(i in s) acc+= i.code-96
    return if(acc%s.length==0) 1 else 0
}

1 stands for Truthy and 0 stands for falsy, derived from this post Interpretation of Truthy/Falsey

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

C#, 101 83 bytes

bool P(string w){int i=0;foreach(var c in w){i+=(int)c%32;};return i%w.Length==0;};

Try it online

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Welcome to Code Golf, and nice first answer! Be sure to check out our Tips for golfing in C# page for ways you can golf your program. We allow anonymous functions here, so you should be able to remove the static Func<string,bool> P =, as well as the spaces around the = and => \$\endgroup\$ Jan 28, 2022 at 12:33
  • \$\begingroup\$ @caird thanks for the welcome and the tips, that helped knock a significant chunk off \$\endgroup\$
    – B-Slam
    Jan 28, 2022 at 14:46
  • 1
    \$\begingroup\$ Suggest return i%w.Length<1 instead of return i%w.Length==0 and removing the innermost curly braces. \$\endgroup\$
    – ceilingcat
    Feb 1, 2022 at 10:29
2
+100
\$\begingroup\$

Vyxal, 7 bytes

C₆%₌∑LḊ

Try it Online!

\$\endgroup\$
2
  • \$\begingroup\$ Nice! You don't need the space. \$\endgroup\$
    – emanresu A
    Mar 7, 2022 at 3:12
  • \$\begingroup\$ Try it Online! for 7 bytes. \$\endgroup\$
    – lyxal
    Mar 7, 2022 at 3:31
2
\$\begingroup\$

Nim, 52 bytes

import sequtils,sugar
t=>t.foldl(a+b.int,0)%%t.len<1

Try it online!

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

D, 67 bytes

import std;int p(string w){return !(w.fold!"a+=b-96"(0)%w.length);}

ungolfed

import std;
int p(string w) {
    return !(w.fold!"a+=b-96"(0)%w.length);
}
// not much more readable, lol

takes a string w, and then performs a fold on it. The fold adds each char, minus 96, to the accumulator. 96 being the ascii value of the backtick character, one behind a (since this challenge specifies that the characters are 1-indexed). this effectively adds up all characters in the string. Then we perform a modulo for a divisibility check, and since we want 0 to be the true case, we invert it. Note how we return int from this function so that it takes up one less byte. ints can be implicitly cast to bool so it's fine.

Try it online!

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

GolfScript, 9 bytes

.{+}*\,%!

Try it online!

Explanation

.{+}*\,%! | whole program
 {+}*     | sum the codepoints of the string
.    \,   | push the length
       %  | modulo
        ! | logical negate
\$\endgroup\$
2
\$\begingroup\$

Go, 73 bytes

func(R[]rune)bool{s:=0
for _,r:=range R{s+=int(r-'`')}
return s%len(R)<1}

Attempt This Online!

\$\endgroup\$
1
  • \$\begingroup\$ 69 bytes (using TIO because ATO isn't working for me for some reason) \$\endgroup\$
    – The Thonnu
    Jun 25, 2023 at 14:00
1
\$\begingroup\$

Swift, 42 bytes

{$0.utf8.reduce(0){$0+Int($1)}%$0.count<1}

Try it online!

This uses the same algorithm as the current top answers for Python, Excel, Java, and Scala, and probably others. As for why I use .utf8, see my explanation here. As with that answer, the input type here can be String or Substring, and the output type is Bool.

It still surprises me that Swift has .reduce(0, +) rather than .sum() for collections of numbers.

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

APOL, 32 bytes

v(0 i);!(%(⊕(ƒ(⁰ ⌕(ⓛ ∋))) l(⁰)))

Explanation:

v(            Set memory cell
  0
  i           to input
);
!(            Not
  %(          Modulo
    ⊕(       Sum
      ƒ(      List-builder for
        ⁰     Memory cell 0
        ⌕(    Find
          ⓛ  All ASCII lowercase characters
          ∋   Loop item
        )
      )
    )
    l(        Length of
      ⁰       Memory cell 0
    )
  )
)
\$\endgroup\$
1
\$\begingroup\$

Thunno, \$ 7\log_{256}(96)\approx \$ 5.76 bytes

OSz0L%!

Attempt This Online!

Explanation

OSz0L%!  # Implicit input
 S       # the sum of
O        # the ords of the input
     %!  # is divisible by
    L    # the length of
  z0     # the input?
         # Implicit output
\$\endgroup\$
1
\$\begingroup\$

PHP, 67 bytes

fn($w)=>!(array_sum(array_map('ord',str_split($w)))%96%strlen($w));

Try it online!

Ungolfed

fn($w) => !(array_sum(
    array_map('ord', str_split($w))
  ) % 96 % strlen($w));
\$\endgroup\$
1
\$\begingroup\$

Stax, 5 bytes

:VR1=

Run and debug it

This program's length is the same packed and unpacked, so I chose to use the unpacked version.

Explanation

:V    # mean of array (returns a fraction)
  R   # denominator
    = # is equal to
   1  # 1
\$\endgroup\$
1
\$\begingroup\$

PARI/GP, 40 bytes

Try it online!

f(w)=!(sum(i=1,#w,Vecsmall(w)[i]-96)%#w)
\$\endgroup\$
1
\$\begingroup\$

Lua, 67 59 bytes

s=...a=0s:gsub('.',load'a=a+(...):byte()-96')print(a%#s==0)

Try it online!

Ungolfed version:

s=...
a=0
s:gsub('.',load'a=a+(...):byte()-96')  -- Add up value of chars, store in a
print(a%#s==0)
\$\endgroup\$
1
\$\begingroup\$

minigolf, 12 bytes

i+,ni#*i+=;+

Attempt This Online!

Explanation

i+         sum of codepoints of input
,          map in [1..sum(i)]:
  n          push curr. item
  i#*        Multiply by input's length
  i+=        Is that equal to input's sum?
;          end map
+          Sum the list
           (we definitely have a 1 output for an integer quotient,
            and 0 with no integer output

Implicit output
\$\endgroup\$
1
\$\begingroup\$

Thunno 2 B, 4 bytes

SslḊ

Attempt This Online!

Explanation

SslḊ  # Implicit input, converted
      # to ordinals by B flag
S     # Sum the ordinals
 sl   # Get the length of the input
   Ḋ  # Is divisible?
      # Implicit output
\$\endgroup\$
1
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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