27
\$\begingroup\$

Your task

Given a string of lowercase letters, output the "alphabet checksum" of that string, as a letter.

Example

Let's say we have the string "helloworld". With a = 0, b = 1, c = 2 ... z = 25, we can replace all of the letters with numbers:

h  e  l  l  o  w  o  r  l  d
7  4  11 11 14 22 14 17 11 3

Now, we can sum these:

7+4+11+11+14+22+14+17+11+3 = 114

If we mod this by 26, we get:

114 % 26 = 10

Now, using the same numbering system as before, get the 10th letter, k. This is our answer.

Test cases

Input          Output

helloworld     k
abcdef         p
codegolf       h
stackexchange  e
aaaaa          a

This is , so shortest code in bytes wins.

\$\endgroup\$
1

54 Answers 54

1
2
2
\$\begingroup\$

Zsh, 41 bytes

a=(+##${(s..)^1}+7)
<<<${(#)$((a%26+97))}

Try it online!

(s..)plit, ^ RC-style expand as +##${1[1]}+7 +##${1[2]}+7 .... Then (#) evaluate the expression as character codes.

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

Fig, \$10\log_{256}(96)\approx\$ 8.231 bytes

ica%26S+7C

Using Arnauld's logic. Accepts a list of characters

Try it online!

ica%26S+7C
         C # str -> char code, vectorises
       +7  # add 7 to each item
      S    # sum
   %26     # sum % 26
 ca        # lowercase alphabet
i          # index intro ca using result

Alternate \$13\log_{256}(96)\approx\$ 10.701 bytes

ica%26SM'lxca

Try it online!

ica%26SM'lxca
           ca  # lowercase alphabet
          x    # input
       M'l     # map find over x where we look for each char in ca, returns index
      S        # sum
   %26         # sum % 26
ica            # index into ca using the result
\$\endgroup\$
2
\$\begingroup\$

C (gcc), 46

t;f(char*s){for(t=0;*s;)t+=*s++-97;t=t%26+97;}

Try it online!

\$\endgroup\$
3
  • 1
    \$\begingroup\$ 41 \$\endgroup\$
    – AZTECCO
    Oct 22, 2022 at 12:50
  • \$\begingroup\$ You can save one more by changing char to int. \$\endgroup\$
    – naffetS
    Oct 22, 2022 at 18:18
  • \$\begingroup\$ 40 bytes \$\endgroup\$
    – jdt
    Nov 2, 2022 at 13:32
2
\$\begingroup\$

ARM Thumb machine code, 18 bytes

61 20 04 c9 61 3a 10 44 fb d5 1a 38 fd d2 7b 30
70 47

Assembler source:

    .syntax unified
    .arch armv7-a
    .thumb
    .globl alpha_checksum
    .thumb_func
    // Input: r1: null terminated UTF-32LE string
    // Output: r0
    // Clobbers: r0-r2
alpha_checksum:
    // Initial accumulator. Start at 'a' to cancel the checksum
    // loop adding '\0' - 'a' when the null terminator is reached.
    movs   r0, #'a'
.Lloop:
    // Load character, increment pointer
    ldmia  r1!, {r2}
    // Subtract 'a' to convert to a number, set flags
    // In the case of the null terminator, this will result in
    // -'a', which ends the loop condition below.
    subs   r2, #'a'
    // Add to the checksum, without setting the flags
    add    r0, r2
    // Loop if the subs didn't return negative,
    // which happens only with the null terminator.
    bpl    .Lloop
.Lend:
    // Calculate (checksum % 26) - 26 using a naive subtraction loop
.Lmodulo:
    // Subtract 26
    subs   r0, #26
    // Loop while it was >= 26
    bhs    .Lmodulo
    // Add 26 to correct the modulo, and 'a' to convert to ASCII.
    adds   r0, #'a' + 26
    // Return
    bx     lr

This can be called from C using a dummy parameter to place ptr in r1.

ptr is expected to be a pointer to a null terminated UTF-32LE string.

char32_t alpha_checksum(int dummy, const char32_t *ptr);
\$\endgroup\$
4
  • 1
    \$\begingroup\$ I was curious how much it saves to take UTF32 / wchar_t input: The ldmia is only 2 bytes (04 c9), but a 11 f8 01 2b ldrb r2, [r1], #1 post-increment byte load is 4 bytes. So a char* version would be 2 bytes longer. Passing a length as another arg would also cost extra bytes, since an implicit-length C string allows folding the check into a subs we're already doing. And there's no [R1, R2] addressing mode with pre-decrement of one register. \$\endgroup\$ Oct 22, 2022 at 8:30
  • 1
    \$\begingroup\$ Not that it matters for code size, but I think it would be more idiomatic to use bge or bhs to keep looping while the input character was >= 'a' (signed or unsigned), rather than branching on the sign of the subtraction result. bpl is different from bge if there's signed overflow. In this case you could think about it as doing a (potentially signed-wrapping) subtraction and then checking the sign of the result, but it seems like a bad habit vs. using the flags result of subs like it was a cmp. Probably not worth editing the answer to change, though. Nice one. \$\endgroup\$ Oct 22, 2022 at 8:47
  • 1
    \$\begingroup\$ Yeah I could also do bge or bhs, I chose bpl because I was emphasizing the fact that it will end up adding a negative. \$\endgroup\$
    – EasyasPi
    Oct 22, 2022 at 13:34
  • \$\begingroup\$ Oh that makes sense, good point. \$\endgroup\$ Oct 22, 2022 at 13:35
2
\$\begingroup\$

Clojure, 65 bytes

(defn a[s](char(+(mod(apply + (map #(- % 97)(map int s)))26)97)))

Try it online!

Ungolfed:

(defn alpha-checksum [s]
  (char (+ (mod (apply + (map #(- % 97) (map int s))) 26) 97)))
\$\endgroup\$
3
  • \$\begingroup\$ You can remove the space in + ( for -1, and you can use fn instead of defn a (using an anonymous function) to save another 4, and then combine the two map statements to save a bunch more - TIO \$\endgroup\$
    – naffetS
    Oct 22, 2022 at 18:14
  • \$\begingroup\$ And off of that, you can save one more byte by using a # lambda for the outer function and fn on the inner one (which allows removing a whitespace): Try it online! \$\endgroup\$
    – naffetS
    Oct 22, 2022 at 18:17
  • \$\begingroup\$ And off of that (sorry lol), you can save one more byte using a trick from the other answers (changing -97 to +7): Try it online! \$\endgroup\$
    – naffetS
    Oct 22, 2022 at 18:19
2
\$\begingroup\$

Wren, 47 bytes

Fn.new{|s|(s.bytes.reduce{|x,y|x+7+y}+7)%26+97}

Try it online!

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

Charcoal, 8 bytes

§βΣES⌕βι

Try it online! Link is to verbose version of code. Explanation:

    S       Input string
   E        Map over characters
       ι    Current character
     ⌕      Find index in
      β     Predefined variable lowercase alphabet
  Σ         Take the sum
§           Cyclically indexed into
 β          Predefined variable lowercase alphabet
            Implicitly print
\$\endgroup\$
2
\$\begingroup\$

Retina 0.8.2, 25 bytes

0T1>`l`L
+T`l__L`zlL_`^..

Try it online! Link includes test cases. Explanation:

0T1>`l`L

Uppercase all letters after the first.

+T`l__L`zlL_`^..

While there are at least two letters, repeatedly rotate the first letter backwards and the second letter forwards in the alphabet, however the first letter rotates back from a to z while the second letter drops off when it passes Z, allowing subsequent letters to be processed.

The l and L in the patters expand to the lowercase and uppercase alphabet respectively. The _ in the source pattern is just a placeholder to allow the use of l and L in the destination pattern, while in the destination pattern it indicates that the character is to be deleted.

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

Pip, 20 bytes

C(($+(7+A*a))%26+97)

Try It Online!

Probably could be shorter, I feel like there are just way too many parentheses.

\$\endgroup\$
2
  • \$\begingroup\$ Hint: The preset variable z should be quite useful here. \$\endgroup\$
    – DLosc
    Oct 22, 2022 at 4:02
  • \$\begingroup\$ @DLosc I literally tried that and it came out longer, I must be doing something horribly wrong \$\endgroup\$
    – Aiden Chow
    Oct 22, 2022 at 5:02
2
\$\begingroup\$

BQN, 15 bytes

'a'+26|·+´-⟜'a'

Try it at BQN REPL

'a'+26|·+´-⟜'a'
          -⟜'a'     # subtract 'a' from each letter of input
        +´          # sum
       ·            # (no-op to preserve train syntax)
    26|             # modulo 26
'a'+                # add 'a'
\$\endgroup\$
2
\$\begingroup\$

Gema, 77 characters

?=@set{s;@add{${s;};@add{@char-int{?};7}}}
\Z=@int-char{@add{@mod{$s;26};97}}

(Yepp. Arithmetic operations are a pain in Gema.)

Sample run:

bash-5.1$ echo -n helloworld | gema '?=@set{s;@add{${s;};@add{@char-int{?};7}}};\Z=@int-char{@add{@mod{$s;26};97}}'
k

Try it online!

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

JavaScript (V8), 72 bytes

([...s])=>String.fromCharCode(s.map(c=>t+=c.charCodeAt()+7,t=0)|t%26+97)

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Any idea how to get this working also for inputs of size 1 without additional bytes? \$\endgroup\$ Oct 25, 2022 at 21:21
2
\$\begingroup\$

PowerShell, 54 bytes

$s.tochararray()|%{$r+=([char]$_)-97};[char]($r%26+97)

Try it online!

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

Pip, 16 bytes

zPK$+(A*a-97)%26

Try It Online!

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

x86‑64 assembly machine code, 30 B

input

  • unsigned length of string in 64‑bit register rdi
  • address of string buffer in 64‑bit register rsi

code listing

 1                 alphabet_checksum:
 2 0000 6A61        push 'a'                    ; push(97)
 3 0002 58          pop rax                     ; pop(rax)
 4 0003 F7E7        mul edi                     ; edx○eax ≔ eax × edi
 5                  
 6 0005 F7D8        neg eax                     ; eax ≔ −eax; CF ≔ eax ≠ 0
 7 0007 7310        jnc .adjust                 ; if ¬CF then goto adjust
 8                 .sum:
 9 0009 0FB64C3EFF  movzx ecx, byte [rsi+rdi-1] ; ecx ≔ (rsi + rdi − 1)↑
10 000E 01C8        add eax, ecx                ; eax ≔ eax + ecx
11 0010 FFCF        dec edi                     ; edi ≔ edi − 1; ZF ≔ edi = 0
12 0012 75F5        jnz .sum                    ; if ¬ZF then goto sum
13                  
14 0014 6A1A        push 26                     ; push(26)
15 0016 5F          pop rdi                     ; pop(rdi)
16 0017 F7F7        div edi                     ; edx ≔ edx○eax mod edi
17                 .adjust:
18 0019 92          xchg eax, edx               ; eax ≔ edx
19 001A 83C061      add eax, 'a'                ; eax ≔ eax + 97
20 001D C3          ret

output

  • alphabet checksum as ASCII character in 64‑bit register rax

limitations

  • length of string must be ≤ 44,278,013, else the mul spills into edx, yet the algorithm relies on edx being 0 in the case of a zero-length string
\$\endgroup\$
3
  • \$\begingroup\$ So isn't that just 31 bytes (\$2^5 - 1 = 31\$)? \$\endgroup\$
    – The Thonnu
    Oct 22, 2022 at 20:25
  • \$\begingroup\$ What about multiplying edi with -97? Later use cdq to clean edx, with half but still enough range \$\endgroup\$
    – l4m2
    Jan 15, 2023 at 7:31
  • \$\begingroup\$ Also imul eax, edi, -97 is only 3 byte \$\endgroup\$
    – l4m2
    Jan 15, 2023 at 7:34
2
\$\begingroup\$

Haskell, 43 bytes

f s=['a'..]!!mod(sum[fromEnum c-97|c<-s])26

Try it online!

Same-length alternative:

f s=['a'..]!!mod(sum$do c<-s;1<$['b'..c])26

Try it online!

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

Knight (v2), 36 bytes

;=sP;=i@O;Ws;=i+~-97iAs=s]sA+97%i 26

Try it online!

I feel like you can golf better but i tried for awhile and gave up

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

><> (Fish), 26 24 bytes

  • -2 bytes thanks to @Eminga. I didn't want to change the input mode to stack though so I didn't use all the golfing potential. Also I wanted to exit properly and not just error.
0i:0(?v+7+2d*%!
o+"a"~<;

Animated Version

Explanation:

0

Push 0, the starting value

i:0(?v

Check if the input is negative, if so go down.

+7+2d*%

Add 7+the input to the accumulator, then mod 26

!

Skip the 0 the second time, since the accumulator is already set

~"a"+o;

(Reversed in the program) Print "a" + the accumulator.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ You can save 7 bytes by adding 7 to each char code and summing them before modding by 26. \$\endgroup\$
    – Emigna
    Nov 9, 2022 at 13:04
2
\$\begingroup\$

Uiua, 11 bytes

+@a◿26/+-@a

Try it!

+@a◿26/+-@a
        -@a  # convert string to code points
      /+     # sum
   ◿26       # modulo 26
+@a          # add the letter a
\$\endgroup\$
1
  • 1
    \$\begingroup\$ The +@a ... -@a bugs me... it's quite annoying that ⍜'-@a(◿26/+) is a byte longer... \$\endgroup\$ Oct 19, 2023 at 22:40
1
\$\begingroup\$

C++ (gcc), 76 73 bytes

-3 thanks to @ceilingcat

I think this is as much golf as you can get without using a completely different method. Other people will probably prove me wrong the moment I hit "Post." have in fact proven me wrong.

#import<ios>
int f(char*s){int t=0;for(;*s;t+=*s++-97);putchar(t%26+97);}

Try it online!

Ungolfed

We used #import<ios> so we can putchar().

int f(char* s) {
    int t = 0;                      // Running total
    for(;*s != 0;t += *s++ - 97);   // Loop through string until we get to null byte, add to running total
    putchar(t % 26 + 97);           // Add 97 to final result and print
}
\$\endgroup\$
0
1
\$\begingroup\$

Arturo, 29 bytes

$[a][+97(sum map a=>[+7])%26]

Try it

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

brainfuck, 91 bytes

++[++[->+>+<<]>>[--<<+>>]<],[[-[->+<]>]>>>>>>>,]+[<<<<<<<<<<<<<<<<<<<<<<<<<<+<[-----.[>]]>]

Try it online!

++[++[->+>+<<]>>[--<<+>>]<]    Init memory with 1,2,3,...,127
,[[-[->+<]>]>>>>>>>,]          Reading each byte, move right that many steps
+[<<<<<<<<<<<<<<<<<<<<<<<<<<+< Go left 26 and check if empty
[-----.[>]]>]                  If not empty, give shift, output and halt
\$\endgroup\$
1
\$\begingroup\$

Dyalog APL v18, 28 bytes*

{a[1+26|+/1-⍨(a←¯1∘⎕C⎕A)⍳⍵]}

Assuming that indices start from one (⎕IO←1).

________________
*: APL can be written in its own legacy charset (defined by ⎕AV) instead of Unicode; therefore an APL program that only uses ASCII characters and APL symbols can be scored as 1 char = 1 byte.

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

Thunno 2, 6 bytes

Ä⁻S⁺ÄL

Try it online!

Explanation

Ä⁻S⁺ÄL  # Implicit input
Ä       # 1-based index in alphabet
 ⁻      # Decrement to make 0-indexed
  S     # Sum the resulting list
   ⁺    # Increment for 1-indexing
    Ä   # 1-based convert to letter
     L  # Lowercase it
        # 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.