8
\$\begingroup\$

A port of my other question: Double Prime Words

Consider a word/string of n alphanumeric characters with sum of the characters, s, using their numeric position in the alphabet (a=1, B=2, c=3, etc.) or numeric value (0,1, 2, 3 - 9). Numeric characters should be taken at individual value. (66 is two 6 characters for a sum of 12)

A word is a Length-Sum Multiple if and only if s is a multiple of n, specifically s/n is a positive integer {1,2,3,4...}. In the case of s=0, and n={0,00,000,...}, 0 is a multiple of any n but it does not yield a positive integer. Hence an input of {0,00,000,...} is False.

Input can be any combination of numbers and upper or lower case alphabetic characters, as there is no numeric difference between a or A. Handling empty input, n=s=0, is not required.

Output is any appropriate logical format related to your language. i.e. True or False, T or F, 1 or 0, positive for truthy and 0 for falsy, etc. Specifying what format your output will appear is highly appreciated, but not required. (Output need not include n or s, but I include them below as demonstration and example)

Winning condition: In as few bytes as possible, write a function that is able to determine if a string is a Length-Sum Multiple.

Examples

Input -> Output (n,s) 

hello -> False (5, 52) 
MuLtIpLe -> False (8, 108)
Junct10n -> False (8, 83)
Order66 -> False (7, 72)
CodeGolf -> False (8, 67)
SUM -> False (3, 53)
ID -> False (2, 13)

25 -> False (2, 7)
0 -> False (1, 0) 0/1 = 0 which is not a positive integer
10 -> False (2, 1) 

hello2 -> True (6, 54)
5um -> True (3, 39)
length -> True (6, 66)
Order64 -> True (7, 70)
Covid19 -> True (7, 63)
Word -> True (4, 60)
APPLE -> True (5, 50)
lawYER -> True (6, 84)
abc123 -> True (6, 12)
is -> True (2, 28)
television -> True (10, 130)
19 -> True (2, 10)
234 -> True (3, 9)

a -> True (1, 1)
b -> True (1, 2)
C -> True (1, 3)
Z -> True (1, 26)
1 -> True (1, 1)
9 -> True (1, 9)
\$\endgroup\$
  • 2
    \$\begingroup\$ Sorry I missed this in the sandbox. Overall, a very good challenge! One thing though - I would consider allowing answerers to specify if they want input as whatever, all uppercase, or all lowercase - for most submissions, requiring both will just make them put a ".lower()" at the beginning which doesn't add much interesting to solutions. Up to you though - I think there could definitely be some interesting approaches this way too! \$\endgroup\$ – HyperNeutrino Sep 21 at 15:30
  • 3
    \$\begingroup\$ For whatever one opinion is worth, I don't agree with the idea to allow only upper & only lower. \$\endgroup\$ – Dominic van Essen Sep 21 at 15:35
  • 6
    \$\begingroup\$ Why is 0 falsey? 0 IS divisible by 1.. \$\endgroup\$ – Kevin Cruijssen Sep 21 at 15:40
  • 2
    \$\begingroup\$ "if and only if s is a multiple of n, or more strictly \$s \equiv 0 \mod n\$, or even \$s\div n\$ is a positive integer \${1,2,3,4...}\$" These three contradict each other for \$s = 0\$ \$\endgroup\$ – caird coinheringaahing Sep 21 at 15:46
  • 2
    \$\begingroup\$ @Sumner18 The contradiction is in "s is a multiple of n" and "more strictly s mod n == 0" compared with "s/n is a positive integer". The first two are true for \$s=0\$ and the third isn't. I'd recommend removing the first two and just use the third, which is rigorous enough to work by itself \$\endgroup\$ – caird coinheringaahing Sep 21 at 16:06

21 Answers 21

4
\$\begingroup\$

05AB1E, 16 15 bytes

þIáÇ32%«ODXgÖ*Ā

Input as a list of characters.

-1 byte implicitly thanks to @ovs.

Try it online or verify all test cases.

Explanation:

þ                # Only leave the digits of the (implicit) input-list
 Iá              # Push the input-list again, and only leave its letters
   Ç             # Convert each letter to its codepoint integer
    32%          # Take modulo-32 on each codepoint
       «         # Merge it to the list of digits
        O        # Sum this list
         D       # Duplicate this sum
          Ig     # Push the input-list again, and pop and push its length
            Ö    # Check if the sum is divisible by this length
             *   # Multiply it by the duplicated sum
              Ā  # And check that this is NOT 0
                 # (after which the result is output implicitly)

3 bytes (D*Ā) are used for edge-cases 0/00/000/etc.

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ I had þSDŠKÇžw%«ODIgÖ*Ā - only one byte longer :). \$\endgroup\$ – ovs Sep 21 at 16:04
  • \$\begingroup\$ @ovs Nice. I was actually just looking for some alternatives and found another 16-byter: Asálk>®þ«OD®gÖ*Ā. No 15-byter yet, although I have the feeling it's possible. \$\endgroup\$ – Kevin Cruijssen Sep 21 at 16:07
  • \$\begingroup\$ @ovs Actually, I think your approach opens up a 15-byter like this: þIáÇžw%«ODIgÖ*Ā, so thanks. :) \$\endgroup\$ – Kevin Cruijssen Sep 21 at 16:09
4
\$\begingroup\$

Jelly,  12  11 bytes

ŒlO%48Sȯ.%L

A monadic Link accepting a list of characters which yields zero (falsey) if the string is a length-sum-multiple or a non-zero number (truthy) if not.

Try it online! Or see the test-suite.

How?

ŒlO%48Sȯ.%L - Link: list of characters, w  e.g. "ID"       "10"     "19"     "0...0"
Œl          - lower-case (w)                    "id"       "10"     "19"     "0...0"
  O         - ordinals                          [105,100]  [49,48]  [49,57]  [48,...,48]
    48      - forty-eight                       48         48       48       48
   %        - modulo                            [9,4]      [1,0]    [1,9]    [0,...,0]
      S     - sum                               13         1        10       0
        .   - a half                            0.5        0.5      0.5      0.5
       ȯ    - logical OR                        13         1        10       0.5
         L  - length (w)                        2          2        2        length(w)
        %   - modulo                            1          1        0        0.5
                                               (nope       nope     yep!     nope)
| improve this answer | |
\$\endgroup\$
4
\$\begingroup\$

C (gcc), 73 \$\cdots\$ 63 61 bytes

Saved a 3 bytes thanks to ceilingcat!!!

n;u;f(char*s){for(n=u=0;*s;++n)u+=*s&15+*s++/64*16;u*=u%n<1;}

Try it online!

Inputs a string and returns a truthy if it's a Length-Sum Multiple or a falsey otherwise.

| improve this answer | |
\$\endgroup\$
4
\$\begingroup\$

J, 29 24 bytes

#(|=0=])1#.48|64|96|3&u:

Try it online!

-5 bytes thanks to xash

Inspired by Neil's answer -- be sure to upvote him.

  • 3&u: turns the string into ascii codes
  • 96| mods the lowercase letters into the range 1-26
  • 64| mods the uppercase letters into the range 1-26
  • 48| mods the digits into the range 0-9
  • 1#. sum of all those converted digits
  • # (on the far left) length of string
  • (|=0=]) First we check if the sum is zero 0=] -- this will return 1 when it is and 0 otherwise. Then we check if sum mod the length | is equal to that. Thus for the entire phrase to return true it must be the case that the sum is both evenly divisible its length and nonzero.

Why can't you just use a single 32 mod instead of doing a 96 followed by a 64?

With 32, you'd be affecting the values 0-9 as well. With 96/64, you fix the letters without touching the digits, and now, since the letters are all 26 and under, when you fix the digits the already-fixed letters are unaffected.

| improve this answer | |
\$\endgroup\$
  • 2
    \$\begingroup\$ 24 bytes \$\endgroup\$ – xash Sep 21 at 21:25
  • 2
    \$\begingroup\$ Excellent. That added enough cleverness to be worthy of explanation :) \$\endgroup\$ – Jonah Sep 21 at 21:40
  • \$\begingroup\$ Based on the explanation, I would have guessed that one could replace both 64| and 96| with 32|, but that doesn't seem to be the case when I try... \$\endgroup\$ – Dominic van Essen Sep 22 at 13:32
  • 1
    \$\begingroup\$ Got it! It's right-to-left mods of the same number, right? Sorry for not having any clue about J syntax... \$\endgroup\$ – Dominic van Essen Sep 22 at 13:40
  • 1
    \$\begingroup\$ I love it! ...and, I've immediately stolen that trick to save 1 byte in my R answer. Thankyou very much! \$\endgroup\$ – Dominic van Essen Sep 22 at 13:43
3
\$\begingroup\$

Python 3, 54 bytes

lambda s:(sum(ord(c)%48for c in s.lower())or.5)%len(s)

An unnamed function accepting a string which returns zero (falsey) if the string is a length-sum-multiple or a non-zero number (truthy) if not.

Try it online! Or see the test-suite.

| improve this answer | |
\$\endgroup\$
3
\$\begingroup\$

R, 63 62 57 56 bytes

Edit: saved 1 byte thanks to Jonah

function(s)!sum(i<-utf8ToInt(s)%%96%%64%%48)%%nchar(s)&i

Try it online!

Output is Truthy list of one-or-more TRUEs, or Falsy list of one-or-more FALSEs.

| improve this answer | |
\$\endgroup\$
3
\$\begingroup\$

Scala, 71 62 46 bytes

s=>{val x=(0/:s)(_+_%96%64%48);x>0&x%s.size<1}

Try it online

32 bytes if zero weren't falsey

s=>(0/:s)(_+_%96%64%48)%s.size<1

Try it online

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ As far as I can tell yours fails on the "0" test case \$\endgroup\$ – Mr Redstoner Sep 21 at 20:23
  • \$\begingroup\$ @MrRedstoner Fixed it for 71 bytes :( \$\endgroup\$ – user Sep 22 at 12:50
  • \$\begingroup\$ 67 bytes: s=>{val x=s.map{x=>if(x.isDigit)x%48 else x%32}.sum;x>0&x%s.size<1} \$\endgroup\$ – Dominic van Essen Sep 22 at 13:27
  • \$\begingroup\$ If you 'steal' the amazingly-cunning trick from xash's tip for Jonah's answer, you could even get 50 bytes: s=>{val x=s.map{x=>x%96%64%48}.sum;x>0&x%s.size<1}... (at which point you'll be beating me...). \$\endgroup\$ – Dominic van Essen Sep 23 at 7:50
  • \$\begingroup\$ @DominicvanEssen Wow, that's really clever \$\endgroup\$ – user Sep 23 at 13:31
3
\$\begingroup\$

Java 79 77 68 66 64 bytes

s->{int u=0;for(int c:s)u+=c%96%64%48;return u>0&u%s.length<1;};

Try it here!

My first ever answer! The "0" test case messed me up, without it I could have had 51, (I wanted to try challenge the C answer, from which I've borrowed the char-to-number conversion). Now pretty much a port of the C answer.

s->s.chars().map(c->c%96%64%48).sum()%s.length()<1;

Still fairly proud of beating out some of current answers in languages like Python and JavaScript using the 'oh so verbose' Java.

Thanks to @user for a few extra bytes saved

@ceilingcat for a few more

@dominic-van-essen for 2 more using @xash's idea

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ @user thanks, I really should have taken a better look at that C submission and realized that myself. \$\endgroup\$ – Mr Redstoner Sep 21 at 18:40
  • \$\begingroup\$ 68 bytes if you use an array \$\endgroup\$ – user Sep 21 at 18:46
  • \$\begingroup\$ A shame about loosing Stream and making it pretty much a port of the C answer, but at least the fails-on-"0" is staying a Stream because I can't find a way to apply the same improvement without making it worse. \$\endgroup\$ – Mr Redstoner Sep 21 at 18:56
  • 1
    \$\begingroup\$ Very nice answer! 64 bytes if you steal xash's MOD tip for Jonah's answer. \$\endgroup\$ – Dominic van Essen Sep 24 at 6:40
2
\$\begingroup\$

Python 3.8, 59 bytes

lambda d:1>(x:=sum(int(c,36)-9*(c>'9')for c in d))%len(d)<x

Try it online!

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ is this "x:=" an assignment inside an expression? That's rather new isn't it? \$\endgroup\$ – Teck-freak Sep 21 at 16:00
  • 1
    \$\begingroup\$ @Teck-freak yes it was introduced in version 3.8 and is called assignment expression. The walrus operator is quite handy for golfing. \$\endgroup\$ – ovs Sep 21 at 16:07
  • \$\begingroup\$ yes, I even played around a bit when it was introduced. I completely forgot about it, as I'm mainly doing addons in 2.7 and 3.4 and maybe 3.7 Nice idea going with a base36 int by the way. \$\endgroup\$ – Teck-freak Sep 21 at 16:12
2
\$\begingroup\$

Charcoal, 18 bytes

≔ΣE↧θ﹪℅ι⁴⁸η∧η¬﹪ηLθ

Try it online! Link is to verbose version of code. Output is a Charcoal boolean, i.e. - for a multiple, nothing if not. Explanation:

≔ΣE↧θ﹪℅ι⁴⁸η

Convert the string to lower case, take the code points of all the characters, reduce them modulo 48, then take the sum.

∧η¬﹪ηLθ

Check that the sum is a non-zero multiple of the length of the string.

| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

Perl 5 + -plF, 32 bytes

-7 bytes thanks to @Nahuel Fouilleul!

$s+=ord(lc)%48for@F;$_&&=1>$s%@F

Try it online!

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ 38 bytes without using sum Try it online! \$\endgroup\$ – Nahuel Fouilleul Sep 22 at 9:44
  • \$\begingroup\$ @NahuelFouilleul Nice! Much cleaner, thank you! I wasn't happy with it last night, but I didn't have time to go back to it :) \$\endgroup\$ – Dom Hastings Sep 22 at 10:52
  • \$\begingroup\$ nice trick to switch to lowercase so that 96%48 is also 0 \$\endgroup\$ – Nahuel Fouilleul Sep 22 at 17:47
1
\$\begingroup\$

Python 3, 101 96 bytes

def f(s):x=sum([i-[48,96][i>96]for i in map(ord,s.lower())]);return not(x%len(s))and x//len(s)>0

Try it online!

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ You can replace your ternery construct "-96if i>96else i-48" with "-[48,96][i>96]" which saves you 5 bytes (boolean as index). \$\endgroup\$ – Teck-freak Sep 21 at 16:20
  • \$\begingroup\$ You can return "not x%len(s)" The brackets fall away (operation-order) and the "and"-part isn't needed as the only case where it is 0 is for empty strings, or if we have rest. empty strings need not be checked and rests are already indicating a False => saves 16 Bytes \$\endgroup\$ – Teck-freak Sep 21 at 16:26
1
\$\begingroup\$

Jelly, 23 bytes

ØWiⱮ_³e€ØD¤%26Sµ;ọ³L¤$Ȧ

Try it online!

Golfed 1 byte and also made the program actually work (third time's a charm? it was still broken)

Explanation

ØWiⱮ_³e€ØD¤%26Sµ;ọ³L¤$Ȧ  Main Link
   Ɱ                     For each character in the input
  i                      find its index in
ØW                       "ABC...XYZabc...xyz0123456789_"
    _                    and subtract from each element
     ³e€ØD¤              the corresponding value, which is
     ³                   if the original character
      e€                 is a member of
        ØD               the digits (this is to fix the one-off offset of the digits)
                         (the above nilad gets a list of 0 and 1 for if each character is a digit, and since Jelly's subtraction `_` is vectorized, this works as subtracting the corresponding element)
           %26           modulo 26
              Sµ         take the sum; begin a new link with this value
                ;    $   append
                 ọ       the number of times the sum is divisible by (just plain "divisible by?" has the arguments in the opposite order which would take 1 extra byte to flip)
                  ³L¤    the length of the input
                      Ȧ  any and all - are both values truthy; that is, is the sum divisible and non-zero?
| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ This fails for 0, an irritating corner case \$\endgroup\$ – caird coinheringaahing Sep 21 at 16:16
  • \$\begingroup\$ @cairdcoinheringaahing i thought i fixed that lol??? well, thanks for pointing that out, i managed to golf 0 bytes with a different approach but it did fix the problem! \$\endgroup\$ – HyperNeutrino Sep 21 at 16:22
  • \$\begingroup\$ Well, it's a better answer than mine (yours actually works :P), very nice :D. Interesting that you used ØW (my original approach used ØB) \$\endgroup\$ – caird coinheringaahing Sep 21 at 16:23
  • 1
    \$\begingroup\$ @cairdcoinheringaahing yeah my first try used that and I think I just ended up copy-pasting a different one when I retried with this approach lol \$\endgroup\$ – HyperNeutrino Sep 21 at 16:24
1
\$\begingroup\$

Japt, 22 17 15 bytes

Input is an array of characters.

Or 13 bytes, without having to special-case 0.

xÈv c u48
©vNÎl

Try it

;x@ÒBbXu)ªX\n©vNÎl     :Implicit input of character array U
 x                     :Reduce by addition
  @                    :After passing each X through the following function
   Ò                   :  Negate the bitwise NOT of
;   B                  :  Uppercase alphabet
     b                 :  0-based index of
      Xu               :    Uppercase X
        )              :  End indexing
         ªX            :  Logical OR with X, which gets coerced to an integer
           \n          :Reassign to U
             ©         :Logical AND with
              v        :  Is divisible by
               N       :  Array of all inputs
                Î      :  First element (i.e., the original U)
                 l     :  Length
| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

JavaScript (Node.js),  54  53 bytes

Returns 0 or 1.

s=>Buffer(s).map(c=>t+=++k&&c%96%64%48,k=t=0)|t%k<!!t

Try it online!

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Python 2 & Python 3 -- 69 Bytes

lambda a:0==sum(ord(s.upper())-[64,48][s.isdigit()]for s in a)%len(a)

Assuming the input as string on variable a, one can get down to 60 Bytes

0==sum(ord(s.upper())-[64,48][s.isdigit()]for s in a)%len(a)
| improve this answer | |
\$\endgroup\$
  • 3
    \$\begingroup\$ Hello, based on site consensus, input cannot be taken as a variable. You could wrap your program into a function/lambda and it would be valid. Also, your program has to either output the value or return it from a function, it cannot be a single expression that evaluates to the answer. \$\endgroup\$ – HyperNeutrino Sep 21 at 16:00
  • \$\begingroup\$ Hello @HyperNeutrino I fail to see how a single expression is not applicable, but yes, I'll modify it into a lambda. (it is my fift golf and the first in over 2 years.) \$\endgroup\$ – Teck-freak Sep 21 at 16:08
0
\$\begingroup\$

JavaScript, 107 bytes

a=>(b=a.toLowerCase().split('').reduce((c,d)=>c+(+(isNaN(d)?d.charCodeAt(0)-96:d)),0)/a.length,!(b?b%1:!b))

Try it online!

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Retina 0.8.2, 63 bytes

^
$.'$*1;
T`L`l
[j-z]
55$&
[t-z]
55$&
T`_l`ddd
\d
$*
^(1+);\1+$

Try it online! Link includes test cases. Explanation:

^
$.'$*1;

Prefix the input with a unary copy of itself.

T`L`l

Convert it to lower case.

[j-z]
55$&
[t-z]
55$&
T`_l`ddd

Convert the letters to digits with the same digital sum.

\d
$*

Take the digital sum.

^(1+);\1+$

Check that it is a non-zero multiple of the length.

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

MAWP, 78 bytes

%|0/[!843WWP843WWWA/]~[!88WP88WWA/]~[!86WP86WWA/]_1A![1A~M~]%!~!~/P\WA{0:.}?1:

Try it!

Waiting for answer in 1+...

Uses the modulus method from Jonah's J answer.

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

MATL, 12 11 bytes

k48\stGn\~*

Output is 0 if the input is length-sum multiple, or a positive number otherwise.

Try it online! Or verify all test cases.

How it works

k     % Implicit input. Convert to lowercase
48    % Push 48
\     % Modulus. Each character is first converted to its code-point
s     % Sum. This gives "s"
t     % Duplicate (*)
G     % Push input again
n     % Number of elements. This gives "n"
\     % Modulus
~     % Negate. This gives true if s mod n equals 0, or false otherwise (**)
*     % Multiply (*) and (**)
      % Implicit display. True and false are displayed as 1 and 0 respectively
| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Wolfram Language (Mathematica), 54 bytes

Tr[a=FromDigits/@#/.a_/;a>9:>a-9]~Mod~Tr[1^#]==0<Tr@a&

Try it online! Pure function. Takes a list of characters as input and returns True or False as output. The bulk of the work is done by FromDigits, which converts the characters 0-9, A-Z to the numbers 0-35.

| improve this answer | |
\$\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.