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)
21 Answers 21
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.
-
1\$\begingroup\$ I had
þSDŠKÇžw%«ODIgÖ*Ā- only one byte longer :). \$\endgroup\$ovs– ovs2020年09月21日 16:04:03 +00:00Commented Sep 21, 2020 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– Kevin Cruijssen2020年09月21日 16:07:27 +00:00Commented Sep 21, 2020 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– Kevin Cruijssen2020年09月21日 16:09:54 +00:00Commented Sep 21, 2020 at 16:09
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)
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;}
Inputs a string and returns a truthy if it's a Length-Sum Multiple or a falsey otherwise.
J, 29 24 bytes
#(|=0=])1#.48|64|96|3&u:
-5 bytes thanks to xash
Inspired by Neil's answer -- be sure to upvote him.
3&u:turns the string into ascii codes96|mods the lowercase letters into the range 1-2664|mods the uppercase letters into the range 1-2648|mods the digits into the range 0-91#.sum of all those converted digits#(on the far left) length of string(|=0=])First we check if the sum is zero0=]-- this will return1when it is and0otherwise. 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.
-
2
-
2\$\begingroup\$ Excellent. That added enough cleverness to be worthy of explanation :) \$\endgroup\$Jonah– Jonah2020年09月21日 21:40:35 +00:00Commented Sep 21, 2020 at 21:40
-
\$\begingroup\$ Based on the explanation, I would have guessed that one could replace both
64|and96|with32|, but that doesn't seem to be the case when I try... \$\endgroup\$Dominic van Essen– Dominic van Essen2020年09月22日 13:32:19 +00:00Commented Sep 22, 2020 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– Dominic van Essen2020年09月22日 13:40:22 +00:00Commented Sep 22, 2020 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– Dominic van Essen2020年09月22日 13:43:29 +00:00Commented Sep 22, 2020 at 13:43
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.
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
Output is Truthy list of one-or-more TRUEs, or Falsy list of one-or-more FALSEs.
Scala, (削除) 71 (削除ここまで) (削除) 62 (削除ここまで) 46 bytes
- Fixed answer thanks to @Mr Redstoner
- Saved 9 bytes thanks to @Dominic Van Essen
- Saved 16 bytes! thanks to the tip @xash gave on Jonah's answer, which Dominic Van Essen suggested.
s=>{val x=(0/:s)(_+_%96%64%48);x>0&x%s.size<1}
32 bytes if zero weren't falsey
s=>(0/:s)(_+_%96%64%48)%s.size<1
-
\$\begingroup\$ As far as I can tell yours fails on the "0" test case \$\endgroup\$Mr Redstoner– Mr Redstoner2020年09月21日 20:23:42 +00:00Commented Sep 21, 2020 at 20:23
-
\$\begingroup\$ @MrRedstoner Fixed it for 71 bytes :( \$\endgroup\$user– user2020年09月22日 12:50:43 +00:00Commented Sep 22, 2020 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– Dominic van Essen2020年09月22日 13:27:28 +00:00Commented Sep 22, 2020 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– Dominic van Essen2020年09月23日 07:50:48 +00:00Commented Sep 23, 2020 at 7:50 -
\$\begingroup\$ @DominicvanEssen Wow, that's really clever \$\endgroup\$user– user2020年09月23日 13:31:35 +00:00Commented Sep 23, 2020 at 13:31
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;};
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
-
1\$\begingroup\$ @user thanks, I really should have taken a better look at that C submission and realized that myself. \$\endgroup\$Mr Redstoner– Mr Redstoner2020年09月21日 18:40:19 +00:00Commented Sep 21, 2020 at 18:40
-
-
\$\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– Mr Redstoner2020年09月21日 18:56:36 +00:00Commented Sep 21, 2020 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– Dominic van Essen2020年09月24日 06:40:53 +00:00Commented Sep 24, 2020 at 6:40
-
\$\begingroup\$ is this "x:=" an assignment inside an expression? That's rather new isn't it? \$\endgroup\$Teck-freak– Teck-freak2020年09月21日 16:00:01 +00:00Commented Sep 21, 2020 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– ovs2020年09月21日 16:07:31 +00:00Commented Sep 21, 2020 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– Teck-freak2020年09月21日 16:12:11 +00:00Commented Sep 21, 2020 at 16:12
Charcoal, 18 bytes
≔ΣE↧θ%c/oι48η∧η¬%η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↧θ%c/oι48η
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.
-
1\$\begingroup\$ 38 bytes without using sum Try it online! \$\endgroup\$Nahuel Fouilleul– Nahuel Fouilleul2020年09月22日 09:44:09 +00:00Commented Sep 22, 2020 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– Dom Hastings2020年09月22日 10:52:25 +00:00Commented Sep 22, 2020 at 10:52
-
\$\begingroup\$ nice trick to switch to lowercase so that 96%48 is also 0 \$\endgroup\$Nahuel Fouilleul– Nahuel Fouilleul2020年09月22日 17:47:40 +00:00Commented Sep 22, 2020 at 17:47
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
-
\$\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– Teck-freak2020年09月21日 16:20:46 +00:00Commented Sep 21, 2020 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– Teck-freak2020年09月21日 16:26:22 +00:00Commented Sep 21, 2020 at 16:26
Jelly, 23 bytes
ØWiⱮ_3e€ØD¤%26Sμ;ọ3L¤$Ȧ
Golfed 1 byte and also made the program actually work (third time's a charm? it was still broken)
Explanation
ØWiⱮ_3e€ØD¤%26Sμ;ọ3L¤$Ȧ Main Link
Ɱ For each character in the input
i find its index in
ØW "ABC...XYZabc...xyz0123456789_"
_ and subtract from each element
3e€ØD¤ the corresponding value, which is
3 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)
3L¤ the length of the input
Ȧ any and all - are both values truthy; that is, is the sum divisible and non-zero?
-
1\$\begingroup\$ This fails for
0, an irritating corner case \$\endgroup\$2020年09月21日 16:16:58 +00:00Commented Sep 21, 2020 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\$2020年09月21日 16:22:30 +00:00Commented Sep 21, 2020 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\$2020年09月21日 16:23:36 +00:00Commented Sep 21, 2020 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\$2020年09月21日 16:24:56 +00:00Commented Sep 21, 2020 at 16:24
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
;x@ÒBbXu)aX\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
aX : 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
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
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)
-
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\$2020年09月21日 16:00:15 +00:00Commented Sep 21, 2020 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– Teck-freak2020年09月21日 16:08:15 +00:00Commented Sep 21, 2020 at 16:08
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))
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.
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
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.
.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\$0falsey?0IS divisible by 1.. \$\endgroup\$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\$