Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

rot13.gno

1.67 Kb · 50 lines
 1// Package rot13 ports Go's classic ROT13 example — the one used to teach
 2// strings.Map and io.Reader in the standard library docs — to gno as a reusable
 3// pure package. The core is a pure letter-rotation cipher over ASCII: ROT13
 4// shifts each letter 13 places, which (since the alphabet has 26 letters)
 5// makes ROT13 its own inverse. Caesar generalizes it to any shift.
 6//
 7// Everything here is pure strings/unicode logic: no state, no randomness,
 8// no clock.
 9//
10// A live demo of this package is at
11// [r/moul/x/daily/rot13demo](/r/nym-moultest123/x/daily/rot13demo/v0).
12package rot13
13
14import "strings"
15
16// Rot13 applies the ROT13 substitution cipher, rotating ASCII letters by 13
17// and leaving every other byte untouched. Because 13 is half of 26,
18// Rot13(Rot13(s)) == s — the cipher is its own inverse. This mirrors the
19// canonical strings.Map example from the Go docs.
20func Rot13(s string) string {
21	return strings.Map(rot13Rune, s)
22}
23
24// rot13Rune is the mapping function handed to strings.Map — the heart of the
25// classic example.
26func rot13Rune(r rune) rune {
27	switch {
28	case r >= 'a' && r <= 'z':
29		return 'a' + (r-'a'+13)%26
30	case r >= 'A' && r <= 'Z':
31		return 'A' + (r-'A'+13)%26
32	}
33	return r
34}
35
36// Caesar generalizes ROT13 to an arbitrary shift. Negative and large shifts
37// are normalized into [0,26). Only ASCII letters move; anything else passes
38// through unchanged. Caesar(s, 13) is exactly Rot13(s).
39func Caesar(s string, shift int) string {
40	sh := rune(((shift % 26) + 26) % 26)
41	return strings.Map(func(r rune) rune {
42		switch {
43		case r >= 'a' && r <= 'z':
44			return 'a' + (r-'a'+sh)%26
45		case r >= 'A' && r <= 'Z':
46			return 'A' + (r-'A'+sh)%26
47		}
48		return r
49	}, s)
50}