1// Package rot13 ports Go's classic ROT13 example — the one used to teach2// strings.Map and io.Reader in the standard library docs — to gno as a reusable3// pure package. The core is a pure letter-rotation cipher over ASCII: ROT134// 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 at11// [r/moul/x/daily/rot13demo](/r/moul/x/daily/rot13demo/v0).12package rot131314import "strings"1516// Rot13 applies the ROT13 substitution cipher, rotating ASCII letters by 1317// 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 the19// canonical strings.Map example from the Go docs.20func Rot13(s string) string {21 return strings.Map(rot13Rune, s)22}2324// rot13Rune is the mapping function handed to strings.Map — the heart of the25// classic example.26func rot13Rune(r rune) rune {27 switch {28 case r >= 'a' && r <= 'z':29 return 'a' + (r-'a'+13)%2630 case r >= 'A' && r <= 'Z':31 return 'A' + (r-'A'+13)%2632 }33 return r34}3536// Caesar generalizes ROT13 to an arbitrary shift. Negative and large shifts37// are normalized into [0,26). Only ASCII letters move; anything else passes38// 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)%2645 case r >= 'A' && r <= 'Z':46 return 'A' + (r-'A'+sh)%2647 }48 return r49 }, s)50}51Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.